Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
xmc4700_eth.c
Go to the documentation of this file.
00001 /** 00002 * @file xmc4700_eth.c 00003 * @brief Infineon XMC4700 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 "xmc4700.h" 00034 #include "core/net.h" 00035 #include "drivers/xmc4700_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 #pragma location = "ETH_RAM" 00047 static uint8_t txBuffer[XMC4700_ETH_TX_BUFFER_COUNT][XMC4700_ETH_TX_BUFFER_SIZE]; 00048 //Receive buffer 00049 #pragma data_alignment = 4 00050 #pragma location = "ETH_RAM" 00051 static uint8_t rxBuffer[XMC4700_ETH_RX_BUFFER_COUNT][XMC4700_ETH_RX_BUFFER_SIZE]; 00052 //Transmit DMA descriptors 00053 #pragma data_alignment = 4 00054 #pragma location = "ETH_RAM" 00055 static Xmc4700TxDmaDesc txDmaDesc[XMC4700_ETH_TX_BUFFER_COUNT]; 00056 //Receive DMA descriptors 00057 #pragma data_alignment = 4 00058 #pragma location = "ETH_RAM" 00059 static Xmc4700RxDmaDesc rxDmaDesc[XMC4700_ETH_RX_BUFFER_COUNT]; 00060 00061 //Keil MDK-ARM or GCC compiler? 00062 #else 00063 00064 //Transmit buffer 00065 static uint8_t txBuffer[XMC4700_ETH_TX_BUFFER_COUNT][XMC4700_ETH_TX_BUFFER_SIZE] 00066 __attribute__((aligned(4), __section__("ETH_RAM"))); 00067 //Receive buffer 00068 static uint8_t rxBuffer[XMC4700_ETH_RX_BUFFER_COUNT][XMC4700_ETH_RX_BUFFER_SIZE] 00069 __attribute__((aligned(4), __section__("ETH_RAM"))); 00070 //Transmit DMA descriptors 00071 static Xmc4700TxDmaDesc txDmaDesc[XMC4700_ETH_TX_BUFFER_COUNT] 00072 __attribute__((aligned(4), __section__("ETH_RAM"))); 00073 //Receive DMA descriptors 00074 static Xmc4700RxDmaDesc rxDmaDesc[XMC4700_ETH_RX_BUFFER_COUNT] 00075 __attribute__((aligned(4), __section__("ETH_RAM"))); 00076 00077 #endif 00078 00079 //Pointer to the current TX DMA descriptor 00080 static Xmc4700TxDmaDesc *txCurDmaDesc; 00081 //Pointer to the current RX DMA descriptor 00082 static Xmc4700RxDmaDesc *rxCurDmaDesc; 00083 00084 00085 /** 00086 * @brief XMC4700 Ethernet MAC driver 00087 **/ 00088 00089 const NicDriver xmc4700EthDriver = 00090 { 00091 NIC_TYPE_ETHERNET, 00092 ETH_MTU, 00093 xmc4700EthInit, 00094 xmc4700EthTick, 00095 xmc4700EthEnableIrq, 00096 xmc4700EthDisableIrq, 00097 xmc4700EthEventHandler, 00098 xmc4700EthSendPacket, 00099 xmc4700EthSetMulticastFilter, 00100 xmc4700EthUpdateMacConfig, 00101 xmc4700EthWritePhyReg, 00102 xmc4700EthReadPhyReg, 00103 TRUE, 00104 TRUE, 00105 TRUE, 00106 FALSE 00107 }; 00108 00109 00110 /** 00111 * @brief XMC4700 Ethernet MAC initialization 00112 * @param[in] interface Underlying network interface 00113 * @return Error code 00114 **/ 00115 00116 error_t xmc4700EthInit(NetInterface *interface) 00117 { 00118 error_t error; 00119 00120 //Debug message 00121 TRACE_INFO("Initializing XMC4700 Ethernet MAC...\r\n"); 00122 00123 //Save underlying network interface 00124 nicDriverInterface = interface; 00125 00126 //Disable parity error trap 00127 SCU_PARITY->PETE = 0; 00128 //Disable unaligned access trap 00129 PPB->CCR &= ~PPB_CCR_UNALIGN_TRP_Msk; 00130 00131 //Enable ETH0 peripheral clock 00132 SCU_CLK->CLKSET = SCU_CLK_CLKSET_ETH0CEN_Msk; 00133 00134 //GPIO configuration 00135 xmc4700EthInitGpio(interface); 00136 00137 //Reset ETH0 peripheral 00138 SCU_RESET->PRSET2 = SCU_RESET_PRSET2_ETH0RS_Msk; 00139 SCU_RESET->PRCLR2 = SCU_RESET_PRCLR2_ETH0RS_Msk; 00140 00141 //Reset DMA controller 00142 ETH0->BUS_MODE |= ETH_BUS_MODE_SWR_Msk; 00143 //Wait for the reset to complete 00144 while(ETH0->BUS_MODE & ETH_BUS_MODE_SWR_Msk); 00145 00146 //Adjust MDC clock range depending on ETH clock frequency 00147 ETH0->GMII_ADDRESS = ETH_GMII_ADDRESS_CR_DIV62; 00148 00149 //PHY transceiver initialization 00150 error = interface->phyDriver->init(interface); 00151 //Failed to initialize PHY transceiver? 00152 if(error) 00153 return error; 00154 00155 //Use default MAC configuration 00156 ETH0->MAC_CONFIGURATION = ETH_MAC_CONFIGURATION_RESERVED15_Msk | 00157 ETH_MAC_CONFIGURATION_DO_Msk; 00158 00159 //Set the MAC address 00160 ETH0->MAC_ADDRESS0_LOW = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16); 00161 ETH0->MAC_ADDRESS0_HIGH = interface->macAddr.w[2]; 00162 00163 //Initialize hash table 00164 ETH0->HASH_TABLE_LOW = 0; 00165 ETH0->HASH_TABLE_HIGH = 0; 00166 00167 //Configure the receive filter 00168 ETH0->MAC_FRAME_FILTER = ETH_MAC_FRAME_FILTER_HPF_Msk | ETH_MAC_FRAME_FILTER_HMC_Msk; 00169 //Disable flow control 00170 ETH0->FLOW_CONTROL = 0; 00171 //Enable store and forward mode 00172 ETH0->OPERATION_MODE = ETH_OPERATION_MODE_RSF_Msk | ETH_OPERATION_MODE_TSF_Msk; 00173 00174 //Configure DMA bus mode 00175 ETH0->BUS_MODE = ETH_BUS_MODE_AAL_Msk | ETH_BUS_MODE_USP_Msk | 00176 ETH_BUS_MODE_RPBL_1 | ETH_BUS_MODE_PR_1_1 | ETH_BUS_MODE_PBL_1; 00177 00178 //Initialize DMA descriptor lists 00179 xmc4700EthInitDmaDesc(interface); 00180 00181 //Prevent interrupts from being generated when statistic counters reach 00182 //half their maximum value 00183 ETH0->MMC_TRANSMIT_INTERRUPT_MASK = 0xFFFFFFFF; 00184 ETH0->MMC_RECEIVE_INTERRUPT_MASK = 0xFFFFFFFF; 00185 ETH0->MMC_IPC_RECEIVE_INTERRUPT_MASK = 0xFFFFFFFF; 00186 00187 //Disable MAC interrupts 00188 ETH0->INTERRUPT_MASK = ETH_INTERRUPT_MASK_TSIM_Msk | ETH_INTERRUPT_MASK_PMTIM_Msk; 00189 00190 //Enable the desired DMA interrupts 00191 ETH0->INTERRUPT_ENABLE = ETH_INTERRUPT_ENABLE_NIE_Msk | 00192 ETH_INTERRUPT_ENABLE_RIE_Msk | ETH_INTERRUPT_ENABLE_TIE_Msk; 00193 00194 //Set priority grouping (6 bits for pre-emption priority, no bits for subpriority) 00195 NVIC_SetPriorityGrouping(XMC4700_ETH_IRQ_PRIORITY_GROUPING); 00196 00197 //Configure Ethernet interrupt priority 00198 NVIC_SetPriority(ETH0_0_IRQn, NVIC_EncodePriority(XMC4700_ETH_IRQ_PRIORITY_GROUPING, 00199 XMC4700_ETH_IRQ_GROUP_PRIORITY, XMC4700_ETH_IRQ_SUB_PRIORITY)); 00200 00201 //Enable MAC transmission and reception 00202 ETH0->MAC_CONFIGURATION |= ETH_MAC_CONFIGURATION_TE_Msk | ETH_MAC_CONFIGURATION_RE_Msk; 00203 //Enable DMA transmission and reception 00204 ETH0->OPERATION_MODE |= ETH_OPERATION_MODE_ST_Msk | ETH_OPERATION_MODE_SR_Msk; 00205 00206 //Accept any packets from the upper layer 00207 osSetEvent(&interface->nicTxEvent); 00208 00209 //Successful initialization 00210 return NO_ERROR; 00211 } 00212 00213 00214 //XMC4700 Relax Kit? 00215 #if defined(USE_XMC4700_RELAX_KIT) 00216 00217 /** 00218 * @brief GPIO configuration 00219 * @param[in] interface Underlying network interface 00220 **/ 00221 00222 void xmc4700EthInitGpio(NetInterface *interface) 00223 { 00224 uint32_t temp; 00225 00226 //Configure ETH0.MDIO (P2.0), ETH0.RXD0A (P2.2) and ETH0.RXD1A (P2.3) 00227 temp = PORT2->IOCR0; 00228 temp &= ~(PORT2_IOCR0_PC0_Msk | PORT2_IOCR0_PC2_Msk | PORT2_IOCR0_PC3_Msk); 00229 temp |= (0UL << PORT2_IOCR0_PC0_Pos) | (0UL << PORT2_IOCR0_PC2_Pos) | (0UL << PORT2_IOCR0_PC3_Pos); 00230 PORT2->IOCR0 = temp; 00231 00232 //Configure ETH0.RXERA (P2.4), ETH0.TX_EN (P2.5) and ETH0.MDC (P2.7) 00233 temp = PORT2->IOCR4; 00234 temp &= ~(PORT2_IOCR4_PC4_Msk | PORT2_IOCR4_PC5_Msk | PORT2_IOCR4_PC7_Msk); 00235 temp |= (0UL << PORT2_IOCR4_PC4_Pos) | (17UL << PORT2_IOCR4_PC5_Pos) | (17UL << PORT2_IOCR4_PC7_Pos); 00236 PORT2->IOCR4 = temp; 00237 00238 //Configure ETH0.TXD0 (P2.8) and ETH0.TXD1 (P2.9) 00239 temp = PORT2->IOCR8; 00240 temp &= ~(PORT2_IOCR8_PC8_Msk | PORT2_IOCR8_PC9_Msk); 00241 temp |= (17UL << PORT2_IOCR8_PC8_Pos) | (17UL << PORT2_IOCR8_PC9_Pos); 00242 PORT2->IOCR8 = temp; 00243 00244 //Configure ETH0.CLK_RMIIC (P15.8) and ETH0.CRS_DVC (P15.9) 00245 temp = PORT15->IOCR8; 00246 temp &= ~(PORT15_IOCR8_PC8_Msk | PORT15_IOCR8_PC9_Msk); 00247 temp |= (0UL << PORT15_IOCR8_PC8_Pos) | (0UL << PORT15_IOCR8_PC9_Pos); 00248 PORT15->IOCR8 = temp; 00249 00250 //Assign ETH_MDIO (P2.0) to HW0 00251 temp = PORT2->HWSEL & ~PORT2_HWSEL_HW0_Msk; 00252 PORT2->HWSEL = temp | (1UL << PORT2_HWSEL_HW0_Pos); 00253 00254 //Select output driver strength for ETH0.TX_EN (P2.5) 00255 temp = PORT2->PDR0; 00256 temp &= ~PORT2_PDR0_PD5_Msk; 00257 temp |= (0UL << PORT2_PDR0_PD5_Pos); 00258 PORT2->PDR0 = temp; 00259 00260 //Select output driver strength for ETH0.TXD0 (P2.8) and ETH0.TXD1 (P2.9) 00261 temp = PORT2->PDR1; 00262 temp &= ~(PORT2_PDR1_PD8_Msk | PORT2_PDR1_PD9_Msk); 00263 temp |= (0UL << PORT2_PDR1_PD8_Pos) | (0UL << PORT2_PDR1_PD9_Pos); 00264 PORT2->PDR1 = temp; 00265 00266 //Use ETH0.CLK_RMIIC (P15.8) and ETH0.CRS_DVC (P15.9) as digital inputs 00267 PORT15->PDISC &= ~(PORT15_PDISC_PDIS8_Msk | PORT15_PDISC_PDIS9_Msk); 00268 00269 //Select RMII operation mode 00270 ETH0_CON->CON = ETH_CON_INFSEL_Msk | ETH_CON_MDIO_B | ETH_CON_RXER_A | 00271 ETH_CON_CRS_DV_C | ETH_CON_CLK_RMII_C | ETH_CON_RXD1_A | ETH_CON_RXD0_A; 00272 } 00273 00274 #endif 00275 00276 00277 /** 00278 * @brief Initialize DMA descriptor lists 00279 * @param[in] interface Underlying network interface 00280 **/ 00281 00282 void xmc4700EthInitDmaDesc(NetInterface *interface) 00283 { 00284 uint_t i; 00285 00286 //Initialize TX DMA descriptor list 00287 for(i = 0; i < XMC4700_ETH_TX_BUFFER_COUNT; i++) 00288 { 00289 //Use chain structure rather than ring structure 00290 txDmaDesc[i].tdes0 = ETH_TDES0_IC | ETH_TDES0_TCH; 00291 //Initialize transmit buffer size 00292 txDmaDesc[i].tdes1 = 0; 00293 //Transmit buffer address 00294 txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i]; 00295 //Next descriptor address 00296 txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1]; 00297 } 00298 00299 //The last descriptor is chained to the first entry 00300 txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0]; 00301 //Point to the very first descriptor 00302 txCurDmaDesc = &txDmaDesc[0]; 00303 00304 //Initialize RX DMA descriptor list 00305 for(i = 0; i < XMC4700_ETH_RX_BUFFER_COUNT; i++) 00306 { 00307 //The descriptor is initially owned by the DMA 00308 rxDmaDesc[i].rdes0 = ETH_RDES0_OWN; 00309 //Use chain structure rather than ring structure 00310 rxDmaDesc[i].rdes1 = ETH_RDES1_RCH | (XMC4700_ETH_RX_BUFFER_SIZE & ETH_RDES1_RBS1); 00311 //Receive buffer address 00312 rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i]; 00313 //Next descriptor address 00314 rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1]; 00315 } 00316 00317 //The last descriptor is chained to the first entry 00318 rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0]; 00319 //Point to the very first descriptor 00320 rxCurDmaDesc = &rxDmaDesc[0]; 00321 00322 //Start location of the TX descriptor list 00323 ETH0->TRANSMIT_DESCRIPTOR_LIST_ADDRESS = (uint32_t) txDmaDesc; 00324 //Start location of the RX descriptor list 00325 ETH0->RECEIVE_DESCRIPTOR_LIST_ADDRESS = (uint32_t) rxDmaDesc; 00326 } 00327 00328 00329 /** 00330 * @brief XMC4700 Ethernet MAC timer handler 00331 * 00332 * This routine is periodically called by the TCP/IP stack to 00333 * handle periodic operations such as polling the link state 00334 * 00335 * @param[in] interface Underlying network interface 00336 **/ 00337 00338 void xmc4700EthTick(NetInterface *interface) 00339 { 00340 //Handle periodic operations 00341 interface->phyDriver->tick(interface); 00342 } 00343 00344 00345 /** 00346 * @brief Enable interrupts 00347 * @param[in] interface Underlying network interface 00348 **/ 00349 00350 void xmc4700EthEnableIrq(NetInterface *interface) 00351 { 00352 //Enable Ethernet MAC interrupts 00353 NVIC_EnableIRQ(ETH0_0_IRQn); 00354 //Enable Ethernet PHY interrupts 00355 interface->phyDriver->enableIrq(interface); 00356 } 00357 00358 00359 /** 00360 * @brief Disable interrupts 00361 * @param[in] interface Underlying network interface 00362 **/ 00363 00364 void xmc4700EthDisableIrq(NetInterface *interface) 00365 { 00366 //Disable Ethernet MAC interrupts 00367 NVIC_DisableIRQ(ETH0_0_IRQn); 00368 //Disable Ethernet PHY interrupts 00369 interface->phyDriver->disableIrq(interface); 00370 } 00371 00372 00373 /** 00374 * @brief XMC4700 Ethernet MAC interrupt service routine 00375 **/ 00376 00377 void ETH0_0_IRQHandler(void) 00378 { 00379 bool_t flag; 00380 uint32_t status; 00381 00382 //Enter interrupt service routine 00383 osEnterIsr(); 00384 00385 //This flag will be set if a higher priority task must be woken 00386 flag = FALSE; 00387 00388 //Read DMA status register 00389 status = ETH0->STATUS; 00390 00391 //A packet has been transmitted? 00392 if(status & ETH_STATUS_TI_Msk) 00393 { 00394 //Clear TI interrupt flag 00395 ETH0->STATUS = ETH_STATUS_TI_Msk; 00396 00397 //Check whether the TX buffer is available for writing 00398 if(!(txCurDmaDesc->tdes0 & ETH_TDES0_OWN)) 00399 { 00400 //Notify the TCP/IP stack that the transmitter is ready to send 00401 flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent); 00402 } 00403 } 00404 00405 //A packet has been received? 00406 if(status & ETH_STATUS_RI_Msk) 00407 { 00408 //Disable RIE interrupt 00409 ETH0->INTERRUPT_ENABLE &= ~ETH_INTERRUPT_ENABLE_RIE_Msk; 00410 00411 //Set event flag 00412 nicDriverInterface->nicEvent = TRUE; 00413 //Notify the TCP/IP stack of the event 00414 flag |= osSetEventFromIsr(&netEvent); 00415 } 00416 00417 //Clear NIS interrupt flag 00418 ETH0->STATUS = ETH_STATUS_NIS_Msk; 00419 00420 //Leave interrupt service routine 00421 osExitIsr(flag); 00422 } 00423 00424 00425 /** 00426 * @brief XMC4700 Ethernet MAC event handler 00427 * @param[in] interface Underlying network interface 00428 **/ 00429 00430 void xmc4700EthEventHandler(NetInterface *interface) 00431 { 00432 error_t error; 00433 00434 //Packet received? 00435 if(ETH0->STATUS & ETH_STATUS_RI_Msk) 00436 { 00437 //Clear interrupt flag 00438 ETH0->STATUS = ETH_STATUS_RI_Msk; 00439 00440 //Process all pending packets 00441 do 00442 { 00443 //Read incoming packet 00444 error = xmc4700EthReceivePacket(interface); 00445 00446 //No more data in the receive buffer? 00447 } while(error != ERROR_BUFFER_EMPTY); 00448 } 00449 00450 //Re-enable DMA interrupts 00451 ETH0->INTERRUPT_ENABLE |= ETH_INTERRUPT_ENABLE_NIE_Msk | 00452 ETH_INTERRUPT_ENABLE_RIE_Msk | ETH_INTERRUPT_ENABLE_TIE_Msk; 00453 } 00454 00455 00456 /** 00457 * @brief Send a packet 00458 * @param[in] interface Underlying network interface 00459 * @param[in] buffer Multi-part buffer containing the data to send 00460 * @param[in] offset Offset to the first data byte 00461 * @return Error code 00462 **/ 00463 00464 error_t xmc4700EthSendPacket(NetInterface *interface, 00465 const NetBuffer *buffer, size_t offset) 00466 { 00467 size_t length; 00468 00469 //Retrieve the length of the packet 00470 length = netBufferGetLength(buffer) - offset; 00471 00472 //Check the frame length 00473 if(length > XMC4700_ETH_TX_BUFFER_SIZE) 00474 { 00475 //The transmitter can accept another packet 00476 osSetEvent(&interface->nicTxEvent); 00477 //Report an error 00478 return ERROR_INVALID_LENGTH; 00479 } 00480 00481 //Make sure the current buffer is available for writing 00482 if(txCurDmaDesc->tdes0 & ETH_TDES0_OWN) 00483 return ERROR_FAILURE; 00484 00485 //Copy user data to the transmit buffer 00486 netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length); 00487 00488 //Write the number of bytes to send 00489 txCurDmaDesc->tdes1 = length & ETH_TDES1_TBS1; 00490 //Set LS and FS flags as the data fits in a single buffer 00491 txCurDmaDesc->tdes0 |= ETH_TDES0_LS | ETH_TDES0_FS; 00492 //Give the ownership of the descriptor to the DMA 00493 txCurDmaDesc->tdes0 |= ETH_TDES0_OWN; 00494 00495 //Clear TU flag to resume processing 00496 ETH0->STATUS = ETH_STATUS_TU_Msk; 00497 //Instruct the DMA to poll the transmit descriptor list 00498 ETH0->TRANSMIT_POLL_DEMAND = 0; 00499 00500 //Point to the next descriptor in the list 00501 txCurDmaDesc = (Xmc4700TxDmaDesc *) txCurDmaDesc->tdes3; 00502 00503 //Check whether the next buffer is available for writing 00504 if(!(txCurDmaDesc->tdes0 & ETH_TDES0_OWN)) 00505 { 00506 //The transmitter can accept another packet 00507 osSetEvent(&interface->nicTxEvent); 00508 } 00509 00510 //Data successfully written 00511 return NO_ERROR; 00512 } 00513 00514 00515 /** 00516 * @brief Receive a packet 00517 * @param[in] interface Underlying network interface 00518 * @return Error code 00519 **/ 00520 00521 error_t xmc4700EthReceivePacket(NetInterface *interface) 00522 { 00523 error_t error; 00524 size_t n; 00525 00526 //The current buffer is available for reading? 00527 if(!(rxCurDmaDesc->rdes0 & ETH_RDES0_OWN)) 00528 { 00529 //FS and LS flags should be set 00530 if((rxCurDmaDesc->rdes0 & ETH_RDES0_FS) && (rxCurDmaDesc->rdes0 & ETH_RDES0_LS)) 00531 { 00532 //Make sure no error occurred 00533 if(!(rxCurDmaDesc->rdes0 & ETH_RDES0_ES)) 00534 { 00535 //Retrieve the length of the frame 00536 n = (rxCurDmaDesc->rdes0 & ETH_RDES0_FL) >> 16; 00537 //Limit the number of data to read 00538 n = MIN(n, XMC4700_ETH_RX_BUFFER_SIZE); 00539 00540 //Pass the packet to the upper layer 00541 nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n); 00542 00543 //Valid packet received 00544 error = NO_ERROR; 00545 } 00546 else 00547 { 00548 //The received packet contains an error 00549 error = ERROR_INVALID_PACKET; 00550 } 00551 } 00552 else 00553 { 00554 //The packet is not valid 00555 error = ERROR_INVALID_PACKET; 00556 } 00557 00558 //Give the ownership of the descriptor back to the DMA 00559 rxCurDmaDesc->rdes0 = ETH_RDES0_OWN; 00560 //Point to the next descriptor in the list 00561 rxCurDmaDesc = (Xmc4700RxDmaDesc *) rxCurDmaDesc->rdes3; 00562 } 00563 else 00564 { 00565 //No more data in the receive buffer 00566 error = ERROR_BUFFER_EMPTY; 00567 } 00568 00569 //Clear RU flag to resume processing 00570 ETH0->STATUS = ETH_STATUS_RU_Msk; 00571 //Instruct the DMA to poll the receive descriptor list 00572 ETH0->RECEIVE_POLL_DEMAND = 0; 00573 00574 //Return status code 00575 return error; 00576 } 00577 00578 00579 /** 00580 * @brief Configure multicast MAC address filtering 00581 * @param[in] interface Underlying network interface 00582 * @return Error code 00583 **/ 00584 00585 error_t xmc4700EthSetMulticastFilter(NetInterface *interface) 00586 { 00587 uint_t i; 00588 uint_t k; 00589 uint32_t crc; 00590 uint32_t hashTable[2]; 00591 MacFilterEntry *entry; 00592 00593 //Debug message 00594 TRACE_DEBUG("Updating XMC4700 hash table...\r\n"); 00595 00596 //Clear hash table 00597 hashTable[0] = 0; 00598 hashTable[1] = 0; 00599 00600 //The MAC filter table contains the multicast MAC addresses 00601 //to accept when receiving an Ethernet frame 00602 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++) 00603 { 00604 //Point to the current entry 00605 entry = &interface->macMulticastFilter[i]; 00606 00607 //Valid entry? 00608 if(entry->refCount > 0) 00609 { 00610 //Compute CRC over the current MAC address 00611 crc = xmc4700EthCalcCrc(&entry->addr, sizeof(MacAddr)); 00612 00613 //The upper 6 bits in the CRC register are used to index the 00614 //contents of the hash table 00615 k = (crc >> 26) & 0x3F; 00616 00617 //Update hash table contents 00618 hashTable[k / 32] |= (1 << (k % 32)); 00619 } 00620 } 00621 00622 //Write the hash table 00623 ETH0->HASH_TABLE_LOW = hashTable[0]; 00624 ETH0->HASH_TABLE_HIGH = hashTable[1]; 00625 00626 //Debug message 00627 TRACE_DEBUG(" HTL = %08" PRIX32 "\r\n", ETH0->HASH_TABLE_LOW); 00628 TRACE_DEBUG(" HTH = %08" PRIX32 "\r\n", ETH0->HASH_TABLE_HIGH); 00629 00630 //Successful processing 00631 return NO_ERROR; 00632 } 00633 00634 00635 /** 00636 * @brief Adjust MAC configuration parameters for proper operation 00637 * @param[in] interface Underlying network interface 00638 * @return Error code 00639 **/ 00640 00641 error_t xmc4700EthUpdateMacConfig(NetInterface *interface) 00642 { 00643 uint32_t config; 00644 00645 //Read current MAC configuration 00646 config = ETH0->MAC_CONFIGURATION; 00647 00648 //10BASE-T or 100BASE-TX operation mode? 00649 if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS) 00650 config |= ETH_MAC_CONFIGURATION_FES_Msk; 00651 else 00652 config &= ~ETH_MAC_CONFIGURATION_FES_Msk; 00653 00654 //Half-duplex or full-duplex mode? 00655 if(interface->duplexMode == NIC_FULL_DUPLEX_MODE) 00656 config |= ETH_MAC_CONFIGURATION_DM_Msk; 00657 else 00658 config &= ~ETH_MAC_CONFIGURATION_DM_Msk; 00659 00660 //Update MAC configuration register 00661 ETH0->MAC_CONFIGURATION = config; 00662 00663 //Successful processing 00664 return NO_ERROR; 00665 } 00666 00667 00668 /** 00669 * @brief Write PHY register 00670 * @param[in] phyAddr PHY address 00671 * @param[in] regAddr Register address 00672 * @param[in] data Register value 00673 **/ 00674 00675 void xmc4700EthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data) 00676 { 00677 uint32_t value; 00678 00679 //Take care not to alter MDC clock configuration 00680 value = ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_CR_Msk; 00681 //Set up a write operation 00682 value |= ETH_GMII_ADDRESS_MW_Msk | ETH_GMII_ADDRESS_MB_Msk; 00683 //PHY address 00684 value |= (phyAddr << ETH_GMII_ADDRESS_PA_Pos) & ETH_GMII_ADDRESS_PA_Msk; 00685 //Register address 00686 value |= (regAddr << ETH_GMII_ADDRESS_MR_Pos) & ETH_GMII_ADDRESS_MR_Msk; 00687 00688 //Data to be written in the PHY register 00689 ETH0->GMII_DATA = data & ETH_GMII_DATA_MD_Msk; 00690 00691 //Start a write operation 00692 ETH0->GMII_ADDRESS = value; 00693 //Wait for the write to complete 00694 while(ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_MB_Msk); 00695 } 00696 00697 00698 /** 00699 * @brief Read PHY register 00700 * @param[in] phyAddr PHY address 00701 * @param[in] regAddr Register address 00702 * @return Register value 00703 **/ 00704 00705 uint16_t xmc4700EthReadPhyReg(uint8_t phyAddr, uint8_t regAddr) 00706 { 00707 uint32_t value; 00708 00709 //Take care not to alter MDC clock configuration 00710 value = ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_CR_Msk; 00711 //Set up a read operation 00712 value |= ETH_GMII_ADDRESS_MB_Msk; 00713 //PHY address 00714 value |= (phyAddr << ETH_GMII_ADDRESS_PA_Pos) & ETH_GMII_ADDRESS_PA_Msk; 00715 //Register address 00716 value |= (regAddr << ETH_GMII_ADDRESS_MR_Pos) & ETH_GMII_ADDRESS_MR_Msk; 00717 00718 //Start a read operation 00719 ETH0->GMII_ADDRESS = value; 00720 //Wait for the read to complete 00721 while(ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_MB_Msk); 00722 00723 //Return PHY register contents 00724 return ETH0->GMII_DATA & ETH_GMII_DATA_MD_Msk; 00725 } 00726 00727 00728 /** 00729 * @brief CRC calculation 00730 * @param[in] data Pointer to the data over which to calculate the CRC 00731 * @param[in] length Number of bytes to process 00732 * @return Resulting CRC value 00733 **/ 00734 00735 uint32_t xmc4700EthCalcCrc(const void *data, size_t length) 00736 { 00737 uint_t i; 00738 uint_t j; 00739 00740 //Point to the data over which to calculate the CRC 00741 const uint8_t *p = (uint8_t *) data; 00742 //CRC preset value 00743 uint32_t crc = 0xFFFFFFFF; 00744 00745 //Loop through data 00746 for(i = 0; i < length; i++) 00747 { 00748 //The message is processed bit by bit 00749 for(j = 0; j < 8; j++) 00750 { 00751 //Update CRC value 00752 if(((crc >> 31) ^ (p[i] >> j)) & 0x01) 00753 crc = (crc << 1) ^ 0x04C11DB7; 00754 else 00755 crc = crc << 1; 00756 } 00757 } 00758 00759 //Return CRC value 00760 return ~crc; 00761 } 00762
Generated on Tue Jul 12 2022 17:10:17 by
