Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers str912_eth.c Source File

str912_eth.c

Go to the documentation of this file.
00001 /**
00002  * @file str912_eth.c
00003  * @brief STR9 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 "91x_lib.h"
00034 #include "core/net.h"
00035 #include "drivers/str912_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[STR912_ETH_TX_BUFFER_COUNT][STR912_ETH_TX_BUFFER_SIZE];
00047 //Receive buffer
00048 #pragma data_alignment = 4
00049 static uint8_t rxBuffer[STR912_ETH_RX_BUFFER_COUNT][STR912_ETH_RX_BUFFER_SIZE];
00050 //Transmit DMA descriptors
00051 #pragma data_alignment = 4
00052 static Str912TxDmaDesc txDmaDesc[STR912_ETH_TX_BUFFER_COUNT];
00053 //Receive DMA descriptors
00054 #pragma data_alignment = 4
00055 static Str912RxDmaDesc rxDmaDesc[STR912_ETH_RX_BUFFER_COUNT];
00056 
00057 //Keil MDK-ARM or GCC compiler?
00058 #else
00059 
00060 //Transmit buffer
00061 static uint8_t txBuffer[STR912_ETH_TX_BUFFER_COUNT][STR912_ETH_TX_BUFFER_SIZE]
00062    __attribute__((aligned(4)));
00063 //Receive buffer
00064 static uint8_t rxBuffer[STR912_ETH_RX_BUFFER_COUNT][STR912_ETH_RX_BUFFER_SIZE]
00065    __attribute__((aligned(4)));
00066 //Transmit DMA descriptors
00067 static Str912TxDmaDesc txDmaDesc[STR912_ETH_TX_BUFFER_COUNT]
00068    __attribute__((aligned(4)));
00069 //Receive DMA descriptors
00070 static Str912RxDmaDesc rxDmaDesc[STR912_ETH_RX_BUFFER_COUNT]
00071    __attribute__((aligned(4)));
00072 
00073 #endif
00074 
00075 //Pointer to the current TX DMA descriptor
00076 static Str912TxDmaDesc *txCurDmaDesc;
00077 //Pointer to the current RX DMA descriptor
00078 static Str912RxDmaDesc *rxCurDmaDesc;
00079 
00080 
00081 /**
00082  * @brief STR912 Ethernet MAC driver
00083  **/
00084 
00085 const NicDriver str912EthDriver =
00086 {
00087    NIC_TYPE_ETHERNET,
00088    ETH_MTU,
00089    str912EthInit,
00090    str912EthTick,
00091    str912EthEnableIrq,
00092    str912EthDisableIrq,
00093    str912EthEventHandler,
00094    str912EthSendPacket,
00095    str912EthSetMulticastFilter,
00096    str912EthUpdateMacConfig,
00097    str912EthWritePhyReg,
00098    str912EthReadPhyReg,
00099    TRUE,
00100    TRUE,
00101    TRUE,
00102    FALSE
00103 };
00104 
00105 
00106 /**
00107  * @brief STR912 Ethernet MAC initialization
00108  * @param[in] interface Underlying network interface
00109  * @return Error code
00110  **/
00111 
00112 error_t str912EthInit(NetInterface *interface)
00113 {
00114    error_t error;
00115 
00116    //Debug message
00117    TRACE_INFO("Initializing STR912 Ethernet MAC...\r\n");
00118 
00119    //Save underlying network interface
00120    nicDriverInterface = interface;
00121 
00122    //GPIO configuration
00123    str912EthInitGpio(interface);
00124 
00125    //Enable Ethernet MAC clock
00126    SCU_AHBPeriphClockConfig(__ENET, ENABLE);
00127 
00128    //Reset Ethernet MAC peripheral
00129    SCU_AHBPeriphReset(__ENET, ENABLE);
00130    SCU_AHBPeriphReset(__ENET, DISABLE);
00131 
00132    //MAC DMA software reset
00133    ENET_DMA->SCR |= ENET_SCR_SRESET;
00134    ENET_DMA->SCR &= ~ENET_SCR_SRESET;
00135 
00136    //Use default MAC configuration
00137    ENET_MAC->MCR = ENET_MCR_AFM_1 | ENET_MCR_RVFF |
00138       ENET_MCR_BL_1 | ENET_MCR_DCE | ENET_MCR_RVBE;
00139 
00140    //Adjust HCLK divider depending on system clock frequency
00141    if(SCU_GetHCLKFreqValue() > 50000)
00142       ENET_MAC->MCR |= ENET_MCR_PS_1;
00143 
00144    //PHY transceiver initialization
00145    error = interface->phyDriver->init(interface);
00146    //Failed to initialize PHY transceiver?
00147    if(error)
00148       return error;
00149 
00150    //Set the MAC address
00151    ENET_MAC->MAL = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
00152    ENET_MAC->MAH = interface->macAddr.w[2];
00153 
00154    //Initialize hash table
00155    ENET_MAC->MCLA = 0;
00156    ENET_MAC->MCHA = 0;
00157 
00158    //DMA configuration
00159    //ENET_DMA->SCR = 0;
00160 
00161    //Force a DMA abort
00162    ENET_DMA->TXSTR |= ENET_TXSTR_DMA_EN;
00163    ENET_DMA->RXSTR |= ENET_RXSTR_DMA_EN;
00164 
00165    //Set descriptor fetch delay
00166    ENET_DMA->TXSTR = ENET_TXSTR_DFETCH_DLY_DEFAULT | ENET_TXSTR_UNDER_RUN;
00167    ENET_DMA->RXSTR = ENET_RXSTR_DFETCH_DLY_DEFAULT;
00168 
00169    //Initialize DMA descriptor lists
00170    str912EthInitDmaDesc(interface);
00171 
00172    //Clear interrupt flags
00173    ENET_DMA->ISR = ENET_ISR_TX_CURR_DONE | ENET_ISR_RX_CURR_DONE;
00174    //Configure DMA interrupts as desired
00175    ENET_DMA->IER = ENET_IER_TX_CURR_DONE_EN | ENET_IER_RX_CURR_DONE_EN;
00176 
00177    //Configure Ethernet interrupt priority
00178    VIC_Config(ENET_ITLine, VIC_IRQ, STR912_ETH_IRQ_PRIORITY);
00179 
00180    //Enable MAC transmission and reception
00181    ENET_MAC->MCR |= ENET_MCR_TE | ENET_MCR_RE;
00182    //Instruct the DMA to poll the receive descriptor list
00183    ENET_DMA->RXSTR |= ENET_RXSTR_START_FETCH;
00184 
00185    //Accept any packets from the upper layer
00186    osSetEvent(&interface->nicTxEvent);
00187 
00188    //Successful initialization
00189    return NO_ERROR;
00190 }
00191 
00192 
00193 //STR-E912 evaluation board?
00194 #if defined(USE_STR_E912)
00195 
00196 /**
00197  * @brief GPIO configuration
00198  * @param[in] interface Underlying network interface
00199  **/
00200 
00201 void str912EthInitGpio(NetInterface *interface)
00202 {
00203    GPIO_InitTypeDef GPIO_InitStructure;
00204 
00205    //Enable GPIO clocks
00206    SCU_APBPeriphClockConfig(__GPIO0, ENABLE);
00207    SCU_APBPeriphClockConfig(__GPIO1, ENABLE);
00208    SCU_APBPeriphClockConfig(__GPIO5, ENABLE);
00209 
00210    //Enable MII_PHYCLK clock
00211    SCU_PHYCLKConfig(ENABLE);
00212 
00213    //Configure MII_TX_CLK (P0.0), MII_RXD0 (P0.2), MII_RXD1 (P0.3), MII_RXD2 (P0.4),
00214    //MII_RXD3 (P0.5), MII_RX_CLK (P0.6) and MII_RX_DV (P0.7)
00215    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_3 |
00216       GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
00217 
00218    GPIO_InitStructure.GPIO_Direction = GPIO_PinInput;
00219    GPIO_InitStructure.GPIO_IPInputConnected = GPIO_IPInputConnected_Disable;
00220    GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1;
00221    GPIO_Init(GPIO0, &GPIO_InitStructure);
00222 
00223    //Configure MII_RX_ER (P1.0), MII_COL (P1.5) and MII_CRS (P1.6)
00224    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_5 | GPIO_Pin_6;
00225    GPIO_InitStructure.GPIO_Direction = GPIO_PinInput;
00226    GPIO_InitStructure.GPIO_IPInputConnected = GPIO_IPInputConnected_Disable;
00227    GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1;
00228    GPIO_Init(GPIO1, &GPIO_InitStructure);
00229 
00230    //Configure MII_TXD0 (P1.1), MII_TXD1 (P1.2), MII_TXD2 (P1.3),
00231    //MII_TXD3 (P1.4) and MII_MDC (P1.7)
00232    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 |
00233       GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_7;
00234 
00235    GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
00236    GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
00237    GPIO_InitStructure.GPIO_IPInputConnected = GPIO_IPInputConnected_Disable;
00238    GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt2;
00239    GPIO_Init(GPIO1, &GPIO_InitStructure);
00240 
00241    //Configure MII_PHYCLK (P5.2) and MII_TX_EN (P5.3)
00242    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
00243    GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
00244    GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
00245    GPIO_InitStructure.GPIO_IPInputConnected = GPIO_IPInputConnected_Disable;
00246    GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt2;
00247    GPIO_Init(GPIO5, &GPIO_InitStructure);
00248 }
00249 
00250 #endif
00251 
00252 
00253 /**
00254  * @brief Initialize DMA descriptor lists
00255  * @param[in] interface Underlying network interface
00256  **/
00257 
00258 void str912EthInitDmaDesc(NetInterface *interface)
00259 {
00260    uint_t i;
00261 
00262    //Initialize TX DMA descriptor list
00263    for(i = 0; i < STR912_ETH_TX_BUFFER_COUNT; i++)
00264    {
00265       //Control word
00266       txDmaDesc[i].ctrl = ENET_TDES_CTRL_NXT_EN;
00267       //Transmit buffer address
00268       txDmaDesc[i].start = (uint32_t) txBuffer[i];
00269       //Next descriptor address
00270       txDmaDesc[i].next = (uint32_t) &txDmaDesc[i + 1] | ENET_TDES_NEXT_NPOL_EN;
00271       //Status word
00272       txDmaDesc[i].status = 0;
00273    }
00274 
00275    //The last descriptor is chained to the first entry
00276    txDmaDesc[i - 1].next = (uint32_t) &txDmaDesc[0] | ENET_TDES_NEXT_NPOL_EN;
00277    //Point to the very first descriptor
00278    txCurDmaDesc = &txDmaDesc[0];
00279 
00280    //Initialize RX DMA descriptor list
00281    for(i = 0; i < STR912_ETH_RX_BUFFER_COUNT; i++)
00282    {
00283       //Control word
00284       rxDmaDesc[i].ctrl = ENET_RDES_CTRL_NXT_EN | STR912_ETH_RX_BUFFER_SIZE;
00285       //Receive buffer address
00286       rxDmaDesc[i].start = (uint32_t) rxBuffer[i];
00287       //Next descriptor address
00288       rxDmaDesc[i].next = (uint32_t) &rxDmaDesc[i + 1] | ENET_RDES_NEXT_NPOL_EN;
00289       //Status word
00290       rxDmaDesc[i].status = ENET_RDES_STATUS_VALID;
00291    }
00292 
00293    //The last descriptor is chained to the first entry
00294    rxDmaDesc[i - 1].next = (uint32_t) &rxDmaDesc[0] | ENET_RDES_NEXT_NPOL_EN;
00295    //Point to the very first descriptor
00296    rxCurDmaDesc = &rxDmaDesc[0];
00297 
00298    //Start location of the TX descriptor list
00299    ENET_DMA->TXNDAR = (uint32_t) txDmaDesc | ENET_TDES_NEXT_NPOL_EN;
00300    //Start location of the RX descriptor list
00301    ENET_DMA->RXNDAR = (uint32_t) rxDmaDesc | ENET_RDES_NEXT_NPOL_EN;
00302 }
00303 
00304 
00305 /**
00306  * @brief STR912 Ethernet MAC timer handler
00307  *
00308  * This routine is periodically called by the TCP/IP stack to
00309  * handle periodic operations such as polling the link state
00310  *
00311  * @param[in] interface Underlying network interface
00312  **/
00313 
00314 void str912EthTick(NetInterface *interface)
00315 {
00316    //Handle periodic operations
00317    interface->phyDriver->tick(interface);
00318 }
00319 
00320 
00321 /**
00322  * @brief Enable interrupts
00323  * @param[in] interface Underlying network interface
00324  **/
00325 
00326 void str912EthEnableIrq(NetInterface *interface)
00327 {
00328    //Enable Ethernet MAC interrupts
00329    VIC_ITCmd(ENET_ITLine, ENABLE);
00330    //Enable Ethernet PHY interrupts
00331    interface->phyDriver->enableIrq(interface);
00332 }
00333 
00334 
00335 /**
00336  * @brief Disable interrupts
00337  * @param[in] interface Underlying network interface
00338  **/
00339 
00340 void str912EthDisableIrq(NetInterface *interface)
00341 {
00342    //Disable Ethernet MAC interrupts
00343    VIC_ITCmd(ENET_ITLine, DISABLE);
00344    //Disable Ethernet PHY interrupts
00345    interface->phyDriver->disableIrq(interface);
00346 }
00347 
00348 
00349 /**
00350  * @brief STR912 Ethernet MAC interrupt service routine
00351  **/
00352 
00353 void ENET_IRQHandler(void)
00354 {
00355    bool_t flag;
00356    uint32_t status;
00357 
00358    //Enter interrupt service routine
00359    osEnterIsr();
00360 
00361    //This flag will be set if a higher priority task must be woken
00362    flag = FALSE;
00363 
00364    //Read DMA status register
00365    status = ENET_DMA->ISR;
00366 
00367    //A packet has been transmitted?
00368    if(status & ENET_ISR_TX_CURR_DONE)
00369    {
00370       //Clear TX_CURR_DONE interrupt flag
00371       ENET_DMA->ISR = ENET_ISR_TX_CURR_DONE;
00372 
00373       //Check whether the TX buffer is available for writing
00374       if(!(txCurDmaDesc->status & ENET_TDES_STATUS_VALID))
00375       {
00376          //Notify the TCP/IP stack that the transmitter is ready to send
00377          flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
00378       }
00379    }
00380 
00381    //A packet has been received?
00382    if(status & ENET_ISR_RX_CURR_DONE)
00383    {
00384       //Disable RX_CURR_DONE interrupt
00385       ENET_DMA->IER &= ~ENET_IER_RX_CURR_DONE_EN;
00386 
00387       //Set event flag
00388       nicDriverInterface->nicEvent = TRUE;
00389       //Notify the TCP/IP stack of the event
00390       flag |= osSetEventFromIsr(&netEvent);
00391    }
00392 
00393    //Leave interrupt service routine
00394    osExitIsr(flag);
00395 }
00396 
00397 
00398 /**
00399  * @brief STR912 Ethernet MAC event handler
00400  * @param[in] interface Underlying network interface
00401  **/
00402 
00403 void str912EthEventHandler(NetInterface *interface)
00404 {
00405    error_t error;
00406 
00407    //Packet received?
00408    if(ENET_DMA->ISR & ENET_ISR_RX_CURR_DONE)
00409    {
00410       //Clear interrupt flag
00411       ENET_DMA->ISR = ENET_ISR_RX_CURR_DONE;
00412 
00413       //Process all pending packets
00414       do
00415       {
00416          //Read incoming packet
00417          error = str912EthReceivePacket(interface);
00418 
00419          //No more data in the receive buffer?
00420       } while(error != ERROR_BUFFER_EMPTY);
00421    }
00422 
00423    //Re-enable DMA interrupts
00424    ENET_DMA->IER = ENET_IER_TX_CURR_DONE_EN | ENET_IER_RX_CURR_DONE_EN;
00425 }
00426 
00427 
00428 /**
00429  * @brief Send a packet
00430  * @param[in] interface Underlying network interface
00431  * @param[in] buffer Multi-part buffer containing the data to send
00432  * @param[in] offset Offset to the first data byte
00433  * @return Error code
00434  **/
00435 
00436 error_t str912EthSendPacket(NetInterface *interface,
00437    const NetBuffer *buffer, size_t offset)
00438 {
00439    size_t length;
00440 
00441    //Retrieve the length of the packet
00442    length = netBufferGetLength(buffer) - offset;
00443 
00444    //Check the frame length
00445    if(length > STR912_ETH_TX_BUFFER_SIZE)
00446    {
00447       //The transmitter can accept another packet
00448       osSetEvent(&interface->nicTxEvent);
00449       //Report an error
00450       return ERROR_INVALID_LENGTH;
00451    }
00452 
00453    //Make sure the current buffer is available for writing
00454    if(txCurDmaDesc->status & ENET_TDES_STATUS_VALID)
00455       return ERROR_FAILURE;
00456 
00457    //Copy user data to the transmit buffer
00458    netBufferRead((uint8_t *) (txCurDmaDesc->start & ENET_TDES_START_ADDR),
00459       buffer, offset, length);
00460 
00461    //Write the number of bytes to send
00462    txCurDmaDesc->ctrl = ENET_TDES_CTRL_NXT_EN | length;
00463    //Give the ownership of the descriptor to the DMA
00464    txCurDmaDesc->status = ENET_TDES_STATUS_VALID;
00465 
00466    //Instruct the DMA to poll the transmit descriptor list
00467    ENET_DMA->TXSTR |= ENET_TXSTR_START_FETCH;
00468 
00469    //Point to the next descriptor in the list
00470    txCurDmaDesc = (Str912TxDmaDesc *) (txCurDmaDesc->next & ENET_TDES_NEXT_ADDR);
00471 
00472    //Check whether the next buffer is available for writing
00473    if(!(txCurDmaDesc->status & ENET_TDES_STATUS_VALID))
00474    {
00475       //The transmitter can accept another packet
00476       osSetEvent(&interface->nicTxEvent);
00477    }
00478 
00479    //Data successfully written
00480    return NO_ERROR;
00481 }
00482 
00483 
00484 /**
00485  * @brief Receive a packet
00486  * @param[in] interface Underlying network interface
00487  * @return Error code
00488  **/
00489 
00490 error_t str912EthReceivePacket(NetInterface *interface)
00491 {
00492    error_t error;
00493    size_t n;
00494    uint8_t *p;
00495 
00496    //The current buffer is available for reading?
00497    if(!(rxCurDmaDesc->status & ENET_RDES_STATUS_VALID))
00498    {
00499       //Make sure no error occurred
00500       if(!(rxCurDmaDesc->status & ENET_RDES_STATUS_ERROR))
00501       {
00502          //Point to the received frame
00503          p = (uint8_t *) (rxCurDmaDesc->start & ENET_RDES_START_ADDR);
00504 
00505          //Retrieve the length of the frame
00506          n = rxCurDmaDesc->status & ENET_RDES_STATUS_FL;
00507          //Limit the number of data to read
00508          n = MIN(n, STR912_ETH_RX_BUFFER_SIZE);
00509 
00510          //Pass the packet to the upper layer
00511          nicProcessPacket(interface, p, n);
00512 
00513          //Valid packet received
00514          error = NO_ERROR;
00515       }
00516       else
00517       {
00518          //The received packet contains an error
00519          error = ERROR_INVALID_PACKET;
00520       }
00521 
00522       //Give the ownership of the descriptor back to the DMA
00523       rxCurDmaDesc->status = ENET_RDES_STATUS_VALID;
00524       //Point to the next descriptor in the list
00525       rxCurDmaDesc = (Str912RxDmaDesc *) (rxCurDmaDesc->next & ENET_RDES_NEXT_ADDR);
00526    }
00527    else
00528    {
00529       //No more data in the receive buffer
00530       error = ERROR_BUFFER_EMPTY;
00531    }
00532 
00533    //Instruct the DMA to poll the receive descriptor list
00534    ENET_DMA->RXSTR |= ENET_RXSTR_START_FETCH;
00535 
00536    //Return status code
00537    return error;
00538 }
00539 
00540 
00541 /**
00542  * @brief Configure multicast MAC address filtering
00543  * @param[in] interface Underlying network interface
00544  * @return Error code
00545  **/
00546 
00547 error_t str912EthSetMulticastFilter(NetInterface *interface)
00548 {
00549    uint_t i;
00550    uint_t k;
00551    uint32_t crc;
00552    uint32_t hashTable[2];
00553    MacFilterEntry *entry;
00554 
00555    //Debug message
00556    TRACE_DEBUG("Updating STR912 hash table...\r\n");
00557 
00558    //Clear hash table
00559    hashTable[0] = 0;
00560    hashTable[1] = 0;
00561 
00562    //The MAC filter table contains the multicast MAC addresses
00563    //to accept when receiving an Ethernet frame
00564    for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++)
00565    {
00566       //Point to the current entry
00567       entry = &interface->macMulticastFilter[i];
00568 
00569       //Valid entry?
00570       if(entry->refCount > 0)
00571       {
00572          //Compute CRC over the current MAC address
00573          crc = str912EthCalcCrc(&entry->addr, sizeof(MacAddr));
00574 
00575          //The upper 6 bits in the CRC register are used to index the
00576          //contents of the hash table
00577          k = (crc >> 26) & 0x3F;
00578 
00579          //Update hash table contents
00580          hashTable[k / 32] |= (1 << (k % 32));
00581       }
00582    }
00583 
00584    //Write the hash table
00585    ENET_MAC->MCLA = hashTable[0];
00586    ENET_MAC->MCHA = hashTable[1];
00587 
00588    //Debug message
00589    TRACE_DEBUG("  ENET_MCLA = %08" PRIX32 "\r\n", ENET_MAC->MCLA);
00590    TRACE_DEBUG("  ENET_MCHA = %08" PRIX32 "\r\n", ENET_MAC->MCHA);
00591 
00592    //Successful processing
00593    return NO_ERROR;
00594 }
00595 
00596 
00597 /**
00598  * @brief Adjust MAC configuration parameters for proper operation
00599  * @param[in] interface Underlying network interface
00600  * @return Error code
00601  **/
00602 
00603 error_t str912EthUpdateMacConfig(NetInterface *interface)
00604 {
00605    uint32_t config;
00606 
00607    //Read current MAC configuration
00608    config = ENET_MAC->MCR;
00609 
00610    //Half-duplex or full-duplex mode?
00611    if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
00612    {
00613       //Full-duplex mode
00614       config |= ENET_MCR_FDM;
00615       //Enable the reception path during transmission
00616       config &= ~ENET_MCR_DRO;
00617    }
00618    else
00619    {
00620       //Half-duplex mode
00621       config &= ~ENET_MCR_FDM;
00622       //Disable the reception path during transmission
00623       config |= ENET_MCR_DRO;
00624    }
00625 
00626    //Update MAC configuration register
00627    ENET_MAC->MCR = config;
00628 
00629    //Successful processing
00630    return NO_ERROR;
00631 }
00632 
00633 
00634 /**
00635  * @brief Write PHY register
00636  * @param[in] phyAddr PHY address
00637  * @param[in] regAddr Register address
00638  * @param[in] data Register value
00639  **/
00640 
00641 void str912EthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data)
00642 {
00643    uint32_t value;
00644 
00645    //Set up a write operation
00646    value = ENET_MIIA_WR | ENET_MIIA_BUSY;
00647    //PHY address
00648    value |= (phyAddr << 11) & ENET_MIIA_PADDR;
00649    //Register address
00650    value |= (regAddr << 6) & ENET_MIIA_RADDR;
00651 
00652    //Data to be written in the PHY register
00653    ENET_MAC->MIID = data & ENET_MIID_RDATA;
00654 
00655    //Start a write operation
00656    ENET_MAC->MIIA = value;
00657    //Wait for the write to complete
00658    while(ENET_MAC->MIIA & ENET_MIIA_BUSY);
00659 }
00660 
00661 
00662 /**
00663  * @brief Read PHY register
00664  * @param[in] phyAddr PHY address
00665  * @param[in] regAddr Register address
00666  * @return Register value
00667  **/
00668 
00669 uint16_t str912EthReadPhyReg(uint8_t phyAddr, uint8_t regAddr)
00670 {
00671    uint32_t value;
00672 
00673    //Set up a read operation
00674    value = ENET_MIIA_BUSY;
00675    //PHY address
00676    value |= (phyAddr << 11) & ENET_MIIA_PADDR;
00677    //Register address
00678    value |= (regAddr << 6) & ENET_MIIA_RADDR;
00679 
00680    //Start a read operation
00681    ENET_MAC->MIIA = value;
00682    //Wait for the read to complete
00683    while(ENET_MAC->MIIA & ENET_MIIA_BUSY);
00684 
00685    //Return PHY register contents
00686    return ENET_MAC->MIID & ENET_MIID_RDATA;
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 str912EthCalcCrc(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