Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mkv5x_eth.c Source File

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