Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lpc23xx_eth.c Source File

lpc23xx_eth.c

Go to the documentation of this file.
00001 /**
00002  * @file lpc23xx_eth.c
00003  * @brief LPC2300 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 "lpc23xx.h"
00034 #include "core/net.h"
00035 #include "drivers/lpc23xx_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[LPC23XX_ETH_TX_BUFFER_COUNT][LPC23XX_ETH_TX_BUFFER_SIZE];
00047 //Receive buffer
00048 #pragma data_alignment = 4
00049 static uint8_t rxBuffer[LPC23XX_ETH_RX_BUFFER_COUNT][LPC23XX_ETH_RX_BUFFER_SIZE];
00050 //Transmit descriptors
00051 #pragma data_alignment = 4
00052 static Lpc23xxTxDesc txDesc[LPC23XX_ETH_TX_BUFFER_COUNT];
00053 //Transmit status array
00054 #pragma data_alignment = 4
00055 static Lpc23xxTxStatus txStatus[LPC23XX_ETH_TX_BUFFER_COUNT];
00056 //Receive descriptors
00057 #pragma data_alignment = 4
00058 static Lpc23xxRxDesc rxDesc[LPC23XX_ETH_RX_BUFFER_COUNT];
00059 //Receive status array
00060 #pragma data_alignment = 8
00061 static Lpc23xxRxStatus rxStatus[LPC23XX_ETH_RX_BUFFER_COUNT];
00062 
00063 //Keil MDK-ARM or GCC compiler?
00064 #else
00065 
00066 //Transmit buffer
00067 static uint8_t txBuffer[LPC23XX_ETH_TX_BUFFER_COUNT][LPC23XX_ETH_TX_BUFFER_SIZE]
00068    __attribute__((aligned(4)));
00069 //Receive buffer
00070 static uint8_t rxBuffer[LPC23XX_ETH_RX_BUFFER_COUNT][LPC23XX_ETH_RX_BUFFER_SIZE]
00071    __attribute__((aligned(4)));
00072 //Transmit descriptors
00073 static Lpc23xxTxDesc txDesc[LPC23XX_ETH_TX_BUFFER_COUNT]
00074    __attribute__((aligned(4)));
00075 //Transmit status array
00076 static Lpc23xxTxStatus txStatus[LPC23XX_ETH_TX_BUFFER_COUNT]
00077    __attribute__((aligned(4)));
00078 //Receive descriptors
00079 static Lpc23xxRxDesc rxDesc[LPC23XX_ETH_RX_BUFFER_COUNT]
00080    __attribute__((aligned(4)));
00081 //Receive status array
00082 static Lpc23xxRxStatus rxStatus[LPC23XX_ETH_RX_BUFFER_COUNT]
00083    __attribute__((aligned(8)));
00084 
00085 #endif
00086 
00087 
00088 /**
00089  * @brief LPC23xx Ethernet MAC driver
00090  **/
00091 
00092 const NicDriver lpc23xxEthDriver =
00093 {
00094    NIC_TYPE_ETHERNET,
00095    ETH_MTU,
00096    lpc23xxEthInit,
00097    lpc23xxEthTick,
00098    lpc23xxEthEnableIrq,
00099    lpc23xxEthDisableIrq,
00100    lpc23xxEthEventHandler,
00101    lpc23xxEthSendPacket,
00102    lpc23xxEthSetMulticastFilter,
00103    lpc23xxEthUpdateMacConfig,
00104    lpc23xxEthWritePhyReg,
00105    lpc23xxEthReadPhyReg,
00106    TRUE,
00107    TRUE,
00108    TRUE,
00109    FALSE
00110 };
00111 
00112 
00113 /**
00114  * @brief LPC23xx Ethernet MAC initialization
00115  * @param[in] interface Underlying network interface
00116  * @return Error code
00117  **/
00118 
00119 error_t lpc23xxEthInit(NetInterface *interface)
00120 {
00121    error_t error;
00122 
00123    //Debug message
00124    TRACE_INFO("Initializing LPC23xx Ethernet MAC...\r\n");
00125 
00126    //Save underlying network interface
00127    nicDriverInterface = interface;
00128 
00129    //Power up EMAC controller
00130    PCONP |= PCONP_PCENET;
00131 
00132    //GPIO configuration
00133    lpc23xxEthInitGpio(interface);
00134 
00135    //Reset host registers, transmit datapath and receive datapath
00136    MAC_COMMAND = COMMAND_RX_RESET | COMMAND_TX_RESET | COMMAND_REG_RESET;
00137 
00138    //Reset EMAC controller
00139    MAC_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    MAC_MAC1 = 0;
00144    MAC_MAC2 = MAC2_PAD_CRC_ENABLE | MAC2_CRC_ENABLE;
00145    MAC_IPGR = IPGR_DEFAULT_VALUE;
00146    MAC_CLRT = CLRT_DEFAULT_VALUE;
00147 
00148    //Select RMII mode
00149    MAC_COMMAND = COMMAND_RMII;
00150 
00151    //Configure MDC clock
00152    MAC_MCFG = MCFG_CLOCK_SELECT_DIV28;
00153    //Reset MII management interface
00154    MAC_MCFG |= MCFG_RESET_MII_MGMT;
00155    MAC_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    lpc23xxEthInitDesc(interface);
00165 
00166    //Set the MAC address
00167    MAC_SA0 = interface->macAddr.w[2];
00168    MAC_SA1 = interface->macAddr.w[1];
00169    MAC_SA2 = interface->macAddr.w[0];
00170 
00171    //Initialize hash table
00172    MAC_HASHFILTERL = 0;
00173    MAC_HASHFILTERH = 0;
00174 
00175    //Configure the receive filter
00176    MAC_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    MAC_MAXF = 1518;
00181 
00182    //Reset EMAC interrupt flags
00183    MAC_INTCLEAR  = 0xFFFF;
00184    //Enable desired EMAC interrupts
00185    MAC_INTENABLE = INT_TX_DONE | INT_RX_DONE;
00186 
00187    //The interrupt request is assigned to the IRQ category
00188    VICIntSelect &= ~VIC_INT_ETHERNET;
00189    //Register interrupt handler
00190    VICVectAddr21 = (uint32_t) lpc23xxEthIrqHandler;
00191    //Configure interrupt priority
00192    VICVectPriority21 = LPC23XX_ETH_IRQ_PRIORITY;
00193 
00194    //Enable transmission and reception
00195    MAC_COMMAND |= COMMAND_TX_ENABLE | COMMAND_RX_ENABLE;
00196    //Allow frames to be received
00197    MAC_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 //LPC2378-STK evaluation board?
00208 #if defined(USE_LPC2378_STK)
00209 
00210 /**
00211  * @brief GPIO configuration
00212  * @param[in] interface Underlying network interface
00213  **/
00214 
00215 void lpc23xxEthInitGpio(NetInterface *interface)
00216 {
00217    //Configure P1.0 (ENET_TXD0), P1.1 (ENET_TXD1), P1.4 (ENET_TX_EN), P1.8 (ENET_CRS),
00218    //P1.9 (ENET_RXD0), P1.10 (ENET_RXD1), P1.14 (RX_ER) and P1.15 (ENET_REF_CLK)
00219    PINSEL2 &= ~(PINSEL2_P1_0_MASK | PINSEL2_P1_1_MASK |
00220       PINSEL2_P1_4_MASK | PINSEL2_P1_8_MASK | PINSEL2_P1_9_MASK |
00221       PINSEL2_P1_10_MASK | PINSEL2_P1_14_MASK | PINSEL2_P1_15_MASK);
00222 
00223    PINSEL2 |= PINSEL2_P1_0_ENET_TXD0 | PINSEL2_P1_1_ENET_TXD1 |
00224       PINSEL2_P1_4_ENET_TX_EN | PINSEL2_P1_8_ENET_CRS | PINSEL2_P1_9_ENET_RXD0 |
00225       PINSEL2_P1_10_ENET_RXD1 | PINSEL2_P1_14_ENET_RX_ER | PINSEL2_P1_15_ENET_REF_CLK;
00226 
00227    //Configure P1.16 (ENET_MDC) and P1.17 (ENET_MDIO)
00228    PINSEL3 &= ~(PINSEL3_P1_16_MASK | PINSEL3_P1_17_MASK);
00229    PINSEL3 |= PINSEL3_P1_16_ENET_MDC | PINSEL3_P1_17_ENET_MDIO;
00230 }
00231 
00232 #endif
00233 
00234 
00235 /**
00236  * @brief Initialize TX and RX descriptors
00237  * @param[in] interface Underlying network interface
00238  **/
00239 
00240 void lpc23xxEthInitDesc(NetInterface *interface)
00241 {
00242    uint_t i;
00243 
00244    //Initialize TX descriptors
00245    for(i = 0; i < LPC23XX_ETH_TX_BUFFER_COUNT; i++)
00246    {
00247       //Base address of the buffer containing transmit data
00248       txDesc[i].packet = (uint32_t) txBuffer[i];
00249       //Transmit descriptor control word
00250       txDesc[i].control = 0;
00251       //Transmit status information word
00252       txStatus[i].info = 0;
00253    }
00254 
00255    //Initialize RX descriptors
00256    for(i = 0; i < LPC23XX_ETH_RX_BUFFER_COUNT; i++)
00257    {
00258       //Base address of the buffer for storing receive data
00259       rxDesc[i].packet = (uint32_t) rxBuffer[i];
00260       //Receive descriptor control word
00261       rxDesc[i].control = RX_CTRL_INTERRUPT | (LPC23XX_ETH_RX_BUFFER_SIZE - 1);
00262       //Receive status information word
00263       rxStatus[i].info = 0;
00264       //Receive status HashCRC word
00265       rxStatus[i].hashCrc = 0;
00266    }
00267 
00268    //Initialize EMAC transmit descriptor registers
00269    MAC_TXDESCRIPTOR = (uint32_t) txDesc;
00270    MAC_TXSTATUS = (uint32_t) txStatus;
00271    MAC_TXDESCRIPTORNUM = LPC23XX_ETH_TX_BUFFER_COUNT - 1;
00272    MAC_TXPRODUCEINDEX = 0;
00273 
00274    //Initialize EMAC receive descriptor registers
00275    MAC_RXDESCRIPTOR = (uint32_t) rxDesc;
00276    MAC_RXSTATUS = (uint32_t) rxStatus;
00277    MAC_RXDESCRIPTORNUM = LPC23XX_ETH_RX_BUFFER_COUNT - 1;
00278    MAC_RXCONSUMEINDEX = 0;
00279 }
00280 
00281 
00282 /**
00283  * @brief LPC23xx Ethernet MAC timer handler
00284  *
00285  * This routine is periodically called by the TCP/IP stack to
00286  * handle periodic operations such as polling the link state
00287  *
00288  * @param[in] interface Underlying network interface
00289  **/
00290 
00291 void lpc23xxEthTick(NetInterface *interface)
00292 {
00293    //Handle periodic operations
00294    interface->phyDriver->tick(interface);
00295 }
00296 
00297 
00298 /**
00299  * @brief Enable interrupts
00300  * @param[in] interface Underlying network interface
00301  **/
00302 
00303 void lpc23xxEthEnableIrq(NetInterface *interface)
00304 {
00305    //Enable Ethernet MAC interrupts
00306    VICIntEnable = VIC_INT_ETHERNET;
00307    //Enable Ethernet PHY interrupts
00308    interface->phyDriver->enableIrq(interface);
00309 }
00310 
00311 
00312 /**
00313  * @brief Disable interrupts
00314  * @param[in] interface Underlying network interface
00315  **/
00316 
00317 void lpc23xxEthDisableIrq(NetInterface *interface)
00318 {
00319    //Disable Ethernet MAC interrupts
00320    VICIntEnClr = VIC_INT_ETHERNET;
00321    //Disable Ethernet PHY interrupts
00322    interface->phyDriver->disableIrq(interface);
00323 }
00324 
00325 
00326 /**
00327  * @brief LPC23xx Ethernet MAC interrupt service routine
00328  **/
00329 
00330 __irq void lpc23xxEthIrqHandler(void)
00331 {
00332    uint_t i;
00333    bool_t flag;
00334    uint32_t status;
00335 
00336    //Enter interrupt service routine
00337    osEnterIsr();
00338 
00339    //This flag will be set if a higher priority task must be woken
00340    flag = FALSE;
00341 
00342    //Read interrupt status register
00343    status = MAC_INTSTATUS;
00344 
00345    //A packet has been transmitted?
00346    if(status & INT_TX_DONE)
00347    {
00348       //Clear TxDone interrupt flag
00349       MAC_INTCLEAR = INT_TX_DONE;
00350 
00351       //Get the index of the next descriptor
00352       i = MAC_TXPRODUCEINDEX + 1;
00353 
00354       //Wrap around if necessary
00355       if(i >= LPC23XX_ETH_TX_BUFFER_COUNT)
00356          i = 0;
00357 
00358       //Check whether the TX buffer is available for writing
00359       if(i != MAC_TXCONSUMEINDEX)
00360       {
00361          //Notify the TCP/IP stack that the transmitter is ready to send
00362          flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
00363       }
00364    }
00365 
00366    //A packet has been received?
00367    if(status & INT_RX_DONE)
00368    {
00369       //Disable RxDone interrupts
00370       MAC_INTENABLE &= ~INT_RX_DONE;
00371 
00372       //Set event flag
00373       nicDriverInterface->nicEvent = TRUE;
00374       //Notify the TCP/IP stack of the event
00375       flag |= osSetEventFromIsr(&netEvent);
00376    }
00377 
00378    //Leave interrupt service routine
00379    osExitIsr(flag);
00380 }
00381 
00382 
00383 /**
00384  * @brief LPC23xx Ethernet MAC event handler
00385  * @param[in] interface Underlying network interface
00386  **/
00387 
00388 void lpc23xxEthEventHandler(NetInterface *interface)
00389 {
00390    error_t error;
00391 
00392    //Packet received?
00393    if(MAC_INTSTATUS & INT_RX_DONE)
00394    {
00395       //Clear RxDone interrupt flag
00396       MAC_INTCLEAR = INT_RX_DONE;
00397 
00398       //Process all pending packets
00399       do
00400       {
00401          //Read incoming packet
00402          error = lpc23xxEthReceivePacket(interface);
00403 
00404          //No more data in the receive buffer?
00405       } while(error != ERROR_BUFFER_EMPTY);
00406    }
00407 
00408    //Re-enable TxDone and RxDone interrupts
00409    MAC_INTENABLE = INT_TX_DONE | INT_RX_DONE;
00410 }
00411 
00412 
00413 /**
00414  * @brief Send a packet
00415  * @param[in] interface Underlying network interface
00416  * @param[in] buffer Multi-part buffer containing the data to send
00417  * @param[in] offset Offset to the first data byte
00418  * @return Error code
00419  **/
00420 
00421 error_t lpc23xxEthSendPacket(NetInterface *interface,
00422    const NetBuffer *buffer, size_t offset)
00423 {
00424    uint_t i;
00425    uint_t j;
00426    size_t length;
00427 
00428    //Retrieve the length of the packet
00429    length = netBufferGetLength(buffer) - offset;
00430 
00431    //Check the frame length
00432    if(!length)
00433    {
00434       //The transmitter can accept another packet
00435       osSetEvent(&interface->nicTxEvent);
00436       //We are done since the buffer is empty
00437       return NO_ERROR;
00438    }
00439    else if(length > LPC23XX_ETH_TX_BUFFER_SIZE)
00440    {
00441       //The transmitter can accept another packet
00442       osSetEvent(&interface->nicTxEvent);
00443       //Report an error
00444       return ERROR_INVALID_LENGTH;
00445    }
00446 
00447    //Get the index of the current descriptor
00448    i = MAC_TXPRODUCEINDEX;
00449    //Get the index of the next descriptor
00450    j = i + 1;
00451 
00452    //Wrap around if necessary
00453    if(j >= LPC23XX_ETH_TX_BUFFER_COUNT)
00454       j = 0;
00455 
00456    //Check whether the transmit descriptor array is full
00457    if(j == MAC_TXCONSUMEINDEX)
00458       return ERROR_FAILURE;
00459 
00460    //Copy user data to the transmit buffer
00461    netBufferRead((uint8_t *) txDesc[i].packet, buffer, offset, length);
00462 
00463    //Write the transmit control word
00464    txDesc[i].control = TX_CTRL_INTERRUPT | TX_CTRL_LAST |
00465       TX_CTRL_CRC | TX_CTRL_PAD | ((length - 1) & TX_CTRL_SIZE);
00466 
00467    //Increment index and wrap around if necessary
00468    if(++i >= LPC23XX_ETH_TX_BUFFER_COUNT)
00469       i = 0;
00470 
00471    //Save the resulting value
00472    MAC_TXPRODUCEINDEX = i;
00473 
00474    //Get the index of the next descriptor
00475    j = i + 1;
00476 
00477    //Wrap around if necessary
00478    if(j >= LPC23XX_ETH_TX_BUFFER_COUNT)
00479       j = 0;
00480 
00481    //Check whether the next buffer is available for writing
00482    if(j != MAC_TXCONSUMEINDEX)
00483    {
00484       //The transmitter can accept another packet
00485       osSetEvent(&interface->nicTxEvent);
00486    }
00487 
00488    //Successful write operation
00489    return NO_ERROR;
00490 }
00491 
00492 
00493 /**
00494  * @brief Receive a packet
00495  * @param[in] interface Underlying network interface
00496  * @return Error code
00497  **/
00498 
00499 error_t lpc23xxEthReceivePacket(NetInterface *interface)
00500 {
00501    error_t error;
00502    size_t n;
00503    uint_t i;
00504 
00505    //Point to the current descriptor
00506    i = MAC_RXCONSUMEINDEX;
00507 
00508    //Make sure the current buffer is available for reading
00509    if(i != MAC_RXPRODUCEINDEX)
00510    {
00511       //Retrieve the length of the frame
00512       n = (rxStatus[i].info & RX_STATUS_SIZE) + 1;
00513       //Limit the number of data to read
00514       n = MIN(n, LPC23XX_ETH_RX_BUFFER_SIZE);
00515 
00516       //Pass the packet to the upper layer
00517       nicProcessPacket(interface, (uint8_t *) rxDesc[i].packet, n);
00518 
00519       //Increment index and wrap around if necessary
00520       if(++i >= LPC23XX_ETH_RX_BUFFER_COUNT)
00521          i = 0;
00522 
00523       //Save the resulting value
00524       MAC_RXCONSUMEINDEX = i;
00525 
00526       //Valid packet received
00527       error = NO_ERROR;
00528    }
00529    else
00530    {
00531       //No more data in the receive buffer
00532       error = ERROR_BUFFER_EMPTY;
00533    }
00534 
00535    //Return status code
00536    return error;
00537 }
00538 
00539 
00540 /**
00541  * @brief Configure multicast MAC address filtering
00542  * @param[in] interface Underlying network interface
00543  * @return Error code
00544  **/
00545 
00546 error_t lpc23xxEthSetMulticastFilter(NetInterface *interface)
00547 {
00548    uint_t i;
00549    uint_t k;
00550    uint32_t crc;
00551    uint32_t hashTable[2];
00552    MacFilterEntry *entry;
00553 
00554    //Debug message
00555    TRACE_DEBUG("Updating LPC23xx hash table...\r\n");
00556 
00557    //Clear hash table
00558    hashTable[0] = 0;
00559    hashTable[1] = 0;
00560 
00561    //The MAC filter table contains the multicast MAC addresses
00562    //to accept when receiving an Ethernet frame
00563    for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++)
00564    {
00565       //Point to the current entry
00566       entry = &interface->macMulticastFilter[i];
00567 
00568       //Valid entry?
00569       if(entry->refCount > 0)
00570       {
00571          //Compute CRC over the current MAC address
00572          crc = lpc23xxEthCalcCrc(&entry->addr, sizeof(MacAddr));
00573          //Bits [28:23] are used to form the hash
00574          k = (crc >> 23) & 0x3F;
00575          //Update hash table contents
00576          hashTable[k / 32] |= (1 << (k % 32));
00577       }
00578    }
00579 
00580    //Write the hash table
00581    MAC_HASHFILTERL = hashTable[0];
00582    MAC_HASHFILTERH = hashTable[1];
00583 
00584    //Debug message
00585    TRACE_DEBUG("  HashFilterL = %08" PRIX32 "\r\n", MAC_HASHFILTERL);
00586    TRACE_DEBUG("  HashFilterH = %08" PRIX32 "\r\n", MAC_HASHFILTERH);
00587 
00588    //Successful processing
00589    return NO_ERROR;
00590 }
00591 
00592 
00593 /**
00594  * @brief Adjust MAC configuration parameters for proper operation
00595  * @param[in] interface Underlying network interface
00596  * @return Error code
00597  **/
00598 
00599 error_t lpc23xxEthUpdateMacConfig(NetInterface *interface)
00600 {
00601    //10BASE-T or 100BASE-TX operation mode?
00602    if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
00603       MAC_SUPP = SUPP_SPEED;
00604    else
00605       MAC_SUPP = 0;
00606 
00607    //Half-duplex or full-duplex mode?
00608    if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
00609    {
00610       //The MAC operates in full-duplex mode
00611       MAC_MAC2 |= MAC2_FULL_DUPLEX;
00612       MAC_COMMAND |= COMMAND_FULL_DUPLEX;
00613       //Configure Back-to-Back Inter-Packet Gap
00614       MAC_IPGT = IPGT_FULL_DUPLEX;
00615    }
00616    else
00617    {
00618       //The MAC operates in half-duplex mode
00619       MAC_MAC2 &= ~MAC2_FULL_DUPLEX;
00620       MAC_COMMAND &= ~COMMAND_FULL_DUPLEX;
00621       //Configure Back-to-Back Inter-Packet Gap
00622       MAC_IPGT = IPGT_HALF_DUPLEX;
00623    }
00624 
00625    //Successful processing
00626    return NO_ERROR;
00627 }
00628 
00629 
00630 /**
00631  * @brief Write PHY register
00632  * @param[in] phyAddr PHY address
00633  * @param[in] regAddr Register address
00634  * @param[in] data Register value
00635  **/
00636 
00637 void lpc23xxEthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data)
00638 {
00639    //Clear MCMD register
00640    MAC_MCMD = 0;
00641 
00642    //PHY address
00643    MAC_MADR = (phyAddr << 8) & MADR_PHY_ADDRESS;
00644    //Register address
00645    MAC_MADR |= regAddr & MADR_REGISTER_ADDRESS;
00646    //Data to be written in the PHY register
00647    MAC_MWTD = data & MWTD_WRITE_DATA;
00648 
00649    //Wait for the write to complete
00650    while(MAC_MIND & MIND_BUSY);
00651 }
00652 
00653 
00654 /**
00655  * @brief Read PHY register
00656  * @param[in] phyAddr PHY address
00657  * @param[in] regAddr Register address
00658  * @return Register value
00659  **/
00660 
00661 uint16_t lpc23xxEthReadPhyReg(uint8_t phyAddr, uint8_t regAddr)
00662 {
00663    //PHY address
00664    MAC_MADR = (phyAddr << 8) & MADR_PHY_ADDRESS;
00665    //Register address
00666    MAC_MADR |= regAddr & MADR_REGISTER_ADDRESS;
00667 
00668    //Start a read operation
00669    MAC_MCMD = MCMD_READ;
00670    //Wait for the read to complete
00671    while(MAC_MIND & MIND_BUSY);
00672    //Clear MCMD register
00673    MAC_MCMD = 0;
00674 
00675    //Return PHY register contents
00676    return MAC_MRDD & MRDD_READ_DATA;
00677 }
00678 
00679 
00680 /**
00681  * @brief CRC calculation
00682  * @param[in] data Pointer to the data over which to calculate the CRC
00683  * @param[in] length Number of bytes to process
00684  * @return Resulting CRC value
00685  **/
00686 
00687 uint32_t lpc23xxEthCalcCrc(const void *data, size_t length)
00688 {
00689    uint_t i;
00690    uint_t j;
00691 
00692    //Point to the data over which to calculate the CRC
00693    const uint8_t *p = (uint8_t *) data;
00694    //CRC preset value
00695    uint32_t crc = 0xFFFFFFFF;
00696 
00697    //Loop through data
00698    for(i = 0; i < length; i++)
00699    {
00700       //The message is processed bit by bit
00701       for(j = 0; j < 8; j++)
00702       {
00703          //Update CRC value
00704          if(((crc >> 31) ^ (p[i] >> j)) & 0x01)
00705             crc = (crc << 1) ^ 0x04C11DB7;
00706          else
00707             crc = crc << 1;
00708       }
00709    }
00710 
00711    //Return CRC value
00712    return crc;
00713 }
00714