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