Sergey Pastor / 1

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mk6x_eth.c Source File

mk6x_eth.c

Go to the documentation of this file.
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