Sergey Pastor / 1

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lpc178x_eth.c Source File

lpc178x_eth.c

Go to the documentation of this file.
00001 /**
00002  * @file lpc178x_eth.c
00003  * @brief LPC1786/88 Ethernet MAC controller
00004  *
00005  * @section License
00006  *
00007  * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
00008  *
00009  * This file is part of CycloneTCP Open.
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software Foundation,
00023  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00024  *
00025  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00026  * @version 1.7.6
00027  **/
00028 
00029 //Switch to the appropriate trace level
00030 #define TRACE_LEVEL NIC_TRACE_LEVEL
00031 
00032 //Dependencies
00033 #include "lpc177x_8x.h"
00034 #include "core/net.h"
00035 #include "drivers/lpc178x_eth.h"
00036 #include "debug.h"
00037 
00038 //Underlying network interface
00039 static NetInterface *nicDriverInterface;
00040 
00041 //IAR EWARM compiler?
00042 #if defined(__ICCARM__)
00043 
00044 //Transmit buffer
00045 #pragma data_alignment = 4
00046 static uint8_t txBuffer[LPC178X_ETH_TX_BUFFER_COUNT][LPC178X_ETH_TX_BUFFER_SIZE];
00047 //Receive buffer
00048 #pragma data_alignment = 4
00049 static uint8_t rxBuffer[LPC178X_ETH_RX_BUFFER_COUNT][LPC178X_ETH_RX_BUFFER_SIZE];
00050 //Transmit descriptors
00051 #pragma data_alignment = 4
00052 static Lpc178xTxDesc txDesc[LPC178X_ETH_TX_BUFFER_COUNT];
00053 //Transmit status array
00054 #pragma data_alignment = 4
00055 static Lpc178xTxStatus txStatus[LPC178X_ETH_TX_BUFFER_COUNT];
00056 //Receive descriptors
00057 #pragma data_alignment = 4
00058 static Lpc178xRxDesc rxDesc[LPC178X_ETH_RX_BUFFER_COUNT];
00059 //Receive status array
00060 #pragma data_alignment = 8
00061 static Lpc178xRxStatus rxStatus[LPC178X_ETH_RX_BUFFER_COUNT];
00062 
00063 //Keil MDK-ARM or GCC compiler?
00064 #else
00065 
00066 //Transmit buffer
00067 static uint8_t txBuffer[LPC178X_ETH_TX_BUFFER_COUNT][LPC178X_ETH_TX_BUFFER_SIZE]
00068    __attribute__((aligned(4)));
00069 //Receive buffer
00070 static uint8_t rxBuffer[LPC178X_ETH_RX_BUFFER_COUNT][LPC178X_ETH_RX_BUFFER_SIZE]
00071    __attribute__((aligned(4)));
00072 //Transmit descriptors
00073 static Lpc178xTxDesc txDesc[LPC178X_ETH_TX_BUFFER_COUNT]
00074    __attribute__((aligned(4)));
00075 //Transmit status array
00076 static Lpc178xTxStatus txStatus[LPC178X_ETH_TX_BUFFER_COUNT]
00077    __attribute__((aligned(4)));
00078 //Receive descriptors
00079 static Lpc178xRxDesc rxDesc[LPC178X_ETH_RX_BUFFER_COUNT]
00080    __attribute__((aligned(4)));
00081 //Receive status array
00082 static Lpc178xRxStatus rxStatus[LPC178X_ETH_RX_BUFFER_COUNT]
00083    __attribute__((aligned(8)));
00084 
00085 #endif
00086 
00087 
00088 /**
00089  * @brief LPC178x Ethernet MAC driver
00090  **/
00091 
00092 const NicDriver lpc178xEthDriver =
00093 {
00094    NIC_TYPE_ETHERNET,
00095    ETH_MTU,
00096    lpc178xEthInit,
00097    lpc178xEthTick,
00098    lpc178xEthEnableIrq,
00099    lpc178xEthDisableIrq,
00100    lpc178xEthEventHandler,
00101    lpc178xEthSendPacket,
00102    lpc178xEthSetMulticastFilter,
00103    lpc178xEthUpdateMacConfig,
00104    lpc178xEthWritePhyReg,
00105    lpc178xEthReadPhyReg,
00106    TRUE,
00107    TRUE,
00108    TRUE,
00109    FALSE
00110 };
00111 
00112 
00113 /**
00114  * @brief LPC178x Ethernet MAC initialization
00115  * @param[in] interface Underlying network interface
00116  * @return Error code
00117  **/
00118 
00119 error_t lpc178xEthInit(NetInterface *interface)
00120 {
00121    error_t error;
00122 
00123    //Debug message
00124    TRACE_INFO("Initializing LPC178x Ethernet MAC...\r\n");
00125 
00126    //Save underlying network interface
00127    nicDriverInterface = interface;
00128 
00129    //Power up EMAC controller
00130    LPC_SC->PCONP |= PCONP_PCENET;
00131 
00132    //GPIO configuration
00133    lpc178xEthInitGpio(interface);
00134 
00135    //Reset host registers, transmit datapath and receive datapath
00136    LPC_EMAC->Command = COMMAND_RX_RESET | COMMAND_TX_RESET | COMMAND_REG_RESET;
00137 
00138    //Reset EMAC controller
00139    LPC_EMAC->MAC1 = MAC1_SOFT_RESET | MAC1_SIMULATION_RESET |
00140       MAC1_RESET_MCS_RX | MAC1_RESET_RX | MAC1_RESET_MCS_TX | MAC1_RESET_TX;
00141 
00142    //Initialize MAC related registers
00143    LPC_EMAC->MAC1 = 0;
00144    LPC_EMAC->MAC2 = MAC2_PAD_CRC_ENABLE | MAC2_CRC_ENABLE;
00145    LPC_EMAC->IPGR = IPGR_DEFAULT_VALUE;
00146    LPC_EMAC->CLRT = CLRT_DEFAULT_VALUE;
00147 
00148    //Select RMII mode
00149    LPC_EMAC->Command = COMMAND_RMII;
00150 
00151    //Configure MDC clock
00152    LPC_EMAC->MCFG = MCFG_CLOCK_SELECT_DIV48;
00153    //Reset MII management interface
00154    LPC_EMAC->MCFG |= MCFG_RESET_MII_MGMT;
00155    LPC_EMAC->MCFG &= ~MCFG_RESET_MII_MGMT;
00156 
00157    //PHY transceiver initialization
00158    error = interface->phyDriver->init(interface);
00159    //Failed to initialize PHY transceiver?
00160    if(error)
00161       return error;
00162 
00163    //Initialize TX and RX descriptor arrays
00164    lpc178xEthInitDesc(interface);
00165 
00166    //Set the MAC address
00167    LPC_EMAC->SA0 = interface->macAddr.w[2];
00168    LPC_EMAC->SA1 = interface->macAddr.w[1];
00169    LPC_EMAC->SA2 = interface->macAddr.w[0];
00170 
00171    //Initialize hash table
00172    LPC_EMAC->HashFilterL = 0;
00173    LPC_EMAC->HashFilterH = 0;
00174 
00175    //Configure the receive filter
00176    LPC_EMAC->RxFilterCtrl = RFC_ACCEPT_PERFECT_EN |
00177       RFC_ACCEPT_MULTICAST_HASH_EN | RFC_ACCEPT_BROADCAST_EN;
00178 
00179    //Program the MAXF register with the maximum frame length to be accepted
00180    LPC_EMAC->MAXF = 1518;
00181 
00182    //Reset EMAC interrupt flags
00183    LPC_EMAC->IntClear  = 0xFFFF;
00184    //Enable desired EMAC interrupts
00185    LPC_EMAC->IntEnable = INT_TX_DONE | INT_RX_DONE;
00186 
00187    //Set priority grouping (5 bits for pre-emption priority, no bits for subpriority)
00188    NVIC_SetPriorityGrouping(LPC178X_ETH_IRQ_PRIORITY_GROUPING);
00189 
00190    //Configure Ethernet interrupt priority
00191    NVIC_SetPriority(ENET_IRQn, NVIC_EncodePriority(LPC178X_ETH_IRQ_PRIORITY_GROUPING,
00192       LPC178X_ETH_IRQ_GROUP_PRIORITY, LPC178X_ETH_IRQ_SUB_PRIORITY));
00193 
00194    //Enable transmission and reception
00195    LPC_EMAC->Command |= COMMAND_TX_ENABLE | COMMAND_RX_ENABLE;
00196    //Allow frames to be received
00197    LPC_EMAC->MAC1 |= MAC1_RECEIVE_ENABLE;
00198 
00199    //Accept any packets from the upper layer
00200    osSetEvent(&interface->nicTxEvent);
00201 
00202    //Successful initialization
00203    return NO_ERROR;
00204 }
00205 
00206 
00207 //LPC1788-32 Developer's Kit?
00208 #if defined(USE_LPC1788_32_DEV_KIT)
00209 
00210 /**
00211  * @brief GPIO configuration
00212  * @param[in] interface Underlying network interface
00213  **/
00214 
00215 void lpc178xEthInitGpio(NetInterface *interface)
00216 {
00217    //Power up GPIO
00218    LPC_SC->PCONP |= PCONP_PCGPIO;
00219 
00220    //Configure P1.0 (ENET_TXD0)
00221    LPC_IOCON->P1_0 = IOCON_SLEW | IOCON_FUNC_1;
00222    //Configure P1.1 (ENET_TXD1)
00223    LPC_IOCON->P1_1 = IOCON_SLEW | IOCON_FUNC_1;
00224    //Configure P1.4 (ENET_TX_EN)
00225    LPC_IOCON->P1_4 = IOCON_SLEW | IOCON_FUNC_1;
00226    //Configure P1.8 (ENET_CRS)
00227    LPC_IOCON->P1_8 = IOCON_SLEW | IOCON_FUNC_1;
00228    //Configure P1.9 (ENET_RXD0)
00229    LPC_IOCON->P1_9 = IOCON_SLEW | IOCON_FUNC_1;
00230    //Configure P1.10 (ENET_RXD1)
00231    LPC_IOCON->P1_10 = IOCON_SLEW | IOCON_FUNC_1;
00232    //Configure P1.14 (RX_ER)
00233    LPC_IOCON->P1_14 = IOCON_SLEW | IOCON_FUNC_1;
00234    //Configure P1.15 (ENET_REF_CLK)
00235    LPC_IOCON->P1_15 = IOCON_SLEW | IOCON_FUNC_1;
00236    //Configure P1.16 (ENET_MDC)
00237    LPC_IOCON->P1_16 = IOCON_MODE_PULL_UP | IOCON_FUNC_1;
00238    //Configure P1.17 (ENET_MDIO)
00239    LPC_IOCON->P1_17 = IOCON_MODE_PULL_UP | IOCON_FUNC_1;
00240 }
00241 
00242 #endif
00243 
00244 
00245 /**
00246  * @brief Initialize TX and RX descriptors
00247  * @param[in] interface Underlying network interface
00248  **/
00249 
00250 void lpc178xEthInitDesc(NetInterface *interface)
00251 {
00252    uint_t i;
00253 
00254    //Initialize TX descriptors
00255    for(i = 0; i < LPC178X_ETH_TX_BUFFER_COUNT; i++)
00256    {
00257       //Base address of the buffer containing transmit data
00258       txDesc[i].packet = (uint32_t) txBuffer[i];
00259       //Transmit descriptor control word
00260       txDesc[i].control = 0;
00261       //Transmit status information word
00262       txStatus[i].info = 0;
00263    }
00264 
00265    //Initialize RX descriptors
00266    for(i = 0; i < LPC178X_ETH_RX_BUFFER_COUNT; i++)
00267    {
00268       //Base address of the buffer for storing receive data
00269       rxDesc[i].packet = (uint32_t) rxBuffer[i];
00270       //Receive descriptor control word
00271       rxDesc[i].control = RX_CTRL_INTERRUPT | (LPC178X_ETH_RX_BUFFER_SIZE - 1);
00272       //Receive status information word
00273       rxStatus[i].info = 0;
00274       //Receive status HashCRC word
00275       rxStatus[i].hashCrc = 0;
00276    }
00277 
00278    //Initialize EMAC transmit descriptor registers
00279    LPC_EMAC->TxDescriptor = (uint32_t) txDesc;
00280    LPC_EMAC->TxStatus = (uint32_t) txStatus;
00281    LPC_EMAC->TxDescriptorNumber = LPC178X_ETH_TX_BUFFER_COUNT - 1;
00282    LPC_EMAC->TxProduceIndex = 0;
00283 
00284    //Initialize EMAC receive descriptor registers
00285    LPC_EMAC->RxDescriptor = (uint32_t) rxDesc;
00286    LPC_EMAC->RxStatus = (uint32_t) rxStatus;
00287    LPC_EMAC->RxDescriptorNumber = LPC178X_ETH_RX_BUFFER_COUNT - 1;
00288    LPC_EMAC->RxConsumeIndex = 0;
00289 }
00290 
00291 
00292 /**
00293  * @brief LPC178x Ethernet MAC timer handler
00294  *
00295  * This routine is periodically called by the TCP/IP stack to
00296  * handle periodic operations such as polling the link state
00297  *
00298  * @param[in] interface Underlying network interface
00299  **/
00300 
00301 void lpc178xEthTick(NetInterface *interface)
00302 {
00303    //Handle periodic operations
00304    interface->phyDriver->tick(interface);
00305 }
00306 
00307 
00308 /**
00309  * @brief Enable interrupts
00310  * @param[in] interface Underlying network interface
00311  **/
00312 
00313 void lpc178xEthEnableIrq(NetInterface *interface)
00314 {
00315    //Enable Ethernet MAC interrupts
00316    NVIC_EnableIRQ(ENET_IRQn);
00317    //Enable Ethernet PHY interrupts
00318    interface->phyDriver->enableIrq(interface);
00319 }
00320 
00321 
00322 /**
00323  * @brief Disable interrupts
00324  * @param[in] interface Underlying network interface
00325  **/
00326 
00327 void lpc178xEthDisableIrq(NetInterface *interface)
00328 {
00329    //Disable Ethernet MAC interrupts
00330    NVIC_DisableIRQ(ENET_IRQn);
00331    //Disable Ethernet PHY interrupts
00332    interface->phyDriver->disableIrq(interface);
00333 }
00334 
00335 
00336 /**
00337  * @brief LPC178x Ethernet MAC interrupt service routine
00338  **/
00339 
00340 void ENET_IRQHandler(void)
00341 {
00342    uint_t i;
00343    bool_t flag;
00344    uint32_t status;
00345 
00346    //Enter interrupt service routine
00347    osEnterIsr();
00348 
00349    //This flag will be set if a higher priority task must be woken
00350    flag = FALSE;
00351 
00352    //Read interrupt status register
00353    status = LPC_EMAC->IntStatus;
00354 
00355    //A packet has been transmitted?
00356    if(status & INT_TX_DONE)
00357    {
00358       //Clear TxDone interrupt flag
00359       LPC_EMAC->IntClear = INT_TX_DONE;
00360 
00361       //Get the index of the next descriptor
00362       i = LPC_EMAC->TxProduceIndex + 1;
00363 
00364       //Wrap around if necessary
00365       if(i >= LPC178X_ETH_TX_BUFFER_COUNT)
00366          i = 0;
00367 
00368       //Check whether the TX buffer is available for writing
00369       if(i != LPC_EMAC->TxConsumeIndex)
00370       {
00371          //Notify the TCP/IP stack that the transmitter is ready to send
00372          flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
00373       }
00374    }
00375 
00376    //A packet has been received?
00377    if(status & INT_RX_DONE)
00378    {
00379       //Disable RxDone interrupts
00380       LPC_EMAC->IntEnable &= ~INT_RX_DONE;
00381 
00382       //Set event flag
00383       nicDriverInterface->nicEvent = TRUE;
00384       //Notify the TCP/IP stack of the event
00385       flag |= osSetEventFromIsr(&netEvent);
00386    }
00387 
00388    //Leave interrupt service routine
00389    osExitIsr(flag);
00390 }
00391 
00392 
00393 /**
00394  * @brief LPC178x Ethernet MAC event handler
00395  * @param[in] interface Underlying network interface
00396  **/
00397 
00398 void lpc178xEthEventHandler(NetInterface *interface)
00399 {
00400    error_t error;
00401 
00402    //Packet received?
00403    if(LPC_EMAC->IntStatus & INT_RX_DONE)
00404    {
00405       //Clear RxDone interrupt flag
00406       LPC_EMAC->IntClear = INT_RX_DONE;
00407 
00408       //Process all pending packets
00409       do
00410       {
00411          //Read incoming packet
00412          error = lpc178xEthReceivePacket(interface);
00413 
00414          //No more data in the receive buffer?
00415       } while(error != ERROR_BUFFER_EMPTY);
00416    }
00417 
00418    //Re-enable TxDone and RxDone interrupts
00419    LPC_EMAC->IntEnable = INT_TX_DONE | INT_RX_DONE;
00420 }
00421 
00422 
00423 /**
00424  * @brief Send a packet
00425  * @param[in] interface Underlying network interface
00426  * @param[in] buffer Multi-part buffer containing the data to send
00427  * @param[in] offset Offset to the first data byte
00428  * @return Error code
00429  **/
00430 
00431 error_t lpc178xEthSendPacket(NetInterface *interface,
00432    const NetBuffer *buffer, size_t offset)
00433 {
00434    uint_t i;
00435    uint_t j;
00436    size_t length;
00437 
00438    //Retrieve the length of the packet
00439    length = netBufferGetLength(buffer) - offset;
00440 
00441    //Check the frame length
00442    if(!length)
00443    {
00444       //The transmitter can accept another packet
00445       osSetEvent(&interface->nicTxEvent);
00446       //We are done since the buffer is empty
00447       return NO_ERROR;
00448    }
00449    else if(length > LPC178X_ETH_TX_BUFFER_SIZE)
00450    {
00451       //The transmitter can accept another packet
00452       osSetEvent(&interface->nicTxEvent);
00453       //Report an error
00454       return ERROR_INVALID_LENGTH;
00455    }
00456 
00457    //Get the index of the current descriptor
00458    i = LPC_EMAC->TxProduceIndex;
00459    //Get the index of the next descriptor
00460    j = i + 1;
00461 
00462    //Wrap around if necessary
00463    if(j >= LPC178X_ETH_TX_BUFFER_COUNT)
00464       j = 0;
00465 
00466    //Check whether the transmit descriptor array is full
00467    if(j == LPC_EMAC->TxConsumeIndex)
00468       return ERROR_FAILURE;
00469 
00470    //Copy user data to the transmit buffer
00471    netBufferRead((uint8_t *) txDesc[i].packet, buffer, offset, length);
00472 
00473    //Write the transmit control word
00474    txDesc[i].control = TX_CTRL_INTERRUPT | TX_CTRL_LAST |
00475       TX_CTRL_CRC | TX_CTRL_PAD | ((length - 1) & TX_CTRL_SIZE);
00476 
00477    //Increment index and wrap around if necessary
00478    if(++i >= LPC178X_ETH_TX_BUFFER_COUNT)
00479       i = 0;
00480 
00481    //Save the resulting value
00482    LPC_EMAC->TxProduceIndex = i;
00483 
00484    //Get the index of the next descriptor
00485    j = i + 1;
00486 
00487    //Wrap around if necessary
00488    if(j >= LPC178X_ETH_TX_BUFFER_COUNT)
00489       j = 0;
00490 
00491    //Check whether the next buffer is available for writing
00492    if(j != LPC_EMAC->TxConsumeIndex)
00493    {
00494       //The transmitter can accept another packet
00495       osSetEvent(&interface->nicTxEvent);
00496    }
00497 
00498    //Successful write operation
00499    return NO_ERROR;
00500 }
00501 
00502 
00503 /**
00504  * @brief Receive a packet
00505  * @param[in] interface Underlying network interface
00506  * @return Error code
00507  **/
00508 
00509 error_t lpc178xEthReceivePacket(NetInterface *interface)
00510 {
00511    error_t error;
00512    size_t n;
00513    uint_t i;
00514 
00515    //Point to the current descriptor
00516    i = LPC_EMAC->RxConsumeIndex;
00517 
00518    //Make sure the current buffer is available for reading
00519    if(i != LPC_EMAC->RxProduceIndex)
00520    {
00521       //Retrieve the length of the frame
00522       n = (rxStatus[i].info & RX_STATUS_SIZE) + 1;
00523       //Limit the number of data to read
00524       n = MIN(n, LPC178X_ETH_RX_BUFFER_SIZE);
00525 
00526       //Pass the packet to the upper layer
00527       nicProcessPacket(interface, (uint8_t *) rxDesc[i].packet, n);
00528 
00529       //Increment index and wrap around if necessary
00530       if(++i >= LPC178X_ETH_RX_BUFFER_COUNT)
00531          i = 0;
00532 
00533       //Save the resulting value
00534       LPC_EMAC->RxConsumeIndex = i;
00535 
00536       //Valid packet received
00537       error = NO_ERROR;
00538    }
00539    else
00540    {
00541       //No more data in the receive buffer
00542       error = ERROR_BUFFER_EMPTY;
00543    }
00544 
00545    //Return status code
00546    return error;
00547 }
00548 
00549 
00550 /**
00551  * @brief Configure multicast MAC address filtering
00552  * @param[in] interface Underlying network interface
00553  * @return Error code
00554  **/
00555 
00556 error_t lpc178xEthSetMulticastFilter(NetInterface *interface)
00557 {
00558    uint_t i;
00559    uint_t k;
00560    uint32_t crc;
00561    uint32_t hashTable[2];
00562    MacFilterEntry *entry;
00563 
00564    //Debug message
00565    TRACE_DEBUG("Updating LPC178x hash table...\r\n");
00566 
00567    //Clear hash table
00568    hashTable[0] = 0;
00569    hashTable[1] = 0;
00570 
00571    //The MAC filter table contains the multicast MAC addresses
00572    //to accept when receiving an Ethernet frame
00573    for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++)
00574    {
00575       //Point to the current entry
00576       entry = &interface->macMulticastFilter[i];
00577 
00578       //Valid entry?
00579       if(entry->refCount > 0)
00580       {
00581          //Compute CRC over the current MAC address
00582          crc = lpc178xEthCalcCrc(&entry->addr, sizeof(MacAddr));
00583          //Bits [28:23] are used to form the hash
00584          k = (crc >> 23) & 0x3F;
00585          //Update hash table contents
00586          hashTable[k / 32] |= (1 << (k % 32));
00587       }
00588    }
00589 
00590    //Write the hash table
00591    LPC_EMAC->HashFilterL = hashTable[0];
00592    LPC_EMAC->HashFilterH = hashTable[1];
00593 
00594    //Debug message
00595    TRACE_DEBUG("  HashFilterL = %08" PRIX32 "\r\n", LPC_EMAC->HashFilterL);
00596    TRACE_DEBUG("  HashFilterH = %08" PRIX32 "\r\n", LPC_EMAC->HashFilterH);
00597 
00598    //Successful processing
00599    return NO_ERROR;
00600 }
00601 
00602 
00603 /**
00604  * @brief Adjust MAC configuration parameters for proper operation
00605  * @param[in] interface Underlying network interface
00606  * @return Error code
00607  **/
00608 
00609 error_t lpc178xEthUpdateMacConfig(NetInterface *interface)
00610 {
00611    //10BASE-T or 100BASE-TX operation mode?
00612    if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
00613       LPC_EMAC->SUPP = SUPP_SPEED;
00614    else
00615       LPC_EMAC->SUPP = 0;
00616 
00617    //Half-duplex or full-duplex mode?
00618    if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
00619    {
00620       //The MAC operates in full-duplex mode
00621       LPC_EMAC->MAC2 |= MAC2_FULL_DUPLEX;
00622       LPC_EMAC->Command |= COMMAND_FULL_DUPLEX;
00623       //Configure Back-to-Back Inter-Packet Gap
00624       LPC_EMAC->IPGT = IPGT_FULL_DUPLEX;
00625    }
00626    else
00627    {
00628       //The MAC operates in half-duplex mode
00629       LPC_EMAC->MAC2 &= ~MAC2_FULL_DUPLEX;
00630       LPC_EMAC->Command &= ~COMMAND_FULL_DUPLEX;
00631       //Configure Back-to-Back Inter-Packet Gap
00632       LPC_EMAC->IPGT = IPGT_HALF_DUPLEX;
00633    }
00634 
00635    //Successful processing
00636    return NO_ERROR;
00637 }
00638 
00639 
00640 /**
00641  * @brief Write PHY register
00642  * @param[in] phyAddr PHY address
00643  * @param[in] regAddr Register address
00644  * @param[in] data Register value
00645  **/
00646 
00647 void lpc178xEthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data)
00648 {
00649    //Clear MCMD register
00650    LPC_EMAC->MCMD = 0;
00651 
00652    //PHY address
00653    LPC_EMAC->MADR = (phyAddr << 8) & MADR_PHY_ADDRESS;
00654    //Register address
00655    LPC_EMAC->MADR |= regAddr & MADR_REGISTER_ADDRESS;
00656    //Data to be written in the PHY register
00657    LPC_EMAC->MWTD = data & MWTD_WRITE_DATA;
00658 
00659    //Wait for the write to complete
00660    while(LPC_EMAC->MIND & MIND_BUSY);
00661 }
00662 
00663 
00664 /**
00665  * @brief Read PHY register
00666  * @param[in] phyAddr PHY address
00667  * @param[in] regAddr Register address
00668  * @return Register value
00669  **/
00670 
00671 uint16_t lpc178xEthReadPhyReg(uint8_t phyAddr, uint8_t regAddr)
00672 {
00673    //PHY address
00674    LPC_EMAC->MADR = (phyAddr << 8) & MADR_PHY_ADDRESS;
00675    //Register address
00676    LPC_EMAC->MADR |= regAddr & MADR_REGISTER_ADDRESS;
00677 
00678    //Start a read operation
00679    LPC_EMAC->MCMD = MCMD_READ;
00680    //Wait for the read to complete
00681    while(LPC_EMAC->MIND & MIND_BUSY);
00682    //Clear MCMD register
00683    LPC_EMAC->MCMD = 0;
00684 
00685    //Return PHY register contents
00686    return LPC_EMAC->MRDD & MRDD_READ_DATA;
00687 }
00688 
00689 
00690 /**
00691  * @brief CRC calculation
00692  * @param[in] data Pointer to the data over which to calculate the CRC
00693  * @param[in] length Number of bytes to process
00694  * @return Resulting CRC value
00695  **/
00696 
00697 uint32_t lpc178xEthCalcCrc(const void *data, size_t length)
00698 {
00699    uint_t i;
00700    uint_t j;
00701 
00702    //Point to the data over which to calculate the CRC
00703    const uint8_t *p = (uint8_t *) data;
00704    //CRC preset value
00705    uint32_t crc = 0xFFFFFFFF;
00706 
00707    //Loop through data
00708    for(i = 0; i < length; i++)
00709    {
00710       //The message is processed bit by bit
00711       for(j = 0; j < 8; j++)
00712       {
00713          //Update CRC value
00714          if(((crc >> 31) ^ (p[i] >> j)) & 0x01)
00715             crc = (crc << 1) ^ 0x04C11DB7;
00716          else
00717             crc = crc << 1;
00718       }
00719    }
00720 
00721    //Return CRC value
00722    return crc;
00723 }
00724