Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
fm4_eth.c
Go to the documentation of this file.
00001 /** 00002 * @file fm4_eth.c 00003 * @brief Spansion FM4 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 "s6e2cc.h" 00034 #include "core/net.h" 00035 #include "drivers/fm4_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[FM4_ETH_TX_BUFFER_COUNT][FM4_ETH_TX_BUFFER_SIZE]; 00047 //Receive buffer 00048 #pragma data_alignment = 4 00049 static uint8_t rxBuffer[FM4_ETH_RX_BUFFER_COUNT][FM4_ETH_RX_BUFFER_SIZE]; 00050 //Transmit DMA descriptors 00051 #pragma data_alignment = 4 00052 static Fm4TxDmaDesc txDmaDesc[FM4_ETH_TX_BUFFER_COUNT]; 00053 //Receive DMA descriptors 00054 #pragma data_alignment = 4 00055 static Fm4RxDmaDesc rxDmaDesc[FM4_ETH_RX_BUFFER_COUNT]; 00056 00057 //Keil MDK-ARM or GCC compiler? 00058 #else 00059 00060 //Transmit buffer 00061 static uint8_t txBuffer[FM4_ETH_TX_BUFFER_COUNT][FM4_ETH_TX_BUFFER_SIZE] 00062 __attribute__((aligned(4))); 00063 //Receive buffer 00064 static uint8_t rxBuffer[FM4_ETH_RX_BUFFER_COUNT][FM4_ETH_RX_BUFFER_SIZE] 00065 __attribute__((aligned(4))); 00066 //Transmit DMA descriptors 00067 static Fm4TxDmaDesc txDmaDesc[FM4_ETH_TX_BUFFER_COUNT] 00068 __attribute__((aligned(4))); 00069 //Receive DMA descriptors 00070 static Fm4RxDmaDesc rxDmaDesc[FM4_ETH_RX_BUFFER_COUNT] 00071 __attribute__((aligned(4))); 00072 00073 #endif 00074 00075 //Pointer to the current TX DMA descriptor 00076 static Fm4TxDmaDesc *txCurDmaDesc; 00077 //Pointer to the current RX DMA descriptor 00078 static Fm4RxDmaDesc *rxCurDmaDesc; 00079 00080 00081 /** 00082 * @brief Spansion FM4 Ethernet MAC driver 00083 **/ 00084 00085 const NicDriver fm4EthDriver = 00086 { 00087 NIC_TYPE_ETHERNET, 00088 ETH_MTU, 00089 fm4EthInit, 00090 fm4EthTick, 00091 fm4EthEnableIrq, 00092 fm4EthDisableIrq, 00093 fm4EthEventHandler, 00094 fm4EthSendPacket, 00095 fm4EthSetMulticastFilter, 00096 fm4EthUpdateMacConfig, 00097 fm4EthWritePhyReg, 00098 fm4EthReadPhyReg, 00099 TRUE, 00100 TRUE, 00101 TRUE, 00102 FALSE 00103 }; 00104 00105 00106 /** 00107 * @brief Spansion FM4 Ethernet MAC initialization 00108 * @param[in] interface Underlying network interface 00109 * @return Error code 00110 **/ 00111 00112 error_t fm4EthInit(NetInterface *interface) 00113 { 00114 error_t error; 00115 00116 //Debug message 00117 TRACE_INFO("Initializing Spansion FM4 Ethernet MAC...\r\n"); 00118 00119 //Save underlying network interface 00120 nicDriverInterface = interface; 00121 00122 //GPIO configuration 00123 fm4EthInitGpio(interface); 00124 00125 //Enable Ethernet MAC clock 00126 FM4_ETHERNET_CONTROL->ETH_CLKG_f.MACEN = 1; 00127 00128 //Reset Ethernet MAC peripheral 00129 FM4_ETHERNET_CONTROL->ETH_MODE_f.RST0 = 1; 00130 FM4_ETHERNET_CONTROL->ETH_MODE_f.RST0 = 0; 00131 00132 //Perform a software reset 00133 FM4_ETHERNET_MAC0->BMR_f.SWR = 1; 00134 //Wait for the reset to complete 00135 while(FM4_ETHERNET_MAC0->BMR_f.SWR); 00136 00137 //Ensure that ongoing AHB transactions are complete 00138 while(FM4_ETHERNET_MAC0->AHBSR_f.AHBS); 00139 00140 //Adjust MDC clock range depending on HCLK frequency 00141 FM4_ETHERNET_MAC0->GAR_f.CR = 5; 00142 00143 //PHY transceiver initialization 00144 error = interface->phyDriver->init(interface); 00145 //Failed to initialize PHY transceiver? 00146 if(error) 00147 return error; 00148 00149 //Use default MAC configuration 00150 FM4_ETHERNET_MAC0->MCR = 0; 00151 FM4_ETHERNET_MAC0->MCR_f.PS = 1; 00152 FM4_ETHERNET_MAC0->MCR_f.DO = 1; 00153 00154 //Set the MAC address 00155 FM4_ETHERNET_MAC0->MAR0L = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16); 00156 FM4_ETHERNET_MAC0->MAR0H = interface->macAddr.w[2]; 00157 00158 //Initialize hash table 00159 FM4_ETHERNET_MAC0->MHTRL = 0; 00160 FM4_ETHERNET_MAC0->MHTRH = 0; 00161 00162 //Configure the receive filter 00163 FM4_ETHERNET_MAC0->MFFR = 0; 00164 FM4_ETHERNET_MAC0->MFFR_f.HPF = 1; 00165 FM4_ETHERNET_MAC0->MFFR_f.HMC = 1; 00166 00167 //Disable flow control 00168 FM4_ETHERNET_MAC0->FCR = 0; 00169 00170 //Enable store and forward mode 00171 FM4_ETHERNET_MAC0->OMR = 0; 00172 FM4_ETHERNET_MAC0->OMR_f.RSF = 1; 00173 FM4_ETHERNET_MAC0->OMR_f.TSF = 1; 00174 00175 //Configure DMA bus mode 00176 FM4_ETHERNET_MAC0->BMR = 0; 00177 FM4_ETHERNET_MAC0->BMR_f.TXPR = 0; 00178 FM4_ETHERNET_MAC0->BMR_f.MB = 1; 00179 FM4_ETHERNET_MAC0->BMR_f.AAL = 0; 00180 FM4_ETHERNET_MAC0->BMR_f._8XPBL = 0; 00181 FM4_ETHERNET_MAC0->BMR_f.USP = 1; 00182 FM4_ETHERNET_MAC0->BMR_f.RPBL = 1; 00183 FM4_ETHERNET_MAC0->BMR_f.FB = 0; 00184 FM4_ETHERNET_MAC0->BMR_f.PR = 0; 00185 FM4_ETHERNET_MAC0->BMR_f.PBL = 1; 00186 FM4_ETHERNET_MAC0->BMR_f.ATDS = 1; 00187 FM4_ETHERNET_MAC0->BMR_f.DSL = 0; 00188 FM4_ETHERNET_MAC0->BMR_f.DA = 0; 00189 00190 //Initialize DMA descriptor lists 00191 fm4EthInitDmaDesc(interface); 00192 00193 //Prevent interrupts from being generated when statistic counters reach 00194 //half their maximum value 00195 FM4_ETHERNET_MAC0->mmc_intr_mask_tx = 0xFFFFFFFF; 00196 FM4_ETHERNET_MAC0->mmc_intr_mask_rx = 0xFFFFFFFF; 00197 FM4_ETHERNET_MAC0->mmc_ipc_intr_mask_rx = 0xFFFFFFFF; 00198 00199 //Disable MAC interrupts 00200 bFM4_ETHERNET_MAC0_IMR_LPIIM = 1; 00201 bFM4_ETHERNET_MAC0_IMR_TSIM = 1; 00202 bFM4_ETHERNET_MAC0_IMR_PIM = 1; 00203 bFM4_ETHERNET_MAC0_IMR_RGIM = 1; 00204 00205 //Enable the desired DMA interrupts 00206 bFM4_ETHERNET_MAC0_IER_NIE = 1; 00207 bFM4_ETHERNET_MAC0_IER_RIE = 1; 00208 bFM4_ETHERNET_MAC0_IER_TIE = 1; 00209 00210 //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority) 00211 NVIC_SetPriorityGrouping(FM4_ETH_IRQ_PRIORITY_GROUPING); 00212 00213 //Configure Ethernet interrupt priority 00214 NVIC_SetPriority(ETHER0_IRQn, NVIC_EncodePriority(FM4_ETH_IRQ_PRIORITY_GROUPING, 00215 FM4_ETH_IRQ_GROUP_PRIORITY, FM4_ETH_IRQ_SUB_PRIORITY)); 00216 00217 //Enable MAC transmission and reception 00218 bFM4_ETHERNET_MAC0_MCR_TE = 1; 00219 bFM4_ETHERNET_MAC0_MCR_RE = 1; 00220 00221 //Enable DMA transmission and reception 00222 bFM4_ETHERNET_MAC0_OMR_ST = 1; 00223 bFM4_ETHERNET_MAC0_OMR_SR = 1; 00224 00225 //Accept any packets from the upper layer 00226 osSetEvent(&interface->nicTxEvent); 00227 00228 //Successful initialization 00229 return NO_ERROR; 00230 } 00231 00232 00233 //SK-FM4-176L-S6E2CC-ETH evaluation board? 00234 #if defined(USE_SK_FM4_176L_S6E2CC_ETH) 00235 00236 /** 00237 * @brief GPIO configuration 00238 * @param[in] interface Underlying network interface 00239 **/ 00240 00241 void fm4EthInitGpio(NetInterface *interface) 00242 { 00243 //Select MII interface mode 00244 FM4_ETHERNET_CONTROL->ETH_MODE_f.IFMODE = 0; 00245 00246 //Configure E_RXER (PC0) 00247 FM4_GPIO->PFRC_f.P0 = 1; 00248 //Configure E_RX03 (PC1) 00249 FM4_GPIO->PFRC_f.P1 = 1; 00250 //Configure E_RX02 (PC2) 00251 FM4_GPIO->PFRC_f.P2 = 1; 00252 //Configure E_RX01 (PC3) 00253 FM4_GPIO->PFRC_f.P3 = 1; 00254 //Configure E_RX00 (PC4) 00255 FM4_GPIO->PFRC_f.P4 = 1; 00256 //Configure E_RXDV (PC5) 00257 FM4_GPIO->PFRC_f.P5 = 1; 00258 //Configure E_MDIO (PC6) 00259 FM4_GPIO->PFRC_f.P6 = 1; 00260 //Configure E_MDC (PC7) 00261 FM4_GPIO->PFRC_f.P7 = 1; 00262 //Configure E_RXCK_REFCK (PC8) 00263 FM4_GPIO->PFRC_f.P8 = 1; 00264 //Configure E_COL (PC9) 00265 FM4_GPIO->PFRC_f.P9 = 1; 00266 //Configure E_CRS (PCA) 00267 FM4_GPIO->PFRC_f.PA = 1; 00268 //Configure E_TCK (PCC) 00269 FM4_GPIO->PFRC_f.PC = 1; 00270 //Configure E_TXER (PCD) 00271 FM4_GPIO->PFRC_f.PD = 1; 00272 //Configure E_TX03 (PCE) 00273 FM4_GPIO->PFRC_f.PE = 1; 00274 //Configure E_TX02 (PCF) 00275 FM4_GPIO->PFRC_f.PF = 1; 00276 //Configure E_TX01 (PD0) 00277 FM4_GPIO->PFRD_f.P0 = 1; 00278 //Configure E_TX00 (PD1) 00279 FM4_GPIO->PFRD_f.P1 = 1; 00280 //Configure E_TXEN (PD2) 00281 FM4_GPIO->PFRD_f.P2 = 1; 00282 00283 //Peripheral assignment 00284 FM4_GPIO->EPFR14_f.E_TD0E = 1; 00285 FM4_GPIO->EPFR14_f.E_TD1E = 1; 00286 FM4_GPIO->EPFR14_f.E_TE0E = 1; 00287 FM4_GPIO->EPFR14_f.E_TE1E = 1; 00288 FM4_GPIO->EPFR14_f.E_MC0E = 1; 00289 FM4_GPIO->EPFR14_f.E_MC1B = 1; 00290 FM4_GPIO->EPFR14_f.E_MD0B = 1; 00291 FM4_GPIO->EPFR14_f.E_MD1B = 1; 00292 FM4_GPIO->EPFR14_f.E_SPLC = 1; 00293 00294 //Configure PHY_RST as an output 00295 FM4_GPIO->PFR6_f.PA = 0; 00296 FM4_GPIO->DDR6_f.PA = 1; 00297 00298 //Reset PHY transceiver 00299 FM4_GPIO->PDOR6_f.PA = 0; 00300 sleep(10); 00301 00302 //Take the PHY transceiver out of reset 00303 FM4_GPIO->PDOR6_f.PA = 1; 00304 sleep(10); 00305 } 00306 00307 #endif 00308 00309 00310 /** 00311 * @brief Initialize DMA descriptor lists 00312 * @param[in] interface Underlying network interface 00313 **/ 00314 00315 void fm4EthInitDmaDesc(NetInterface *interface) 00316 { 00317 uint_t i; 00318 00319 //Initialize TX DMA descriptor list 00320 for(i = 0; i < FM4_ETH_TX_BUFFER_COUNT; i++) 00321 { 00322 //Use chain structure rather than ring structure 00323 txDmaDesc[i].tdes0 = ETH_TDES0_IC | ETH_TDES0_TCH; 00324 //Initialize transmit buffer size 00325 txDmaDesc[i].tdes1 = 0; 00326 //Transmit buffer address 00327 txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i]; 00328 //Next descriptor address 00329 txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1]; 00330 //Reserved fields 00331 txDmaDesc[i].tdes4 = 0; 00332 txDmaDesc[i].tdes5 = 0; 00333 //Transmit frame time stamp 00334 txDmaDesc[i].tdes6 = 0; 00335 txDmaDesc[i].tdes7 = 0; 00336 } 00337 00338 //The last descriptor is chained to the first entry 00339 txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0]; 00340 //Point to the very first descriptor 00341 txCurDmaDesc = &txDmaDesc[0]; 00342 00343 //Initialize RX DMA descriptor list 00344 for(i = 0; i < FM4_ETH_RX_BUFFER_COUNT; i++) 00345 { 00346 //The descriptor is initially owned by the DMA 00347 rxDmaDesc[i].rdes0 = ETH_RDES0_OWN; 00348 //Use chain structure rather than ring structure 00349 rxDmaDesc[i].rdes1 = ETH_RDES1_RCH | (FM4_ETH_RX_BUFFER_SIZE & ETH_RDES1_RBS1); 00350 //Receive buffer address 00351 rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i]; 00352 //Next descriptor address 00353 rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1]; 00354 //Extended status 00355 rxDmaDesc[i].rdes4 = 0; 00356 //Reserved field 00357 rxDmaDesc[i].rdes5 = 0; 00358 //Receive frame time stamp 00359 rxDmaDesc[i].rdes6 = 0; 00360 rxDmaDesc[i].rdes7 = 0; 00361 } 00362 00363 //The last descriptor is chained to the first entry 00364 rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0]; 00365 //Point to the very first descriptor 00366 rxCurDmaDesc = &rxDmaDesc[0]; 00367 00368 //Start location of the TX descriptor list 00369 FM4_ETHERNET_MAC0->TDLAR = (uint32_t) txDmaDesc; 00370 //Start location of the RX descriptor list 00371 FM4_ETHERNET_MAC0->RDLAR = (uint32_t) rxDmaDesc; 00372 } 00373 00374 00375 /** 00376 * @brief Spansion FM4 Ethernet MAC timer handler 00377 * 00378 * This routine is periodically called by the TCP/IP stack to 00379 * handle periodic operations such as polling the link state 00380 * 00381 * @param[in] interface Underlying network interface 00382 **/ 00383 00384 void fm4EthTick(NetInterface *interface) 00385 { 00386 //Handle periodic operations 00387 interface->phyDriver->tick(interface); 00388 } 00389 00390 00391 /** 00392 * @brief Enable interrupts 00393 * @param[in] interface Underlying network interface 00394 **/ 00395 00396 void fm4EthEnableIrq(NetInterface *interface) 00397 { 00398 //Enable Ethernet MAC interrupts 00399 NVIC_EnableIRQ(ETHER0_IRQn); 00400 //Enable Ethernet PHY interrupts 00401 interface->phyDriver->enableIrq(interface); 00402 } 00403 00404 00405 /** 00406 * @brief Disable interrupts 00407 * @param[in] interface Underlying network interface 00408 **/ 00409 00410 void fm4EthDisableIrq(NetInterface *interface) 00411 { 00412 //Disable Ethernet MAC interrupts 00413 NVIC_DisableIRQ(ETHER0_IRQn); 00414 //Disable Ethernet PHY interrupts 00415 interface->phyDriver->disableIrq(interface); 00416 } 00417 00418 00419 /** 00420 * @brief Spansion FM4 Ethernet MAC interrupt service routine 00421 **/ 00422 00423 void ETHER0_IRQHandler(void) 00424 { 00425 bool_t flag; 00426 00427 //Enter interrupt service routine 00428 osEnterIsr(); 00429 00430 //This flag will be set if a higher priority task must be woken 00431 flag = FALSE; 00432 00433 //A packet has been transmitted? 00434 if(bFM4_ETHERNET_MAC0_SR_TI) 00435 { 00436 //Clear TI interrupt flag 00437 bFM4_ETHERNET_MAC0_SR_TI = 1; 00438 00439 //Check whether the TX buffer is available for writing 00440 if(!(txCurDmaDesc->tdes0 & ETH_TDES0_OWN)) 00441 { 00442 //Notify the TCP/IP stack that the transmitter is ready to send 00443 flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent); 00444 } 00445 } 00446 00447 //A packet has been received? 00448 if(bFM4_ETHERNET_MAC0_SR_RI) 00449 { 00450 //Disable RIE interrupt 00451 bFM4_ETHERNET_MAC0_IER_RIE = 0; 00452 00453 //Set event flag 00454 nicDriverInterface->nicEvent = TRUE; 00455 //Notify the TCP/IP stack of the event 00456 flag |= osSetEventFromIsr(&netEvent); 00457 } 00458 00459 //Clear NIS interrupt flag 00460 bFM4_ETHERNET_MAC0_SR_NIS = 1; 00461 00462 //Leave interrupt service routine 00463 osExitIsr(flag); 00464 } 00465 00466 00467 /** 00468 * @brief Spansion FM4 Ethernet MAC event handler 00469 * @param[in] interface Underlying network interface 00470 **/ 00471 00472 void fm4EthEventHandler(NetInterface *interface) 00473 { 00474 error_t error; 00475 00476 //Packet received? 00477 if(bFM4_ETHERNET_MAC0_SR_RI) 00478 { 00479 //Clear interrupt flag 00480 bFM4_ETHERNET_MAC0_SR_RI = 1; 00481 00482 //Process all pending packets 00483 do 00484 { 00485 //Read incoming packet 00486 error = fm4EthReceivePacket(interface); 00487 00488 //No more data in the receive buffer? 00489 } while(error != ERROR_BUFFER_EMPTY); 00490 } 00491 00492 //Re-enable DMA interrupts 00493 bFM4_ETHERNET_MAC0_IER_NIE = 1; 00494 bFM4_ETHERNET_MAC0_IER_RIE = 1; 00495 bFM4_ETHERNET_MAC0_IER_TIE = 1; 00496 } 00497 00498 00499 /** 00500 * @brief Send a packet 00501 * @param[in] interface Underlying network interface 00502 * @param[in] buffer Multi-part buffer containing the data to send 00503 * @param[in] offset Offset to the first data byte 00504 * @return Error code 00505 **/ 00506 00507 error_t fm4EthSendPacket(NetInterface *interface, 00508 const NetBuffer *buffer, size_t offset) 00509 { 00510 size_t length; 00511 00512 //Retrieve the length of the packet 00513 length = netBufferGetLength(buffer) - offset; 00514 00515 //Check the frame length 00516 if(length > FM4_ETH_TX_BUFFER_SIZE) 00517 { 00518 //The transmitter can accept another packet 00519 osSetEvent(&interface->nicTxEvent); 00520 //Report an error 00521 return ERROR_INVALID_LENGTH; 00522 } 00523 00524 //Make sure the current buffer is available for writing 00525 if(txCurDmaDesc->tdes0 & ETH_TDES0_OWN) 00526 return ERROR_FAILURE; 00527 00528 //Copy user data to the transmit buffer 00529 netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length); 00530 00531 //Write the number of bytes to send 00532 txCurDmaDesc->tdes1 = length & ETH_TDES1_TBS1; 00533 //Set LS and FS flags as the data fits in a single buffer 00534 txCurDmaDesc->tdes0 |= ETH_TDES0_LS | ETH_TDES0_FS; 00535 //Give the ownership of the descriptor to the DMA 00536 txCurDmaDesc->tdes0 |= ETH_TDES0_OWN; 00537 00538 //Clear TU flag to resume processing 00539 bFM4_ETHERNET_MAC0_SR_TU = 1; 00540 //Instruct the DMA to poll the transmit descriptor list 00541 FM4_ETHERNET_MAC0->TPDR = 0; 00542 00543 //Point to the next descriptor in the list 00544 txCurDmaDesc = (Fm4TxDmaDesc *) txCurDmaDesc->tdes3; 00545 00546 //Check whether the next buffer is available for writing 00547 if(!(txCurDmaDesc->tdes0 & ETH_TDES0_OWN)) 00548 { 00549 //The transmitter can accept another packet 00550 osSetEvent(&interface->nicTxEvent); 00551 } 00552 00553 //Data successfully written 00554 return NO_ERROR; 00555 } 00556 00557 00558 /** 00559 * @brief Receive a packet 00560 * @param[in] interface Underlying network interface 00561 * @return Error code 00562 **/ 00563 00564 error_t fm4EthReceivePacket(NetInterface *interface) 00565 { 00566 error_t error; 00567 size_t n; 00568 00569 //The current buffer is available for reading? 00570 if(!(rxCurDmaDesc->rdes0 & ETH_RDES0_OWN)) 00571 { 00572 //FS and LS flags should be set 00573 if((rxCurDmaDesc->rdes0 & ETH_RDES0_FS) && (rxCurDmaDesc->rdes0 & ETH_RDES0_LS)) 00574 { 00575 //Make sure no error occurred 00576 if(!(rxCurDmaDesc->rdes0 & ETH_RDES0_ES)) 00577 { 00578 //Retrieve the length of the frame 00579 n = (rxCurDmaDesc->rdes0 & ETH_RDES0_FL) >> 16; 00580 //Limit the number of data to read 00581 n = MIN(n, FM4_ETH_RX_BUFFER_SIZE); 00582 00583 //Pass the packet to the upper layer 00584 nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n); 00585 00586 //Valid packet received 00587 error = NO_ERROR; 00588 } 00589 else 00590 { 00591 //The received packet contains an error 00592 error = ERROR_INVALID_PACKET; 00593 } 00594 } 00595 else 00596 { 00597 //The packet is not valid 00598 error = ERROR_INVALID_PACKET; 00599 } 00600 00601 //Give the ownership of the descriptor back to the DMA 00602 rxCurDmaDesc->rdes0 = ETH_RDES0_OWN; 00603 //Point to the next descriptor in the list 00604 rxCurDmaDesc = (Fm4RxDmaDesc *) rxCurDmaDesc->rdes3; 00605 } 00606 else 00607 { 00608 //No more data in the receive buffer 00609 error = ERROR_BUFFER_EMPTY; 00610 } 00611 00612 //Clear RU flag to resume processing 00613 bFM4_ETHERNET_MAC0_SR_RU = 1; 00614 //Instruct the DMA to poll the receive descriptor list 00615 FM4_ETHERNET_MAC0->RPDR = 0; 00616 00617 //Return status code 00618 return error; 00619 } 00620 00621 00622 /** 00623 * @brief Configure multicast MAC address filtering 00624 * @param[in] interface Underlying network interface 00625 * @return Error code 00626 **/ 00627 00628 error_t fm4EthSetMulticastFilter(NetInterface *interface) 00629 { 00630 uint_t i; 00631 uint_t k; 00632 uint32_t crc; 00633 uint32_t hashTable[2]; 00634 MacFilterEntry *entry; 00635 00636 //Debug message 00637 TRACE_DEBUG("Updating Spansion FM4 hash table...\r\n"); 00638 00639 //Clear hash table 00640 hashTable[0] = 0; 00641 hashTable[1] = 0; 00642 00643 //The MAC filter table contains the multicast MAC addresses 00644 //to accept when receiving an Ethernet frame 00645 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++) 00646 { 00647 //Point to the current entry 00648 entry = &interface->macMulticastFilter[i]; 00649 00650 //Valid entry? 00651 if(entry->refCount > 0) 00652 { 00653 //Compute CRC over the current MAC address 00654 crc = fm4EthCalcCrc(&entry->addr, sizeof(MacAddr)); 00655 00656 //The upper 6 bits in the CRC register are used to index the 00657 //contents of the hash table 00658 k = (crc >> 26) & 0x3F; 00659 00660 //Update hash table contents 00661 hashTable[k / 32] |= (1 << (k % 32)); 00662 } 00663 } 00664 00665 //Write the hash table 00666 FM4_ETHERNET_MAC0->MHTRL = hashTable[0]; 00667 FM4_ETHERNET_MAC0->MHTRH = hashTable[1]; 00668 00669 //Debug message 00670 TRACE_DEBUG(" MACHTLR = %08" PRIX32 "\r\n", FM4_ETHERNET_MAC0->MHTRL); 00671 TRACE_DEBUG(" MACHTHR = %08" PRIX32 "\r\n", FM4_ETHERNET_MAC0->MHTRH); 00672 00673 //Successful processing 00674 return NO_ERROR; 00675 } 00676 00677 00678 /** 00679 * @brief Adjust MAC configuration parameters for proper operation 00680 * @param[in] interface Underlying network interface 00681 * @return Error code 00682 **/ 00683 00684 error_t fm4EthUpdateMacConfig(NetInterface *interface) 00685 { 00686 //10BASE-T or 100BASE-TX operation mode? 00687 if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS) 00688 bFM4_ETHERNET_MAC0_MCR_FES = 1; 00689 else 00690 bFM4_ETHERNET_MAC0_MCR_FES = 0; 00691 00692 //Half-duplex or full-duplex mode? 00693 if(interface->duplexMode == NIC_FULL_DUPLEX_MODE) 00694 bFM4_ETHERNET_MAC0_MCR_DM = 1; 00695 else 00696 bFM4_ETHERNET_MAC0_MCR_DM = 0; 00697 00698 //Successful processing 00699 return NO_ERROR; 00700 } 00701 00702 00703 /** 00704 * @brief Write PHY register 00705 * @param[in] phyAddr PHY address 00706 * @param[in] regAddr Register address 00707 * @param[in] data Register value 00708 **/ 00709 00710 void fm4EthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data) 00711 { 00712 //Set up a write operation 00713 FM4_ETHERNET_MAC0->GAR_f.GW = 1; 00714 //PHY address 00715 FM4_ETHERNET_MAC0->GAR_f.PA = phyAddr; 00716 //Register address 00717 FM4_ETHERNET_MAC0->GAR_f.GR = regAddr; 00718 00719 //Data to be written in the PHY register 00720 FM4_ETHERNET_MAC0->GDR_f.GD = data; 00721 00722 //Start a write operation 00723 FM4_ETHERNET_MAC0->GAR_f.GB = 1; 00724 //Wait for the write to complete 00725 while(FM4_ETHERNET_MAC0->GAR_f.GB); 00726 } 00727 00728 00729 /** 00730 * @brief Read PHY register 00731 * @param[in] phyAddr PHY address 00732 * @param[in] regAddr Register address 00733 * @return Register value 00734 **/ 00735 00736 uint16_t fm4EthReadPhyReg(uint8_t phyAddr, uint8_t regAddr) 00737 { 00738 //Set up a read operation 00739 FM4_ETHERNET_MAC0->GAR_f.GW = 0; 00740 //PHY address 00741 FM4_ETHERNET_MAC0->GAR_f.PA = phyAddr; 00742 //Register address 00743 FM4_ETHERNET_MAC0->GAR_f.GR = regAddr; 00744 00745 //Start a read operation 00746 FM4_ETHERNET_MAC0->GAR_f.GB = 1; 00747 //Wait for the read to complete 00748 while(FM4_ETHERNET_MAC0->GAR_f.GB); 00749 00750 //Return PHY register contents 00751 return FM4_ETHERNET_MAC0->GDR_f.GD; 00752 } 00753 00754 00755 /** 00756 * @brief CRC calculation 00757 * @param[in] data Pointer to the data over which to calculate the CRC 00758 * @param[in] length Number of bytes to process 00759 * @return Resulting CRC value 00760 **/ 00761 00762 uint32_t fm4EthCalcCrc(const void *data, size_t length) 00763 { 00764 uint_t i; 00765 uint_t j; 00766 00767 //Point to the data over which to calculate the CRC 00768 const uint8_t *p = (uint8_t *) data; 00769 //CRC preset value 00770 uint32_t crc = 0xFFFFFFFF; 00771 00772 //Loop through data 00773 for(i = 0; i < length; i++) 00774 { 00775 //The message is processed bit by bit 00776 for(j = 0; j < 8; j++) 00777 { 00778 //Update CRC value 00779 if(((crc >> 31) ^ (p[i] >> j)) & 0x01) 00780 crc = (crc << 1) ^ 0x04C11DB7; 00781 else 00782 crc = crc << 1; 00783 } 00784 } 00785 00786 //Return CRC value 00787 return ~crc; 00788 } 00789
Generated on Tue Jul 12 2022 17:10:13 by
