Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
mkv5x_eth.c
Go to the documentation of this file.
00001 /** 00002 * @file mkv5x_eth.c 00003 * @brief Freescale Kinetis KV5x 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 //MKV58F12 device? 00033 #if defined(MKV58F22) 00034 #include "mkv58f22.h" 00035 #endif 00036 00037 //Dependencies 00038 #include "core/net.h" 00039 #include "drivers/mkv5x_eth.h" 00040 #include "debug.h" 00041 00042 //Underlying network interface 00043 static NetInterface *nicDriverInterface; 00044 00045 //IAR EWARM compiler? 00046 #if defined(__ICCARM__) 00047 00048 //TX buffer 00049 #pragma data_alignment = 16 00050 static uint8_t txBuffer[MKV5X_ETH_TX_BUFFER_COUNT][MKV5X_ETH_TX_BUFFER_SIZE]; 00051 //RX buffer 00052 #pragma data_alignment = 16 00053 static uint8_t rxBuffer[MKV5X_ETH_RX_BUFFER_COUNT][MKV5X_ETH_RX_BUFFER_SIZE]; 00054 //TX buffer descriptors 00055 #pragma data_alignment = 16 00056 static uint16_t txBufferDesc[MKV5X_ETH_TX_BUFFER_COUNT][16]; 00057 //RX buffer descriptors 00058 #pragma data_alignment = 16 00059 static uint16_t rxBufferDesc[MKV5X_ETH_RX_BUFFER_COUNT][16]; 00060 00061 //ARM or GCC compiler? 00062 #else 00063 00064 //TX buffer 00065 static uint8_t txBuffer[MKV5X_ETH_TX_BUFFER_COUNT][MKV5X_ETH_TX_BUFFER_SIZE] 00066 __attribute__((aligned(16))); 00067 //RX buffer 00068 static uint8_t rxBuffer[MKV5X_ETH_RX_BUFFER_COUNT][MKV5X_ETH_RX_BUFFER_SIZE] 00069 __attribute__((aligned(16))); 00070 //TX buffer descriptors 00071 static uint16_t txBufferDesc[MKV5X_ETH_TX_BUFFER_COUNT][16] 00072 __attribute__((aligned(16))); 00073 //RX buffer descriptors 00074 static uint16_t rxBufferDesc[MKV5X_ETH_RX_BUFFER_COUNT][16] 00075 __attribute__((aligned(16))); 00076 00077 #endif 00078 00079 //TX buffer index 00080 static uint_t txBufferIndex; 00081 //RX buffer index 00082 static uint_t rxBufferIndex; 00083 00084 00085 /** 00086 * @brief Kinetis KV5x Ethernet MAC driver 00087 **/ 00088 00089 const NicDriver mkv5xEthDriver = 00090 { 00091 NIC_TYPE_ETHERNET, 00092 ETH_MTU, 00093 mkv5xEthInit, 00094 mkv5xEthTick, 00095 mkv5xEthEnableIrq, 00096 mkv5xEthDisableIrq, 00097 mkv5xEthEventHandler, 00098 mkv5xEthSendPacket, 00099 mkv5xEthSetMulticastFilter, 00100 mkv5xEthUpdateMacConfig, 00101 mkv5xEthWritePhyReg, 00102 mkv5xEthReadPhyReg, 00103 TRUE, 00104 TRUE, 00105 TRUE, 00106 FALSE 00107 }; 00108 00109 00110 /** 00111 * @brief Kinetis KV5x Ethernet MAC initialization 00112 * @param[in] interface Underlying network interface 00113 * @return Error code 00114 **/ 00115 00116 error_t mkv5xEthInit(NetInterface *interface) 00117 { 00118 error_t error; 00119 uint32_t value; 00120 00121 //Debug message 00122 TRACE_INFO("Initializing Kinetis KV5x Ethernet MAC...\r\n"); 00123 00124 //Save underlying network interface 00125 nicDriverInterface = interface; 00126 00127 //Disable MPU 00128 MPU->CESR &= ~MPU_CESR_VLD_MASK; 00129 00130 //Enable ENET peripheral clock 00131 SIM->SCGC2 |= SIM_SCGC2_ENET_MASK; 00132 00133 //GPIO configuration 00134 mkv5xEthInitGpio(interface); 00135 00136 //Reset ENET module 00137 ENET->ECR = ENET_ECR_RESET_MASK; 00138 //Wait for the reset to complete 00139 while(ENET->ECR & ENET_ECR_RESET_MASK); 00140 00141 //Receive control register 00142 ENET->RCR = ENET_RCR_MAX_FL(1518) | ENET_RCR_MII_MODE_MASK; 00143 //Transmit control register 00144 ENET->TCR = 0; 00145 //Configure MDC clock frequency 00146 ENET->MSCR = ENET_MSCR_MII_SPEED(49); 00147 00148 //PHY transceiver initialization 00149 error = interface->phyDriver->init(interface); 00150 //Failed to initialize PHY transceiver? 00151 if(error) 00152 return error; 00153 00154 //Set the MAC address (upper 16 bits) 00155 value = interface->macAddr.b[5]; 00156 value |= (interface->macAddr.b[4] << 8); 00157 ENET->PAUR = ENET_PAUR_PADDR2(value) | ENET_PAUR_TYPE(0x8808); 00158 00159 //Set the MAC address (lower 32 bits) 00160 value = interface->macAddr.b[3]; 00161 value |= (interface->macAddr.b[2] << 8); 00162 value |= (interface->macAddr.b[1] << 16); 00163 value |= (interface->macAddr.b[0] << 24); 00164 ENET->PALR = ENET_PALR_PADDR1(value); 00165 00166 //Hash table for unicast address filtering 00167 ENET->IALR = 0; 00168 ENET->IAUR = 0; 00169 //Hash table for multicast address filtering 00170 ENET->GALR = 0; 00171 ENET->GAUR = 0; 00172 00173 //Disable transmit accelerator functions 00174 ENET->TACC = 0; 00175 //Disable receive accelerator functions 00176 ENET->RACC = 0; 00177 00178 //Use enhanced buffer descriptors 00179 ENET->ECR = ENET_ECR_EN1588_MASK; 00180 //Clear MIC counters 00181 ENET->MIBC = ENET_MIBC_MIB_CLEAR_MASK; 00182 00183 //Initialize buffer descriptors 00184 mkv5xEthInitBufferDesc(interface); 00185 00186 //Clear any pending interrupts 00187 ENET->EIR = 0xFFFFFFFF; 00188 //Enable desired interrupts 00189 ENET->EIMR = ENET_EIMR_TXF_MASK | ENET_EIMR_RXF_MASK | ENET_EIMR_EBERR_MASK; 00190 00191 //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority) 00192 NVIC_SetPriorityGrouping(MKV5X_ETH_IRQ_PRIORITY_GROUPING); 00193 00194 //Configure ENET transmit interrupt priority 00195 NVIC_SetPriority(ENET_Transmit_IRQn, NVIC_EncodePriority(MKV5X_ETH_IRQ_PRIORITY_GROUPING, 00196 MKV5X_ETH_IRQ_GROUP_PRIORITY, MKV5X_ETH_IRQ_SUB_PRIORITY)); 00197 00198 //Configure ENET receive interrupt priority 00199 NVIC_SetPriority(ENET_Receive_IRQn, NVIC_EncodePriority(MKV5X_ETH_IRQ_PRIORITY_GROUPING, 00200 MKV5X_ETH_IRQ_GROUP_PRIORITY, MKV5X_ETH_IRQ_SUB_PRIORITY)); 00201 00202 //Configure ENET error interrupt priority 00203 NVIC_SetPriority(ENET_Error_IRQn, NVIC_EncodePriority(MKV5X_ETH_IRQ_PRIORITY_GROUPING, 00204 MKV5X_ETH_IRQ_GROUP_PRIORITY, MKV5X_ETH_IRQ_SUB_PRIORITY)); 00205 00206 //Enable Ethernet MAC 00207 ENET->ECR |= ENET_ECR_ETHEREN_MASK; 00208 //Instruct the DMA to poll the receive descriptor list 00209 ENET->RDAR = ENET_RDAR_RDAR_MASK; 00210 00211 //Accept any packets from the upper layer 00212 osSetEvent(&interface->nicTxEvent); 00213 00214 //Successful initialization 00215 return NO_ERROR; 00216 } 00217 00218 00219 //TWR-KV58F220M evaluation board? 00220 #if defined(USE_TWR_KV58F220M) 00221 00222 /** 00223 * @brief GPIO configuration 00224 * @param[in] interface Underlying network interface 00225 **/ 00226 00227 void mkv5xEthInitGpio(NetInterface *interface) 00228 { 00229 //Enable PORTA peripheral clock 00230 SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK; 00231 00232 //Configure MII0_RXER (PTA5) 00233 PORTA->PCR[5] = PORT_PCR_MUX(4) | PORT_PCR_PE_MASK; 00234 //Configure MII0_MDIO (PTA7) 00235 PORTA->PCR[7] = PORT_PCR_MUX(5) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; 00236 //Configure MII0_MDC (PTA8) 00237 PORTA->PCR[8] = PORT_PCR_MUX(5); 00238 //Configure MII0_RXD3 (PTA9) 00239 PORTA->PCR[9] = PORT_PCR_MUX(5); 00240 //Configure MII0_RXD2 (PTA10) 00241 PORTA->PCR[10] = PORT_PCR_MUX(5); 00242 //Configure MII0_RXCLK (PTA11) 00243 PORTA->PCR[11] = PORT_PCR_MUX(5); 00244 //Configure MII0_RXD1 (PTA12) 00245 PORTA->PCR[12] = PORT_PCR_MUX(5); 00246 //Configure MII0_RXD0 (PTA13) 00247 PORTA->PCR[13] = PORT_PCR_MUX(5); 00248 //Configure MII0_RXDV (PTA14) 00249 PORTA->PCR[14] = PORT_PCR_MUX(5); 00250 //Configure MII0_TXEN (PTA15) 00251 PORTA->PCR[15] = PORT_PCR_MUX(5); 00252 //Configure MII0_TXD0 (PTA16) 00253 PORTA->PCR[16] = PORT_PCR_MUX(5); 00254 //Configure MII0_TXD1 (PTA17) 00255 PORTA->PCR[17] = PORT_PCR_MUX(5); 00256 //Configure MII0_TXD2 (PTA24) 00257 PORTA->PCR[24] = PORT_PCR_MUX(5); 00258 //Configure MII0_TXCLK (PTA25) 00259 PORTA->PCR[25] = PORT_PCR_MUX(5); 00260 //Configure MII0_TXD3 (PTA26) 00261 PORTA->PCR[26] = PORT_PCR_MUX(5); 00262 //Configure MII0_CRS (PTA27) 00263 PORTA->PCR[27] = PORT_PCR_MUX(5); 00264 //Configure MII0_COL (PTA29) 00265 PORTA->PCR[29] = PORT_PCR_MUX(5); 00266 } 00267 00268 #endif 00269 00270 00271 /** 00272 * @brief Initialize buffer descriptors 00273 * @param[in] interface Underlying network interface 00274 **/ 00275 00276 void mkv5xEthInitBufferDesc(NetInterface *interface) 00277 { 00278 uint_t i; 00279 uint32_t address; 00280 00281 //Clear TX and RX buffer descriptors 00282 memset(txBufferDesc, 0, sizeof(txBufferDesc)); 00283 memset(rxBufferDesc, 0, sizeof(rxBufferDesc)); 00284 00285 //Initialize TX buffer descriptors 00286 for(i = 0; i < MKV5X_ETH_TX_BUFFER_COUNT; i++) 00287 { 00288 //Calculate the address of the current TX buffer 00289 address = (uint32_t) txBuffer[i]; 00290 //Transmit buffer address 00291 txBufferDesc[i][2] = htobe16(address >> 16); 00292 txBufferDesc[i][3] = htobe16(address & 0xFFFF); 00293 //Generate interrupts 00294 txBufferDesc[i][4] = HTOBE16(ENET_TBD4_INT); 00295 } 00296 00297 //Mark the last descriptor entry with the wrap flag 00298 txBufferDesc[i - 1][0] |= HTOBE16(ENET_TBD0_W); 00299 //Initialize TX buffer index 00300 txBufferIndex = 0; 00301 00302 //Initialize RX buffer descriptors 00303 for(i = 0; i < MKV5X_ETH_RX_BUFFER_COUNT; i++) 00304 { 00305 //Calculate the address of the current RX buffer 00306 address = (uint32_t) rxBuffer[i]; 00307 //The descriptor is initially owned by the DMA 00308 rxBufferDesc[i][0] = HTOBE16(ENET_RBD0_E); 00309 //Receive buffer address 00310 rxBufferDesc[i][2] = htobe16(address >> 16); 00311 rxBufferDesc[i][3] = htobe16(address & 0xFFFF); 00312 //Generate interrupts 00313 rxBufferDesc[i][4] = HTOBE16(ENET_RBD4_INT); 00314 } 00315 00316 //Mark the last descriptor entry with the wrap flag 00317 rxBufferDesc[i - 1][0] |= HTOBE16(ENET_RBD0_W); 00318 //Initialize RX buffer index 00319 rxBufferIndex = 0; 00320 00321 //Start location of the TX descriptor list 00322 ENET->TDSR = (uint32_t) txBufferDesc; 00323 //Start location of the RX descriptor list 00324 ENET->RDSR = (uint32_t) rxBufferDesc; 00325 //Maximum receive buffer size 00326 ENET->MRBR = MKV5X_ETH_RX_BUFFER_SIZE; 00327 } 00328 00329 00330 /** 00331 * @brief Kinetis KV5x Ethernet MAC timer handler 00332 * 00333 * This routine is periodically called by the TCP/IP stack to 00334 * handle periodic operations such as polling the link state 00335 * 00336 * @param[in] interface Underlying network interface 00337 **/ 00338 00339 void mkv5xEthTick(NetInterface *interface) 00340 { 00341 //Handle periodic operations 00342 interface->phyDriver->tick(interface); 00343 } 00344 00345 00346 /** 00347 * @brief Enable interrupts 00348 * @param[in] interface Underlying network interface 00349 **/ 00350 00351 void mkv5xEthEnableIrq(NetInterface *interface) 00352 { 00353 //Enable Ethernet MAC interrupts 00354 NVIC_EnableIRQ(ENET_Transmit_IRQn); 00355 NVIC_EnableIRQ(ENET_Receive_IRQn); 00356 NVIC_EnableIRQ(ENET_Error_IRQn); 00357 //Enable Ethernet PHY interrupts 00358 interface->phyDriver->enableIrq(interface); 00359 } 00360 00361 00362 /** 00363 * @brief Disable interrupts 00364 * @param[in] interface Underlying network interface 00365 **/ 00366 00367 void mkv5xEthDisableIrq(NetInterface *interface) 00368 { 00369 //Disable Ethernet MAC interrupts 00370 NVIC_DisableIRQ(ENET_Transmit_IRQn); 00371 NVIC_DisableIRQ(ENET_Receive_IRQn); 00372 NVIC_DisableIRQ(ENET_Error_IRQn); 00373 //Disable Ethernet PHY interrupts 00374 interface->phyDriver->disableIrq(interface); 00375 } 00376 00377 00378 /** 00379 * @brief Ethernet MAC transmit interrupt 00380 **/ 00381 00382 void ENET_Transmit_IRQHandler(void) 00383 { 00384 bool_t flag; 00385 00386 //Enter interrupt service routine 00387 osEnterIsr(); 00388 00389 //This flag will be set if a higher priority task must be woken 00390 flag = FALSE; 00391 00392 //A packet has been transmitted? 00393 if(ENET->EIR & ENET_EIR_TXF_MASK) 00394 { 00395 //Clear TXF interrupt flag 00396 ENET->EIR = ENET_EIR_TXF_MASK; 00397 00398 //Check whether the TX buffer is available for writing 00399 if(!(txBufferDesc[txBufferIndex][0] & HTOBE16(ENET_TBD0_R))) 00400 { 00401 //Notify the TCP/IP stack that the transmitter is ready to send 00402 flag = osSetEventFromIsr(&nicDriverInterface->nicTxEvent); 00403 } 00404 00405 //Instruct the DMA to poll the transmit descriptor list 00406 ENET->TDAR = ENET_TDAR_TDAR_MASK; 00407 } 00408 00409 //Leave interrupt service routine 00410 osExitIsr(flag); 00411 } 00412 00413 00414 /** 00415 * @brief Ethernet MAC receive interrupt 00416 **/ 00417 00418 void ENET_Receive_IRQHandler(void) 00419 { 00420 bool_t flag; 00421 00422 //Enter interrupt service routine 00423 osEnterIsr(); 00424 00425 //This flag will be set if a higher priority task must be woken 00426 flag = FALSE; 00427 00428 //A packet has been received? 00429 if(ENET->EIR & ENET_EIR_RXF_MASK) 00430 { 00431 //Disable RXF interrupt 00432 ENET->EIMR &= ~ENET_EIMR_RXF_MASK; 00433 00434 //Set event flag 00435 nicDriverInterface->nicEvent = TRUE; 00436 //Notify the TCP/IP stack of the event 00437 flag = osSetEventFromIsr(&netEvent); 00438 } 00439 00440 //Leave interrupt service routine 00441 osExitIsr(flag); 00442 } 00443 00444 00445 /** 00446 * @brief Ethernet MAC error interrupt 00447 **/ 00448 00449 void ENET_Error_IRQHandler(void) 00450 { 00451 bool_t flag; 00452 00453 //Enter interrupt service routine 00454 osEnterIsr(); 00455 00456 //This flag will be set if a higher priority task must be woken 00457 flag = FALSE; 00458 00459 //System bus error? 00460 if(ENET->EIR & ENET_EIR_EBERR_MASK) 00461 { 00462 //Disable EBERR interrupt 00463 ENET->EIMR &= ~ENET_EIMR_EBERR_MASK; 00464 00465 //Set event flag 00466 nicDriverInterface->nicEvent = TRUE; 00467 //Notify the TCP/IP stack of the event 00468 flag |= osSetEventFromIsr(&netEvent); 00469 } 00470 00471 //Leave interrupt service routine 00472 osExitIsr(flag); 00473 } 00474 00475 00476 /** 00477 * @brief Kinetis KV5x Ethernet MAC event handler 00478 * @param[in] interface Underlying network interface 00479 **/ 00480 00481 void mkv5xEthEventHandler(NetInterface *interface) 00482 { 00483 error_t error; 00484 uint32_t status; 00485 00486 //Read interrupt event register 00487 status = ENET->EIR; 00488 00489 //Packet received? 00490 if(status & ENET_EIR_RXF_MASK) 00491 { 00492 //Clear RXF interrupt flag 00493 ENET->EIR = ENET_EIR_RXF_MASK; 00494 00495 //Process all pending packets 00496 do 00497 { 00498 //Read incoming packet 00499 error = mkv5xEthReceivePacket(interface); 00500 00501 //No more data in the receive buffer? 00502 } while(error != ERROR_BUFFER_EMPTY); 00503 } 00504 00505 //System bus error? 00506 if(status & ENET_EIR_EBERR_MASK) 00507 { 00508 //Clear EBERR interrupt flag 00509 ENET->EIR = ENET_EIR_EBERR_MASK; 00510 00511 //Disable Ethernet MAC 00512 ENET->ECR &= ~ENET_ECR_ETHEREN_MASK; 00513 //Reset buffer descriptors 00514 mkv5xEthInitBufferDesc(interface); 00515 //Resume normal operation 00516 ENET->ECR |= ENET_ECR_ETHEREN_MASK; 00517 //Instruct the DMA to poll the receive descriptor list 00518 ENET->RDAR = ENET_RDAR_RDAR_MASK; 00519 } 00520 00521 //Re-enable Ethernet MAC interrupts 00522 ENET->EIMR = ENET_EIMR_TXF_MASK | ENET_EIMR_RXF_MASK | ENET_EIMR_EBERR_MASK; 00523 } 00524 00525 00526 /** 00527 * @brief Send a packet 00528 * @param[in] interface Underlying network interface 00529 * @param[in] buffer Multi-part buffer containing the data to send 00530 * @param[in] offset Offset to the first data byte 00531 * @return Error code 00532 **/ 00533 00534 error_t mkv5xEthSendPacket(NetInterface *interface, 00535 const NetBuffer *buffer, size_t offset) 00536 { 00537 size_t length; 00538 00539 //Retrieve the length of the packet 00540 length = netBufferGetLength(buffer) - offset; 00541 00542 //Check the frame length 00543 if(length > MKV5X_ETH_TX_BUFFER_SIZE) 00544 { 00545 //The transmitter can accept another packet 00546 osSetEvent(&interface->nicTxEvent); 00547 //Report an error 00548 return ERROR_INVALID_LENGTH; 00549 } 00550 00551 //Make sure the current buffer is available for writing 00552 if(txBufferDesc[txBufferIndex][0] & HTOBE16(ENET_TBD0_R)) 00553 return ERROR_FAILURE; 00554 00555 //Copy user data to the transmit buffer 00556 netBufferRead(txBuffer[txBufferIndex], buffer, offset, length); 00557 00558 //Set frame length 00559 txBufferDesc[txBufferIndex][1] = HTOBE16(length); 00560 //Clear BDU flag 00561 txBufferDesc[txBufferIndex][8] = 0; 00562 00563 //Check current index 00564 if(txBufferIndex < (MKV5X_ETH_TX_BUFFER_COUNT - 1)) 00565 { 00566 //Give the ownership of the descriptor to the DMA engine 00567 txBufferDesc[txBufferIndex][0] = HTOBE16(ENET_TBD0_R | 00568 ENET_TBD0_L | ENET_TBD0_TC); 00569 00570 //Point to the next buffer 00571 txBufferIndex++; 00572 } 00573 else 00574 { 00575 //Give the ownership of the descriptor to the DMA engine 00576 txBufferDesc[txBufferIndex][0] = HTOBE16(ENET_TBD0_R | 00577 ENET_TBD0_W | ENET_TBD0_L | ENET_TBD0_TC); 00578 00579 //Wrap around 00580 txBufferIndex = 0; 00581 } 00582 00583 //Data synchronization barrier 00584 __DSB(); 00585 00586 //Instruct the DMA to poll the transmit descriptor list 00587 ENET->TDAR = ENET_TDAR_TDAR_MASK; 00588 00589 //Check whether the next buffer is available for writing 00590 if(!(txBufferDesc[txBufferIndex][0] & HTOBE16(ENET_TBD0_R))) 00591 { 00592 //The transmitter can accept another packet 00593 osSetEvent(&interface->nicTxEvent); 00594 } 00595 00596 //Successful processing 00597 return NO_ERROR; 00598 } 00599 00600 00601 /** 00602 * @brief Receive a packet 00603 * @param[in] interface Underlying network interface 00604 * @return Error code 00605 **/ 00606 00607 error_t mkv5xEthReceivePacket(NetInterface *interface) 00608 { 00609 static uint8_t temp[MKV5X_ETH_RX_BUFFER_SIZE]; 00610 error_t error; 00611 size_t n; 00612 00613 //Make sure the current buffer is available for reading 00614 if(!(rxBufferDesc[rxBufferIndex][0] & HTOBE16(ENET_RBD0_E))) 00615 { 00616 //The frame should not span multiple buffers 00617 if(rxBufferDesc[rxBufferIndex][0] & HTOBE16(ENET_RBD0_L)) 00618 { 00619 //Check whether an error occurred 00620 if(!(rxBufferDesc[rxBufferIndex][0] & HTOBE16(ENET_RBD0_LG | 00621 ENET_RBD0_NO | ENET_RBD0_CR | ENET_RBD0_OV | ENET_RBD0_TR))) 00622 { 00623 //Retrieve the length of the frame 00624 n = betoh16(rxBufferDesc[rxBufferIndex][1]); 00625 //Limit the number of data to read 00626 n = MIN(n, MKV5X_ETH_RX_BUFFER_SIZE); 00627 00628 //Copy data from the receive buffer 00629 memcpy(temp, rxBuffer[rxBufferIndex], n); 00630 00631 //Pass the packet to the upper layer 00632 nicProcessPacket(interface, temp, n); 00633 00634 //Valid packet received 00635 error = NO_ERROR; 00636 } 00637 else 00638 { 00639 //The received packet contains an error 00640 error = ERROR_INVALID_PACKET; 00641 } 00642 } 00643 else 00644 { 00645 //The packet is not valid 00646 error = ERROR_INVALID_PACKET; 00647 } 00648 00649 //Clear BDU flag 00650 rxBufferDesc[rxBufferIndex][8] = 0; 00651 00652 //Check current index 00653 if(rxBufferIndex < (MKV5X_ETH_RX_BUFFER_COUNT - 1)) 00654 { 00655 //Give the ownership of the descriptor back to the DMA engine 00656 rxBufferDesc[rxBufferIndex][0] = HTOBE16(ENET_RBD0_E); 00657 //Point to the next buffer 00658 rxBufferIndex++; 00659 } 00660 else 00661 { 00662 //Give the ownership of the descriptor back to the DMA engine 00663 rxBufferDesc[rxBufferIndex][0] = HTOBE16(ENET_RBD0_E | ENET_RBD0_W); 00664 //Wrap around 00665 rxBufferIndex = 0; 00666 } 00667 00668 //Instruct the DMA to poll the receive descriptor list 00669 ENET->RDAR = ENET_RDAR_RDAR_MASK; 00670 } 00671 else 00672 { 00673 //No more data in the receive buffer 00674 error = ERROR_BUFFER_EMPTY; 00675 } 00676 00677 //Return status code 00678 return error; 00679 } 00680 00681 00682 /** 00683 * @brief Configure multicast MAC address filtering 00684 * @param[in] interface Underlying network interface 00685 * @return Error code 00686 **/ 00687 00688 error_t mkv5xEthSetMulticastFilter(NetInterface *interface) 00689 { 00690 uint_t i; 00691 uint_t k; 00692 uint32_t crc; 00693 uint32_t hashTable[2]; 00694 MacFilterEntry *entry; 00695 00696 //Debug message 00697 TRACE_DEBUG("Updating Kinetis KV5x hash table...\r\n"); 00698 00699 //Clear hash table 00700 hashTable[0] = 0; 00701 hashTable[1] = 0; 00702 00703 //The MAC filter table contains the multicast MAC addresses 00704 //to accept when receiving an Ethernet frame 00705 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++) 00706 { 00707 //Point to the current entry 00708 entry = &interface->macMulticastFilter[i]; 00709 00710 //Valid entry? 00711 if(entry->refCount > 0) 00712 { 00713 //Compute CRC over the current MAC address 00714 crc = mkv5xEthCalcCrc(&entry->addr, sizeof(MacAddr)); 00715 00716 //The upper 6 bits in the CRC register are used to index the 00717 //contents of the hash table 00718 k = (crc >> 26) & 0x3F; 00719 00720 //Update hash table contents 00721 hashTable[k / 32] |= (1 << (k % 32)); 00722 } 00723 } 00724 00725 //Write the hash table 00726 ENET->GALR = hashTable[0]; 00727 ENET->GAUR = hashTable[1]; 00728 00729 //Debug message 00730 TRACE_DEBUG(" GALR = %08" PRIX32 "\r\n", ENET->GALR); 00731 TRACE_DEBUG(" GAUR = %08" PRIX32 "\r\n", ENET->GAUR); 00732 00733 //Successful processing 00734 return NO_ERROR; 00735 } 00736 00737 00738 /** 00739 * @brief Adjust MAC configuration parameters for proper operation 00740 * @param[in] interface Underlying network interface 00741 * @return Error code 00742 **/ 00743 00744 error_t mkv5xEthUpdateMacConfig(NetInterface *interface) 00745 { 00746 //Disable Ethernet MAC while modifying configuration registers 00747 ENET->ECR &= ~ENET_ECR_ETHEREN_MASK; 00748 00749 //10BASE-T or 100BASE-TX operation mode? 00750 if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS) 00751 { 00752 //100 Mbps operation 00753 ENET->RCR &= ~ENET_RCR_RMII_10T_MASK; 00754 } 00755 else 00756 { 00757 //10 Mbps operation 00758 ENET->RCR |= ENET_RCR_RMII_10T_MASK; 00759 } 00760 00761 //Half-duplex or full-duplex mode? 00762 if(interface->duplexMode == NIC_FULL_DUPLEX_MODE) 00763 { 00764 //Full-duplex mode 00765 ENET->TCR |= ENET_TCR_FDEN_MASK; 00766 //Receive path operates independently of transmit 00767 ENET->RCR &= ~ENET_RCR_DRT_MASK; 00768 } 00769 else 00770 { 00771 //Half-duplex mode 00772 ENET->TCR &= ~ENET_TCR_FDEN_MASK; 00773 //Disable reception of frames while transmitting 00774 ENET->RCR |= ENET_RCR_DRT_MASK; 00775 } 00776 00777 //Reset buffer descriptors 00778 mkv5xEthInitBufferDesc(interface); 00779 00780 //Re-enable Ethernet MAC 00781 ENET->ECR |= ENET_ECR_ETHEREN_MASK; 00782 //Instruct the DMA to poll the receive descriptor list 00783 ENET->RDAR = ENET_RDAR_RDAR_MASK; 00784 00785 //Successful processing 00786 return NO_ERROR; 00787 } 00788 00789 00790 /** 00791 * @brief Write PHY register 00792 * @param[in] phyAddr PHY address 00793 * @param[in] regAddr Register address 00794 * @param[in] data Register value 00795 **/ 00796 00797 void mkv5xEthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data) 00798 { 00799 uint32_t value; 00800 00801 //Set up a write operation 00802 value = ENET_MMFR_ST(1) | ENET_MMFR_OP(1) | ENET_MMFR_TA(2); 00803 //PHY address 00804 value |= ENET_MMFR_PA(phyAddr); 00805 //Register address 00806 value |= ENET_MMFR_RA(regAddr); 00807 //Register value 00808 value |= ENET_MMFR_DATA(data); 00809 00810 //Clear MII interrupt flag 00811 ENET->EIR = ENET_EIR_MII_MASK; 00812 //Start a write operation 00813 ENET->MMFR = value; 00814 //Wait for the write to complete 00815 while(!(ENET->EIR & ENET_EIR_MII_MASK)); 00816 } 00817 00818 00819 /** 00820 * @brief Read PHY register 00821 * @param[in] phyAddr PHY address 00822 * @param[in] regAddr Register address 00823 * @return Register value 00824 **/ 00825 00826 uint16_t mkv5xEthReadPhyReg(uint8_t phyAddr, uint8_t regAddr) 00827 { 00828 uint32_t value; 00829 00830 //Set up a read operation 00831 value = ENET_MMFR_ST(1) | ENET_MMFR_OP(2) | ENET_MMFR_TA(2); 00832 //PHY address 00833 value |= ENET_MMFR_PA(phyAddr); 00834 //Register address 00835 value |= ENET_MMFR_RA(regAddr); 00836 00837 //Clear MII interrupt flag 00838 ENET->EIR = ENET_EIR_MII_MASK; 00839 //Start a read operation 00840 ENET->MMFR = value; 00841 //Wait for the read to complete 00842 while(!(ENET->EIR & ENET_EIR_MII_MASK)); 00843 00844 //Return PHY register contents 00845 return ENET->MMFR & ENET_MMFR_DATA_MASK; 00846 } 00847 00848 00849 /** 00850 * @brief CRC calculation 00851 * @param[in] data Pointer to the data over which to calculate the CRC 00852 * @param[in] length Number of bytes to process 00853 * @return Resulting CRC value 00854 **/ 00855 00856 uint32_t mkv5xEthCalcCrc(const void *data, size_t length) 00857 { 00858 uint_t i; 00859 uint_t j; 00860 00861 //Point to the data over which to calculate the CRC 00862 const uint8_t *p = (uint8_t *) data; 00863 //CRC preset value 00864 uint32_t crc = 0xFFFFFFFF; 00865 00866 //Loop through data 00867 for(i = 0; i < length; i++) 00868 { 00869 //Update CRC value 00870 crc ^= p[i]; 00871 //The message is processed bit by bit 00872 for(j = 0; j < 8; j++) 00873 { 00874 if(crc & 0x00000001) 00875 crc = (crc >> 1) ^ 0xEDB88320; 00876 else 00877 crc = crc >> 1; 00878 } 00879 } 00880 00881 //Return CRC value 00882 return crc; 00883 } 00884
Generated on Tue Jul 12 2022 17:10:14 by
