Sergey Pastor / 1

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tm4c129_eth.c Source File

tm4c129_eth.c

Go to the documentation of this file.
00001 /**
00002  * @file tm4c129_eth.c
00003  * @brief Tiva TM4C129 Ethernet 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 //TM4C1294NCPDT device?
00033 #if defined(PART_TM4C1294NCPDT)
00034    #include "tm4c1294ncpdt.h"
00035 //TM4C129XNCZAD device?
00036 #elif defined(PART_TM4C129XNCZAD)
00037    #include "tm4c129xnczad.h"
00038 #endif
00039 
00040 //Dependencies
00041 #include <stdint.h>
00042 #include <stdbool.h>
00043 #include "inc/hw_emac.h"
00044 #include "inc/hw_memmap.h"
00045 #include "inc/hw_types.h"
00046 #include "driverlib/gpio.h"
00047 #include "driverlib/interrupt.h"
00048 #include "driverlib/pin_map.h"
00049 #include "driverlib/sysctl.h"
00050 #include "core/net.h"
00051 #include "drivers/tm4c129_eth.h"
00052 #include "debug.h"
00053 
00054 //Underlying network interface
00055 static NetInterface *nicDriverInterface;
00056 
00057 //IAR EWARM compiler?
00058 #if defined(__ICCARM__)
00059 
00060 //Transmit buffer
00061 #pragma data_alignment = 4
00062 static uint8_t txBuffer[TM4C129_ETH_TX_BUFFER_COUNT][TM4C129_ETH_TX_BUFFER_SIZE];
00063 //Receive buffer
00064 #pragma data_alignment = 4
00065 static uint8_t rxBuffer[TM4C129_ETH_RX_BUFFER_COUNT][TM4C129_ETH_RX_BUFFER_SIZE];
00066 //Transmit DMA descriptors
00067 #pragma data_alignment = 4
00068 static Tm4c129TxDmaDesc txDmaDesc[TM4C129_ETH_TX_BUFFER_COUNT];
00069 //Receive DMA descriptors
00070 #pragma data_alignment = 4
00071 static Tm4c129RxDmaDesc rxDmaDesc[TM4C129_ETH_RX_BUFFER_COUNT];
00072 
00073 //Keil MDK-ARM or GCC compiler?
00074 #else
00075 
00076 //Transmit buffer
00077 static uint8_t txBuffer[TM4C129_ETH_TX_BUFFER_COUNT][TM4C129_ETH_TX_BUFFER_SIZE]
00078    __attribute__((aligned(4)));
00079 //Receive buffer
00080 static uint8_t rxBuffer[TM4C129_ETH_RX_BUFFER_COUNT][TM4C129_ETH_RX_BUFFER_SIZE]
00081    __attribute__((aligned(4)));
00082 //Transmit DMA descriptors
00083 static Tm4c129TxDmaDesc txDmaDesc[TM4C129_ETH_TX_BUFFER_COUNT]
00084    __attribute__((aligned(4)));
00085 //Receive DMA descriptors
00086 static Tm4c129RxDmaDesc rxDmaDesc[TM4C129_ETH_RX_BUFFER_COUNT]
00087    __attribute__((aligned(4)));
00088 
00089 #endif
00090 
00091 //Pointer to the current TX DMA descriptor
00092 static Tm4c129TxDmaDesc *txCurDmaDesc;
00093 //Pointer to the current RX DMA descriptor
00094 static Tm4c129RxDmaDesc *rxCurDmaDesc;
00095 
00096 
00097 /**
00098  * @brief Tiva TM4C129 Ethernet MAC driver
00099  **/
00100 
00101 const NicDriver tm4c129EthDriver =
00102 {
00103    NIC_TYPE_ETHERNET,
00104    ETH_MTU,
00105    tm4c129EthInit,
00106    tm4c129EthTick,
00107    tm4c129EthEnableIrq,
00108    tm4c129EthDisableIrq,
00109    tm4c129EthEventHandler,
00110    tm4c129EthSendPacket,
00111    tm4c129EthSetMulticastFilter,
00112    NULL,
00113    NULL,
00114    NULL,
00115    TRUE,
00116    TRUE,
00117    TRUE,
00118    FALSE
00119 };
00120 
00121 
00122 /**
00123  * @brief Tiva TM4C129 Ethernet MAC initialization
00124  * @param[in] interface Underlying network interface
00125  * @return Error code
00126  **/
00127 
00128 error_t tm4c129EthInit(NetInterface *interface)
00129 {
00130    //Debug message
00131    TRACE_INFO("Initializing Tiva TM4C129 Ethernet controller...\r\n");
00132 
00133    //Save underlying network interface
00134    nicDriverInterface = interface;
00135 
00136    //Enable Ethernet controller clock
00137    SysCtlPeripheralEnable(SYSCTL_PERIPH_EMAC0);
00138    //Reset Ethernet controller
00139    SysCtlPeripheralReset(SYSCTL_PERIPH_EMAC0);
00140    //Wait for the reset to complete
00141    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_EMAC0));
00142 
00143    //Enable internal PHY clock
00144    SysCtlPeripheralEnable(SYSCTL_PERIPH_EPHY0);
00145    //Reset internal PHY
00146    SysCtlPeripheralReset(SYSCTL_PERIPH_EPHY0);
00147    //Wait for the reset to complete
00148    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_EPHY0));
00149 
00150    //GPIO configuration
00151    tm4c129EthInitGpio(interface);
00152 
00153    //Perform a software reset
00154    EMAC0_DMABUSMOD_R |= EMAC_DMABUSMOD_SWR;
00155    //Wait for the reset to complete
00156    while(EMAC0_DMABUSMOD_R & EMAC_DMABUSMOD_SWR);
00157 
00158    //Adjust MDC clock range depending on SYSCLK frequency
00159    EMAC0_MIIADDR_R = EMAC_MIIADDR_CR_100_150;
00160 
00161    //Reset PHY transceiver
00162    tm4c129EthWritePhyReg(EPHY_BMCR, EPHY_BMCR_MIIRESET);
00163    //Wait for the reset to complete
00164    while(tm4c129EthReadPhyReg(EPHY_BMCR) & EPHY_BMCR_MIIRESET);
00165 
00166    //Dump PHY registers for debugging purpose
00167    tm4c129EthDumpPhyReg();
00168 
00169    //Configure LED0, LED1 and LED2
00170    tm4c129EthWritePhyReg(EPHY_LEDCFG, EPHY_LEDCFG_LED0_TX |
00171       EPHY_LEDCFG_LED1_RX | EPHY_LEDCFG_LED2_LINK);
00172 
00173    //Configure PHY interrupts as desired
00174    tm4c129EthWritePhyReg(EPHY_MISR1, EPHY_MISR1_LINKSTATEN);
00175    //Enable PHY interrupts
00176    tm4c129EthWritePhyReg(EPHY_SCR, EPHY_SCR_INTEN);
00177 
00178    //Use default MAC configuration
00179    EMAC0_CFG_R = EMAC_CFG_DRO;
00180 
00181    //Set the MAC address
00182    EMAC0_ADDR0L_R = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
00183    EMAC0_ADDR0H_R = interface->macAddr.w[2];
00184 
00185    //Initialize hash table
00186    EMAC0_HASHTBLL_R = 0;
00187    EMAC0_HASHTBLH_R = 0;
00188 
00189    //Configure the receive filter
00190    EMAC0_FRAMEFLTR_R = EMAC_FRAMEFLTR_HPF | EMAC_FRAMEFLTR_HMC;
00191    //Disable flow control
00192    EMAC0_FLOWCTL_R = 0;
00193    //Enable store and forward mode
00194    EMAC0_DMAOPMODE_R = EMAC_DMAOPMODE_RSF | EMAC_DMAOPMODE_TSF;
00195 
00196    //Configure DMA bus mode
00197    EMAC0_DMABUSMOD_R = EMAC_DMABUSMOD_AAL | EMAC_DMABUSMOD_USP | EMAC_DMABUSMOD_RPBL_1 |
00198       EMAC_DMABUSMOD_PR_1_1 | EMAC_DMABUSMOD_PBL_1 | EMAC_DMABUSMOD_ATDS;
00199 
00200    //Initialize DMA descriptor lists
00201    tm4c129EthInitDmaDesc(interface);
00202 
00203    //Prevent interrupts from being generated when the transmit statistic
00204    //counters reach half their maximum value
00205    EMAC0_MMCTXIM_R = EMAC_MMCTXIM_OCTCNT | EMAC_MMCTXIM_MCOLLGF |
00206       EMAC_MMCTXIM_SCOLLGF | EMAC_MMCTXIM_GBF;
00207 
00208    //Prevent interrupts from being generated when the receive statistic
00209    //counters reach half their maximum value
00210    EMAC0_MMCRXIM_R = EMAC_MMCRXIM_UCGF | EMAC_MMCRXIM_ALGNERR |
00211       EMAC_MMCRXIM_CRCERR | EMAC_MMCRXIM_GBF;
00212 
00213    //Disable MAC interrupts
00214    EMAC0_IM_R = EMAC_IM_TSI | EMAC_IM_PMT;
00215    //Enable the desired DMA interrupts
00216    EMAC0_DMAIM_R = EMAC_DMAIM_NIE | EMAC_DMAIM_RIE | EMAC_DMAIM_TIE;
00217    //Enable PHY interrupts
00218    EMAC0_EPHYIM_R = EMAC_EPHYIM_INT;
00219 
00220    //Set priority grouping (3 bits for pre-emption priority, no bits for subpriority)
00221    IntPriorityGroupingSet(TM4C129_ETH_IRQ_PRIORITY_GROUPING);
00222    //Configure Ethernet interrupt priority
00223    IntPrioritySet(INT_EMAC0, TM4C129_ETH_IRQ_PRIORITY);
00224 
00225    //Enable MAC transmission and reception
00226    EMAC0_CFG_R |= EMAC_CFG_TE | EMAC_CFG_RE;
00227    //Enable DMA transmission and reception
00228    EMAC0_DMAOPMODE_R |= EMAC_DMAOPMODE_ST | EMAC_DMAOPMODE_SR;
00229 
00230    //Accept any packets from the upper layer
00231    osSetEvent(&interface->nicTxEvent);
00232 
00233    //Successful initialization
00234    return NO_ERROR;
00235 }
00236 
00237 
00238 //DK-TM4C129X or EK-TM4C1294XL evaluation board?
00239 #if defined(USE_DK_TM4C129X) || defined(USE_EK_TM4C1294XL)
00240 
00241 /**
00242  * @brief GPIO configuration
00243  * @param[in] interface Underlying network interface
00244  **/
00245 
00246 void tm4c129EthInitGpio(NetInterface *interface)
00247 {
00248 //DK-TM4C129X evaluation board?
00249 #if defined(USE_DK_TM4C129X)
00250    //Enable GPIO clocks
00251    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
00252    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);
00253 
00254    //Select the relevant alternate function for PF1, PK4 and PK6
00255    GPIOPinConfigure(GPIO_PF1_EN0LED2);
00256    GPIOPinConfigure(GPIO_PK4_EN0LED0);
00257    GPIOPinConfigure(GPIO_PK6_EN0LED1);
00258 
00259    //Configure Ethernet LED pins for proper operation
00260    GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_1);
00261    GPIOPinTypeEthernetLED(GPIO_PORTK_BASE, GPIO_PIN_4 | GPIO_PIN_6);
00262 
00263 //EK-TM4C1294XL evaluation board?
00264 #elif defined(USE_EK_TM4C1294XL)
00265    //Enable GPIO clock
00266    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
00267 
00268    //Select the relevant alternate function for PF0 and PF4
00269    GPIOPinConfigure(GPIO_PF0_EN0LED0);
00270    GPIOPinConfigure(GPIO_PF4_EN0LED1);
00271 
00272    //Configure Ethernet LED pins for proper operation
00273    GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4);
00274 #endif
00275 }
00276 
00277 #endif
00278 
00279 
00280 /**
00281  * @brief Initialize DMA descriptor lists
00282  * @param[in] interface Underlying network interface
00283  **/
00284 
00285 void tm4c129EthInitDmaDesc(NetInterface *interface)
00286 {
00287    uint_t i;
00288 
00289    //Initialize TX DMA descriptor list
00290    for(i = 0; i < TM4C129_ETH_TX_BUFFER_COUNT; i++)
00291    {
00292       //Use chain structure rather than ring structure
00293       txDmaDesc[i].tdes0 = EMAC_TDES0_IC | EMAC_TDES0_TCH;
00294       //Initialize transmit buffer size
00295       txDmaDesc[i].tdes1 = 0;
00296       //Transmit buffer address
00297       txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
00298       //Next descriptor address
00299       txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
00300       //Reserved fields
00301       txDmaDesc[i].tdes4 = 0;
00302       txDmaDesc[i].tdes5 = 0;
00303       //Transmit frame time stamp
00304       txDmaDesc[i].tdes6 = 0;
00305       txDmaDesc[i].tdes7 = 0;
00306    }
00307 
00308    //The last descriptor is chained to the first entry
00309    txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
00310    //Point to the very first descriptor
00311    txCurDmaDesc = &txDmaDesc[0];
00312 
00313    //Initialize RX DMA descriptor list
00314    for(i = 0; i < TM4C129_ETH_RX_BUFFER_COUNT; i++)
00315    {
00316       //The descriptor is initially owned by the DMA
00317       rxDmaDesc[i].rdes0 = EMAC_RDES0_OWN;
00318       //Use chain structure rather than ring structure
00319       rxDmaDesc[i].rdes1 = EMAC_RDES1_RCH | (TM4C129_ETH_RX_BUFFER_SIZE & EMAC_RDES1_RBS1);
00320       //Receive buffer address
00321       rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
00322       //Next descriptor address
00323       rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
00324       //Extended status
00325       rxDmaDesc[i].rdes4 = 0;
00326       //Reserved field
00327       rxDmaDesc[i].rdes5 = 0;
00328       //Receive frame time stamp
00329       rxDmaDesc[i].rdes6 = 0;
00330       rxDmaDesc[i].rdes7 = 0;
00331    }
00332 
00333    //The last descriptor is chained to the first entry
00334    rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
00335    //Point to the very first descriptor
00336    rxCurDmaDesc = &rxDmaDesc[0];
00337 
00338    //Start location of the TX descriptor list
00339    EMAC0_TXDLADDR_R = (uint32_t) txDmaDesc;
00340    //Start location of the RX descriptor list
00341    EMAC0_RXDLADDR_R = (uint32_t) rxDmaDesc;
00342 }
00343 
00344 
00345 /**
00346  * @brief TM4C129 Ethernet MAC timer handler
00347  *
00348  * This routine is periodically called by the TCP/IP stack to
00349  * handle periodic operations such as polling the link state
00350  *
00351  * @param[in] interface Underlying network interface
00352  **/
00353 
00354 void tm4c129EthTick(NetInterface *interface)
00355 {
00356 }
00357 
00358 
00359 /**
00360  * @brief Enable interrupts
00361  * @param[in] interface Underlying network interface
00362  **/
00363 
00364 void tm4c129EthEnableIrq(NetInterface *interface)
00365 {
00366    //Enable Ethernet MAC interrupts
00367    IntEnable(INT_EMAC0);
00368 }
00369 
00370 
00371 /**
00372  * @brief Disable interrupts
00373  * @param[in] interface Underlying network interface
00374  **/
00375 
00376 void tm4c129EthDisableIrq(NetInterface *interface)
00377 {
00378    //Disable Ethernet MAC interrupts
00379    IntDisable(INT_EMAC0);
00380 }
00381 
00382 
00383 /**
00384  * @brief TM4C129 Ethernet MAC interrupt service routine
00385  **/
00386 
00387 void EMAC0_Handler(void)
00388 {
00389    bool_t flag;
00390    uint32_t status;
00391 
00392    //Enter interrupt service routine
00393    osEnterIsr();
00394 
00395    //This flag will be set if a higher priority task must be woken
00396    flag = FALSE;
00397 
00398    //Read PHY status register
00399    status = EMAC0_EPHYRIS_R;
00400 
00401    //PHY interrupt?
00402    if(status & EMAC_EPHYRIS_INT)
00403    {
00404       //Disable PHY interrupt
00405       EMAC0_EPHYIM_R &= ~EMAC_EPHYIM_INT;
00406 
00407       //Set event flag
00408       nicDriverInterface->nicEvent = TRUE;
00409       //Notify the TCP/IP stack of the event
00410       flag |= osSetEventFromIsr(&netEvent);
00411    }
00412 
00413    //Read DMA status register
00414    status = EMAC0_DMARIS_R;
00415 
00416    //A packet has been transmitted?
00417    if(status & EMAC_DMARIS_TI)
00418    {
00419       //Clear TI interrupt flag
00420       EMAC0_DMARIS_R = EMAC_DMARIS_TI;
00421 
00422       //Check whether the TX buffer is available for writing
00423       if(!(txCurDmaDesc->tdes0 & EMAC_TDES0_OWN))
00424       {
00425          //Notify the TCP/IP stack that the transmitter is ready to send
00426          flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
00427       }
00428    }
00429 
00430    //A packet has been received?
00431    if(status & EMAC_DMARIS_RI)
00432    {
00433       //Disable RIE interrupt
00434       EMAC0_DMAIM_R &= ~EMAC_DMAIM_RIE;
00435 
00436       //Set event flag
00437       nicDriverInterface->nicEvent = TRUE;
00438       //Notify the TCP/IP stack of the event
00439       flag |= osSetEventFromIsr(&netEvent);
00440    }
00441 
00442    //Clear NIS interrupt flag
00443    EMAC0_DMARIS_R = EMAC_DMARIS_NIS;
00444 
00445    //Leave interrupt service routine
00446    osExitIsr(flag);
00447 }
00448 
00449 
00450 /**
00451  * @brief TM4C129 Ethernet MAC event handler
00452  * @param[in] interface Underlying network interface
00453  **/
00454 
00455 void tm4c129EthEventHandler(NetInterface *interface)
00456 {
00457    error_t error;
00458    uint32_t status;
00459 
00460    //PHY interrupt?
00461    if(EMAC0_EPHYRIS_R & EMAC_EPHYRIS_INT)
00462    {
00463       //Clear PHY interrupt flag
00464       EMAC0_EPHYMISC_R = EMAC_EPHYMISC_INT;
00465       //Read PHY interrupt status register
00466       status = tm4c129EthReadPhyReg(EPHY_MISR1);
00467 
00468       //Check whether the link state has changed?
00469       if(status & EPHY_MISR1_LINKSTAT)
00470       {
00471          //Read BMSR register
00472          status = tm4c129EthReadPhyReg(EPHY_BMSR);
00473 
00474          //Check whether link is up?
00475          if(status & EPHY_BMSR_LINKSTAT)
00476          {
00477             //Read PHY status register
00478             status = tm4c129EthReadPhyReg(EPHY_STS);
00479 
00480             //Check current speed
00481             if(status & EPHY_STS_SPEED)
00482             {
00483                //10BASE-T operation
00484                interface->linkSpeed = NIC_LINK_SPEED_10MBPS;
00485                //Update MAC configuration
00486                EMAC0_CFG_R &= ~EMAC_CFG_FES;
00487             }
00488             else
00489             {
00490                //100BASE-TX operation
00491                interface->linkSpeed = NIC_LINK_SPEED_100MBPS;
00492                //Update MAC configuration
00493                EMAC0_CFG_R |= EMAC_CFG_FES;
00494             }
00495 
00496             //Check current duplex mode
00497             if(status & EPHY_STS_DUPLEX)
00498             {
00499                //Full-Duplex mode
00500                interface->duplexMode = NIC_FULL_DUPLEX_MODE;
00501                //Update MAC configuration
00502                EMAC0_CFG_R |= EMAC_CFG_DUPM;
00503             }
00504             else
00505             {
00506                //Half-Duplex mode
00507                interface->duplexMode = NIC_HALF_DUPLEX_MODE;
00508                //Update MAC configuration
00509                EMAC0_CFG_R &= ~EMAC_CFG_DUPM;
00510             }
00511 
00512             //Update link state
00513             interface->linkState = TRUE;
00514          }
00515          else
00516          {
00517             //Update link state
00518             interface->linkState = FALSE;
00519          }
00520 
00521          //Process link state change event
00522          nicNotifyLinkChange(interface);
00523       }
00524    }
00525 
00526    //Packet received?
00527    if(EMAC0_DMARIS_R & EMAC_DMARIS_RI)
00528    {
00529       //Clear interrupt flag
00530       EMAC0_DMARIS_R = EMAC_DMARIS_RI;
00531 
00532       //Process all pending packets
00533       do
00534       {
00535          //Read incoming packet
00536          error = tm4c129EthReceivePacket(interface);
00537 
00538          //No more data in the receive buffer?
00539       } while(error != ERROR_BUFFER_EMPTY);
00540    }
00541 
00542    //Re-enable DMA interrupts
00543    EMAC0_DMAIM_R |= EMAC_DMAIM_NIE | EMAC_DMAIM_RIE | EMAC_DMAIM_TIE;
00544    //Re-enable PHY interrupts
00545    EMAC0_EPHYIM_R |= EMAC_EPHYIM_INT;
00546 }
00547 
00548 
00549 /**
00550  * @brief Send a packet
00551  * @param[in] interface Underlying network interface
00552  * @param[in] buffer Multi-part buffer containing the data to send
00553  * @param[in] offset Offset to the first data byte
00554  * @return Error code
00555  **/
00556 
00557 error_t tm4c129EthSendPacket(NetInterface *interface,
00558    const NetBuffer *buffer, size_t offset)
00559 {
00560    size_t length;
00561 
00562    //Retrieve the length of the packet
00563    length = netBufferGetLength(buffer) - offset;
00564 
00565    //Check the frame length
00566    if(length > TM4C129_ETH_TX_BUFFER_SIZE)
00567    {
00568       //The transmitter can accept another packet
00569       osSetEvent(&interface->nicTxEvent);
00570       //Report an error
00571       return ERROR_INVALID_LENGTH;
00572    }
00573 
00574    //Make sure the current buffer is available for writing
00575    if(txCurDmaDesc->tdes0 & EMAC_TDES0_OWN)
00576       return ERROR_FAILURE;
00577 
00578    //Copy user data to the transmit buffer
00579    netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
00580 
00581    //Write the number of bytes to send
00582    txCurDmaDesc->tdes1 = length & EMAC_TDES1_TBS1;
00583    //Set LS and FS flags as the data fits in a single buffer
00584    txCurDmaDesc->tdes0 |= EMAC_TDES0_LS | EMAC_TDES0_FS;
00585    //Give the ownership of the descriptor to the DMA
00586    txCurDmaDesc->tdes0 |= EMAC_TDES0_OWN;
00587 
00588    //Clear TU flag to resume processing
00589    EMAC0_DMARIS_R = EMAC_DMARIS_TU;
00590    //Instruct the DMA to poll the transmit descriptor list
00591    EMAC0_TXPOLLD_R = 0;
00592 
00593    //Point to the next descriptor in the list
00594    txCurDmaDesc = (Tm4c129TxDmaDesc *) txCurDmaDesc->tdes3;
00595 
00596    //Check whether the next buffer is available for writing
00597    if(!(txCurDmaDesc->tdes0 & EMAC_TDES0_OWN))
00598    {
00599       //The transmitter can accept another packet
00600       osSetEvent(&interface->nicTxEvent);
00601    }
00602 
00603    //Data successfully written
00604    return NO_ERROR;
00605 }
00606 
00607 
00608 /**
00609  * @brief Receive a packet
00610  * @param[in] interface Underlying network interface
00611  * @return Error code
00612  **/
00613 
00614 error_t tm4c129EthReceivePacket(NetInterface *interface)
00615 {
00616    error_t error;
00617    size_t n;
00618 
00619    //The current buffer is available for reading?
00620    if(!(rxCurDmaDesc->rdes0 & EMAC_RDES0_OWN))
00621    {
00622       //FS and LS flags should be set
00623       if((rxCurDmaDesc->rdes0 & EMAC_RDES0_FS) && (rxCurDmaDesc->rdes0 & EMAC_RDES0_LS))
00624       {
00625          //Make sure no error occurred
00626          if(!(rxCurDmaDesc->rdes0 & EMAC_RDES0_ES))
00627          {
00628             //Retrieve the length of the frame
00629             n = (rxCurDmaDesc->rdes0 & EMAC_RDES0_FL) >> 16;
00630             //Limit the number of data to read
00631             n = MIN(n, TM4C129_ETH_RX_BUFFER_SIZE);
00632 
00633             //Pass the packet to the upper layer
00634             nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n);
00635 
00636             //Valid packet received
00637             error = NO_ERROR;
00638          }
00639          else
00640          {
00641             //The received packet contains an error
00642             error = ERROR_INVALID_PACKET;
00643          }
00644       }
00645       else
00646       {
00647          //The packet is not valid
00648          error = ERROR_INVALID_PACKET;
00649       }
00650 
00651       //Give the ownership of the descriptor back to the DMA
00652       rxCurDmaDesc->rdes0 = EMAC_RDES0_OWN;
00653       //Point to the next descriptor in the list
00654       rxCurDmaDesc = (Tm4c129RxDmaDesc *) rxCurDmaDesc->rdes3;
00655    }
00656    else
00657    {
00658       //No more data in the receive buffer
00659       error = ERROR_BUFFER_EMPTY;
00660    }
00661 
00662    //Clear RU flag to resume processing
00663    EMAC0_DMARIS_R = EMAC_DMARIS_RU;
00664    //Instruct the DMA to poll the receive descriptor list
00665    EMAC0_RXPOLLD_R = 0;
00666 
00667    //Return status code
00668    return error;
00669 }
00670 
00671 
00672 /**
00673  * @brief Configure multicast MAC address filtering
00674  * @param[in] interface Underlying network interface
00675  * @return Error code
00676  **/
00677 
00678 error_t tm4c129EthSetMulticastFilter(NetInterface *interface)
00679 {
00680    uint_t i;
00681    uint_t k;
00682    uint32_t crc;
00683    uint32_t hashTable[2];
00684    MacFilterEntry *entry;
00685 
00686    //Debug message
00687    TRACE_DEBUG("Updating Tiva TM4C129 hash table...\r\n");
00688 
00689    //Clear hash table
00690    hashTable[0] = 0;
00691    hashTable[1] = 0;
00692 
00693    //The MAC filter table contains the multicast MAC addresses
00694    //to accept when receiving an Ethernet frame
00695    for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++)
00696    {
00697       //Point to the current entry
00698       entry = &interface->macMulticastFilter[i];
00699 
00700       //Valid entry?
00701       if(entry->refCount > 0)
00702       {
00703          //Compute CRC over the current MAC address
00704          crc = tm4c129EthCalcCrc(&entry->addr, sizeof(MacAddr));
00705 
00706          //The upper 6 bits in the CRC register are used to index the
00707          //contents of the hash table
00708          k = (crc >> 26) & 0x3F;
00709 
00710          //Update hash table contents
00711          hashTable[k / 32] |= (1 << (k % 32));
00712       }
00713    }
00714 
00715    //Write the hash table
00716    EMAC0_HASHTBLL_R = hashTable[0];
00717    EMAC0_HASHTBLH_R = hashTable[1];
00718 
00719    //Debug message
00720    TRACE_DEBUG("  HASHTBLL = %08" PRIX32 "\r\n", EMAC0_HASHTBLL_R);
00721    TRACE_DEBUG("  HASHTBLH = %08" PRIX32 "\r\n", EMAC0_HASHTBLH_R);
00722 
00723    //Successful processing
00724    return NO_ERROR;
00725 }
00726 
00727 
00728 /**
00729  * @brief Write PHY register
00730  * @param[in] regAddr Register address
00731  * @param[in] data Register value
00732  **/
00733 
00734 void tm4c129EthWritePhyReg(uint8_t regAddr, uint16_t data)
00735 {
00736    uint32_t value;
00737 
00738    //Take care not to alter MDC clock configuration
00739    value = EMAC0_MIIADDR_R & EMAC_MIIADDR_CR_M;
00740    //Set up a write operation
00741    value |= EMAC_MIIADDR_MIIW | EMAC_MIIADDR_MIIB;
00742    //The address of the integrated PHY is 0
00743    value |= (0 << EMAC_MIIADDR_PLA_S) & EMAC_MIIADDR_PLA_M;
00744    //Register address
00745    value |= (regAddr << EMAC_MIIADDR_MII_S) & EMAC_MIIADDR_MII_M;
00746 
00747    //Data to be written in the PHY register
00748    EMAC0_MIIDATA_R = data & EMAC_MIIDATA_DATA_M;
00749 
00750    //Start a write operation
00751    EMAC0_MIIADDR_R = value;
00752    //Wait for the write to complete
00753    while(EMAC0_MIIADDR_R & EMAC_MIIADDR_MIIB);
00754 }
00755 
00756 
00757 /**
00758  * @brief Read PHY register
00759  * @param[in] regAddr Register address
00760  * @return Register value
00761  **/
00762 
00763 uint16_t tm4c129EthReadPhyReg(uint8_t regAddr)
00764 {
00765    uint32_t value;
00766 
00767    //Take care not to alter MDC clock configuration
00768    value = EMAC0_MIIADDR_R & EMAC_MIIADDR_CR_M;
00769    //Set up a read operation
00770    value |= EMAC_MIIADDR_MIIB;
00771    //The address of the integrated PHY is 0
00772    value |= (0 << EMAC_MIIADDR_PLA_S) & EMAC_MIIADDR_PLA_M;
00773    //Register address
00774    value |= (regAddr << EMAC_MIIADDR_MII_S) & EMAC_MIIADDR_MII_M;
00775 
00776    //Start a read operation
00777    EMAC0_MIIADDR_R = value;
00778    //Wait for the read to complete
00779    while(EMAC0_MIIADDR_R & EMAC_MIIADDR_MIIB);
00780 
00781    //Return PHY register contents
00782    return EMAC0_MIIDATA_R & EMAC_MIIDATA_DATA_M;
00783 }
00784 
00785 
00786 /**
00787  * @brief Dump PHY registers for debugging purpose
00788  **/
00789 
00790 void tm4c129EthDumpPhyReg(void)
00791 {
00792    uint8_t i;
00793 
00794    //Loop through PHY registers
00795    for(i = 0; i < 32; i++)
00796    {
00797       //Display current PHY register
00798       TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i, tm4c129EthReadPhyReg(i));
00799    }
00800 
00801    //Terminate with a line feed
00802    TRACE_DEBUG("\r\n");
00803 }
00804 
00805 
00806 /**
00807  * @brief CRC calculation
00808  * @param[in] data Pointer to the data over which to calculate the CRC
00809  * @param[in] length Number of bytes to process
00810  * @return Resulting CRC value
00811  **/
00812 
00813 uint32_t tm4c129EthCalcCrc(const void *data, size_t length)
00814 {
00815    uint_t i;
00816    uint_t j;
00817 
00818    //Point to the data over which to calculate the CRC
00819    const uint8_t *p = (uint8_t *) data;
00820    //CRC preset value
00821    uint32_t crc = 0xFFFFFFFF;
00822 
00823    //Loop through data
00824    for(i = 0; i < length; i++)
00825    {
00826       //The message is processed bit by bit
00827       for(j = 0; j < 8; j++)
00828       {
00829          //Update CRC value
00830          if(((crc >> 31) ^ (p[i] >> j)) & 0x01)
00831             crc = (crc << 1) ^ 0x04C11DB7;
00832          else
00833             crc = crc << 1;
00834       }
00835    }
00836 
00837    //Return CRC value
00838    return ~crc;
00839 }
00840