Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
tm4c129_eth.c
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
Generated on Tue Jul 12 2022 17:10:17 by
