Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pic32mz_eth.c Source File

pic32mz_eth.c

Go to the documentation of this file.
00001 /**
00002  * @file pic32mz_eth.c
00003  * @brief PIC32MZ Ethernet MAC controller
00004  *
00005  * @section License
00006  *
00007  * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
00008  *
00009  * This file is part of CycloneTCP Open.
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software Foundation,
00023  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00024  *
00025  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00026  * @version 1.7.6
00027  **/
00028 
00029 //Switch to the appropriate trace level
00030 #define TRACE_LEVEL NIC_TRACE_LEVEL
00031 
00032 //Dependencies
00033 #include <p32xxxx.h>
00034 #include <sys/kmem.h>
00035 #include "core/net.h"
00036 #include "drivers/pic32mz_eth.h"
00037 #include "debug.h"
00038 
00039 //Underlying network interface
00040 static NetInterface *nicDriverInterface;
00041 
00042 //Transmit buffer
00043 static uint8_t txBuffer[PIC32MZ_ETH_TX_BUFFER_COUNT][PIC32MZ_ETH_TX_BUFFER_SIZE]
00044    __attribute__((aligned(4)));
00045 //Receive buffer
00046 static uint8_t rxBuffer[PIC32MZ_ETH_RX_BUFFER_COUNT][PIC32MZ_ETH_RX_BUFFER_SIZE]
00047    __attribute__((aligned(4)));
00048 //Transmit buffer descriptors
00049 static Pic32mzTxBufferDesc txBufferDesc[PIC32MZ_ETH_TX_BUFFER_COUNT]
00050    __attribute__((aligned(4)));
00051 //Receive buffer descriptors
00052 static Pic32mzRxBufferDesc rxBufferDesc[PIC32MZ_ETH_RX_BUFFER_COUNT]
00053    __attribute__((aligned(4)));
00054 
00055 //Pointer to the current TX buffer descriptor
00056 static Pic32mzTxBufferDesc *txCurBufferDesc;
00057 //Pointer to the current RX buffer descriptor
00058 static Pic32mzRxBufferDesc *rxCurBufferDesc;
00059 
00060 
00061 /**
00062  * @brief PIC32MZ Ethernet MAC driver
00063  **/
00064 
00065 const NicDriver pic32mzEthDriver =
00066 {
00067    NIC_TYPE_ETHERNET,
00068    ETH_MTU,
00069    pic32mzEthInit,
00070    pic32mzEthTick,
00071    pic32mzEthEnableIrq,
00072    pic32mzEthDisableIrq,
00073    pic32mzEthEventHandler,
00074    pic32mzEthSendPacket,
00075    pic32mzEthSetMulticastFilter,
00076    pic32mzEthUpdateMacConfig,
00077    pic32mzEthWritePhyReg,
00078    pic32mzEthReadPhyReg,
00079    TRUE,
00080    TRUE,
00081    TRUE,
00082    FALSE
00083 };
00084 
00085 
00086 /**
00087  * @brief PIC32MZ Ethernet MAC initialization
00088  * @param[in] interface Underlying network interface
00089  * @return Error code
00090  **/
00091 
00092 error_t pic32mzEthInit(NetInterface *interface)
00093 {
00094    error_t error;
00095 
00096    //Debug message
00097    TRACE_INFO("Initializing PIC32MZ Ethernet MAC...\r\n");
00098 
00099    //Save underlying network interface
00100    nicDriverInterface = interface;
00101 
00102    //GPIO configuration
00103    pic32mzEthInitGpio(interface);
00104 
00105    //Disable Ethernet interrupts
00106    IEC4CLR = _IEC4_ETHIE_MASK;
00107    //Turn the Ethernet controller off
00108    ETHCON1CLR = _ETHCON1_ON_MASK | _ETHCON1_TXRTS_POSITION | _ETHCON1_RXEN_MASK;
00109 
00110    //Wait activity abort by polling the ETHBUSY bit
00111    while(ETHSTAT & _ETHSTAT_ETHBUSY_MASK);
00112 
00113    //Enable the Ethernet controller by setting the ON bit
00114    ETHCON1SET = _ETHCON1_ON_MASK;
00115 
00116    //Clear Ethernet interrupt flag
00117    IFS4CLR = _IFS4_ETHIF_MASK;
00118    //Disable any Ethernet controller interrupt generation
00119    ETHIEN = 0;
00120    ETHIRQ = 0;
00121    //Clear the TX and RX start addresses
00122    ETHTXST = 0;
00123    ETHRXST = 0;
00124 
00125    //Reset the MAC using SOFTRESET
00126    EMAC1CFG1SET = _EMAC1CFG1_SOFTRESET_MASK;
00127    EMAC1CFG1CLR = _EMAC1CFG1_SOFTRESET_MASK;
00128 
00129    //Reset the RMII module
00130    EMAC1SUPPSET = _EMAC1SUPP_RESETRMII_MASK;
00131    EMAC1SUPPCLR = _EMAC1SUPP_RESETRMII_MASK;
00132 
00133    //Issue an MIIM block reset by setting the RESETMGMT bit
00134    EMAC1MCFGSET = _EMAC1MCFG_RESETMGMT_MASK;
00135    EMAC1MCFGCLR = _EMAC1MCFG_RESETMGMT_MASK;
00136 
00137    //Select the proper divider for the MDC clock
00138    EMAC1MCFG = _EMAC1MCFG_CLKSEL_DIV50;
00139 
00140    //PHY transceiver initialization
00141    error = interface->phyDriver->init(interface);
00142    //Failed to initialize PHY transceiver?
00143    if(error)
00144       return error;
00145 
00146    //Optionally set the station MAC address
00147    if(macCompAddr(&interface->macAddr, &MAC_UNSPECIFIED_ADDR))
00148    {
00149       //Use the factory preprogrammed station address
00150       interface->macAddr.w[0] = EMAC1SA2;
00151       interface->macAddr.w[1] = EMAC1SA1;
00152       interface->macAddr.w[2] = EMAC1SA0;
00153 
00154       //Generate the 64-bit interface identifier
00155       macAddrToEui64(&interface->macAddr, &interface->eui64);
00156    }
00157    else
00158    {
00159       //Override the factory preprogrammed address
00160       EMAC1SA0 = interface->macAddr.w[2];
00161       EMAC1SA1 = interface->macAddr.w[1];
00162       EMAC1SA2 = interface->macAddr.w[0];
00163    }
00164 
00165    //Initialize hash table
00166    ETHHT0 = 0;
00167    ETHHT1 = 0;
00168 
00169    //Configure the receive filter
00170    ETHRXFC = _ETHRXFC_HTEN_MASK | _ETHRXFC_CRCOKEN_MASK |
00171       _ETHRXFC_RUNTEN_MASK | _ETHRXFC_UCEN_MASK | _ETHRXFC_BCEN_MASK;
00172 
00173    //Disable flow control
00174    EMAC1CFG1 = _EMAC1CFG1_RXENABLE_MASK;
00175    //Automatic padding and CRC generation
00176    EMAC1CFG2 = _EMAC1CFG2_PADENABLE_MASK | _EMAC1CFG2_CRCENABLE_MASK;
00177    //Set the maximum frame length
00178    EMAC1MAXF = 1518;
00179 
00180    //Initialize DMA descriptor lists
00181    pic32mzEthInitBufferDesc(interface);
00182 
00183    //Enable desired interrupts
00184    ETHIENSET = _ETHIEN_PKTPENDIE_MASK | _ETHIEN_TXDONEIE_MASK;
00185 
00186    //Set interrupt priority
00187    IPC38CLR = _IPC38_ETHIP_MASK;
00188    IPC38SET = (PIC32MZ_ETH_IRQ_PRIORITY << _IPC38_ETHIP_POSITION);
00189    //Set interrupt subpriority
00190    IPC38CLR = _IPC38_ETHIS_MASK;
00191    IPC38SET = (PIC32MZ_ETH_IRQ_SUB_PRIORITY << _IPC38_ETHIS_POSITION);
00192 
00193    //Enable the reception by setting the RXEN bit
00194    ETHCON1SET = _ETHCON1_RXEN_MASK;
00195 
00196    //Accept any packets from the upper layer
00197    osSetEvent(&interface->nicTxEvent);
00198 
00199    //Successful initialization
00200    return NO_ERROR;
00201 }
00202 
00203 
00204 //PIC32MZ EC Starter Kit, PIC32MZ EF Starter Kit or IoT Ethernet Kit?
00205 #if defined(USE_PIC32MZ_EC_STARTER_KIT) || defined(USE_PIC32MZ_EF_STARTER_KIT) || \
00206    defined(USE_IOT_ETHERNET_KIT)
00207 
00208 /**
00209  * @brief GPIO configuration
00210  * @param[in] interface Underlying network interface
00211  **/
00212 
00213 void pic32mzEthInitGpio(NetInterface *interface)
00214 {
00215 //PIC32MZ EC Starter Kit or PIC32MZ EF Starter Kit?
00216 #if defined(USE_PIC32MZ_EC_STARTER_KIT) || defined(USE_PIC32MZ_EF_STARTER_KIT)
00217    //Disable analog pad on ETXD0 (AN35/RJ8)
00218    ANSELJCLR = _ANSELJ_ANSJ8_MASK;
00219    //Disable analog pad on ETXD1 (AN36/RJ9)
00220    ANSELJCLR = _ANSELJ_ANSJ9_MASK;
00221    //Disable analog pad on EREFCLK (AN37/RJ11)
00222    ANSELJCLR = _ANSELJ_ANSJ11_MASK;
00223    //Disable analog pad on ERXERR (AN40/RH4)
00224    ANSELHCLR = _ANSELH_ANSH4_MASK;
00225    //Disable analog pad on ERXD1 (AN41/RH5)
00226    ANSELHCLR = _ANSELH_ANSH5_MASK;
00227 
00228 //IoT Ethernet Kit?
00229 #elif defined(USE_IOT_ETHERNET_KIT)
00230    //Disable analog pad on ERXERR (AN18/RE4)
00231    ANSELECLR = _ANSELE_ANSE4_MASK;
00232    //Disable analog pad on ETXEN (AN17/RE5)
00233    ANSELECLR = _ANSELE_ANSE5_MASK;
00234    //Disable analog pad on ETXD0 (AN16/RE6)
00235    ANSELECLR = _ANSELE_ANSE6_MASK;
00236    //Disable analog pad on ETXD1 (AN15/RE7)
00237    ANSELECLR = _ANSELE_ANSE7_MASK;
00238 #endif
00239 }
00240 
00241 #endif
00242 
00243 
00244 /**
00245  * @brief Initialize DMA descriptor lists
00246  * @param[in] interface Underlying network interface
00247  **/
00248 
00249 void pic32mzEthInitBufferDesc(NetInterface *interface)
00250 {
00251    uint_t i;
00252 
00253    //Initialize TX descriptor list
00254    for(i = 0; i < PIC32MZ_ETH_TX_BUFFER_COUNT; i++)
00255    {
00256       //Point to the current descriptor
00257       txCurBufferDesc = KVA0_TO_KVA1(&txBufferDesc[i]);
00258 
00259       //Use linked list rather than linear list
00260       txCurBufferDesc->control = ETH_TX_CTRL_NPV;
00261       //Transmit buffer address
00262       txCurBufferDesc->address = (uint32_t) KVA_TO_PA(txBuffer[i]);
00263       //Transmit status vector
00264       txCurBufferDesc->status1 = 0;
00265       txCurBufferDesc->status2 = 0;
00266       //Next descriptor address
00267       txCurBufferDesc->next = (uint32_t) KVA_TO_PA(&txBufferDesc[i + 1]);
00268    }
00269 
00270    //The last descriptor is chained to the first entry
00271    txCurBufferDesc->next = (uint32_t) KVA_TO_PA(&txBufferDesc[0]);
00272    //Point to the very first descriptor
00273    txCurBufferDesc = KVA0_TO_KVA1(&txBufferDesc[0]);
00274 
00275    //Initialize RX descriptor list
00276    for(i = 0; i < PIC32MZ_ETH_RX_BUFFER_COUNT; i++)
00277    {
00278       //Point to the current descriptor
00279       rxCurBufferDesc = KVA0_TO_KVA1(&rxBufferDesc[i]);
00280 
00281       //The descriptor is initially owned by the DMA
00282       rxCurBufferDesc->control = ETH_RX_CTRL_NPV | ETH_RX_CTRL_EOWN;
00283       //Receive buffer address
00284       rxCurBufferDesc->address = (uint32_t) KVA_TO_PA(rxBuffer[i]);
00285       //Receive status vector
00286       rxCurBufferDesc->status1 = 0;
00287       rxCurBufferDesc->status2 = 0;
00288       //Next descriptor address
00289       rxCurBufferDesc->next = (uint32_t) KVA_TO_PA(&rxBufferDesc[i + 1]);
00290    }
00291 
00292    //The last descriptor is chained to the first entry
00293    rxCurBufferDesc->next = (uint32_t) KVA_TO_PA(&rxBufferDesc[0]);
00294    //Point to the very first descriptor
00295    rxCurBufferDesc = KVA0_TO_KVA1(&rxBufferDesc[0]);
00296 
00297    //Starting address of TX descriptor table
00298    ETHTXST = (uint32_t) KVA_TO_PA(&txBufferDesc[0]);
00299    //Starting address of RX descriptor table
00300    ETHRXST = (uint32_t) KVA_TO_PA(&rxBufferDesc[0]);
00301    //Set receive buffer size
00302    ETHCON2 = PIC32MZ_ETH_RX_BUFFER_SIZE;
00303 }
00304 
00305 
00306 /**
00307  * @brief PIC32MZ Ethernet MAC timer handler
00308  *
00309  * This routine is periodically called by the TCP/IP stack to
00310  * handle periodic operations such as polling the link state
00311  *
00312  * @param[in] interface Underlying network interface
00313  **/
00314 
00315 void pic32mzEthTick(NetInterface *interface)
00316 {
00317    //Handle periodic operations
00318    interface->phyDriver->tick(interface);
00319 }
00320 
00321 
00322 /**
00323  * @brief Enable interrupts
00324  * @param[in] interface Underlying network interface
00325  **/
00326 
00327 void pic32mzEthEnableIrq(NetInterface *interface)
00328 {
00329    //Enable Ethernet MAC interrupts
00330    IEC4SET = _IEC4_ETHIE_MASK;
00331    //Enable Ethernet PHY interrupts
00332    interface->phyDriver->enableIrq(interface);
00333 }
00334 
00335 
00336 /**
00337  * @brief Disable interrupts
00338  * @param[in] interface Underlying network interface
00339  **/
00340 
00341 void pic32mzEthDisableIrq(NetInterface *interface)
00342 {
00343    //Disable Ethernet MAC interrupts
00344    IEC4CLR = _IEC4_ETHIE_MASK;
00345    //Disable Ethernet PHY interrupts
00346    interface->phyDriver->disableIrq(interface);
00347 }
00348 
00349 
00350 /**
00351  * @brief PIC32MZ Ethernet MAC interrupt service routine
00352  **/
00353 
00354 void pic32mzEthIrqHandler(void)
00355 {
00356    bool_t flag;
00357    uint32_t status;
00358 
00359    //Enter interrupt service routine
00360    osEnterIsr();
00361 
00362    //This flag will be set if a higher priority task must be woken
00363    flag = FALSE;
00364 
00365    //Read interrupt status register
00366    status = ETHIRQ;
00367 
00368    //A packet has been transmitted?
00369    if(status & _ETHIRQ_TXDONE_MASK)
00370    {
00371       //Clear TXDONE interrupt flag
00372       ETHIRQCLR = _ETHIRQ_TXDONE_MASK;
00373 
00374       //Check whether the TX buffer is available for writing
00375       if(!(txCurBufferDesc->control & ETH_TX_CTRL_EOWN))
00376       {
00377          //Notify the TCP/IP stack that the transmitter is ready to send
00378          flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
00379       }
00380    }
00381 
00382    //A packet has been received?
00383    if(status & _ETHIRQ_PKTPEND_MASK)
00384    {
00385       //Disable PKTPEND interrupt
00386       ETHIENCLR = _ETHIEN_PKTPENDIE_MASK;
00387 
00388       //Set event flag
00389       nicDriverInterface->nicEvent = TRUE;
00390       //Notify the TCP/IP stack of the event
00391       flag |= osSetEventFromIsr(&netEvent);
00392    }
00393 
00394    //Clear ETHIF interrupt flag before exiting the service routine
00395    IFS4CLR = _IFS4_ETHIF_MASK;
00396 
00397    //Leave interrupt service routine
00398    osExitIsr(flag);
00399 }
00400 
00401 
00402 /**
00403  * @brief PIC32MZ Ethernet MAC event handler
00404  * @param[in] interface Underlying network interface
00405  **/
00406 
00407 void pic32mzEthEventHandler(NetInterface *interface)
00408 {
00409    error_t error;
00410 
00411    //Packet received?
00412    if(ETHIRQ & _ETHIRQ_PKTPEND_MASK)
00413    {
00414       //Process all pending packets
00415       do
00416       {
00417          //Read incoming packet
00418          error = pic32mzEthReceivePacket(interface);
00419 
00420          //No more data in the receive buffer?
00421       } while(error != ERROR_BUFFER_EMPTY);
00422    }
00423 
00424    //Re-enable PKTPEND interrupt
00425    ETHIENSET = _ETHIEN_PKTPENDIE_MASK;
00426 }
00427 
00428 
00429 /**
00430  * @brief Send a packet
00431  * @param[in] interface Underlying network interface
00432  * @param[in] buffer Multi-part buffer containing the data to send
00433  * @param[in] offset Offset to the first data byte
00434  * @return Error code
00435  **/
00436 
00437 error_t pic32mzEthSendPacket(NetInterface *interface,
00438    const NetBuffer *buffer, size_t offset)
00439 {
00440    size_t length;
00441    uint32_t value;
00442 
00443    //Retrieve the length of the packet
00444    length = netBufferGetLength(buffer) - offset;
00445 
00446    //Check the frame length
00447    if(length > PIC32MZ_ETH_TX_BUFFER_SIZE)
00448    {
00449       //The transmitter can accept another packet
00450       osSetEvent(&interface->nicTxEvent);
00451       //Report an error
00452       return ERROR_INVALID_LENGTH;
00453    }
00454 
00455    //Make sure the current buffer is available for writing
00456    if(txCurBufferDesc->control & ETH_TX_CTRL_EOWN)
00457       return ERROR_FAILURE;
00458 
00459    //Copy user data to the transmit buffer
00460    netBufferRead(PA_TO_KVA1(txCurBufferDesc->address), buffer, offset, length);
00461 
00462    //Write the number of bytes to send
00463    value = (length << 16) & ETH_TX_CTRL_BYTE_COUNT;
00464    //Set SOP and EOP flags since the data fits in a single buffer
00465    value |= ETH_TX_CTRL_SOP | ETH_TX_CTRL_EOP | ETH_TX_CTRL_NPV;
00466    //Give the ownership of the descriptor to the DMA
00467    txCurBufferDesc->control = value | ETH_TX_CTRL_EOWN;
00468 
00469    //Set TXRTS bit to start the transmission
00470    ETHCON1SET = _ETHCON1_TXRTS_MASK;
00471 
00472    //Point to the next descriptor in the list
00473    txCurBufferDesc = PA_TO_KVA1(txCurBufferDesc->next);
00474 
00475    //Check whether the next buffer is available for writing
00476    if(!(txCurBufferDesc->control & ETH_TX_CTRL_EOWN))
00477    {
00478       //The transmitter can accept another packet
00479       osSetEvent(&interface->nicTxEvent);
00480    }
00481 
00482    //Data successfully written
00483    return NO_ERROR;
00484 }
00485 
00486 
00487 /**
00488  * @brief Receive a packet
00489  * @param[in] interface Underlying network interface
00490  * @return Error code
00491  **/
00492 
00493 error_t pic32mzEthReceivePacket(NetInterface *interface)
00494 {
00495    static uint8_t temp[PIC32MZ_ETH_RX_BUFFER_SIZE];
00496    error_t error;
00497    size_t n;
00498 
00499    //The current buffer is available for reading?
00500    if(!(rxCurBufferDesc->control & ETH_RX_CTRL_EOWN))
00501    {
00502       //SOP and EOP flags should be set
00503       if((rxCurBufferDesc->control & ETH_RX_CTRL_SOP) &&
00504          (rxCurBufferDesc->control & ETH_RX_CTRL_EOP))
00505       {
00506          //Make sure no error occurred
00507          if(rxCurBufferDesc->status2 & ETH_RX_STATUS2_OK)
00508          {
00509             //Retrieve the length of the frame
00510             n = (rxCurBufferDesc->control & ETH_RX_CTRL_BYTE_COUNT) >> 16;
00511             //Limit the number of data to read
00512             n = MIN(n, PIC32MZ_ETH_RX_BUFFER_SIZE);
00513 
00514             //Copy data from the receive buffer
00515             memcpy(temp, PA_TO_KVA1(rxCurBufferDesc->address), n);
00516 
00517             //Pass the packet to the upper layer
00518             nicProcessPacket(interface, temp, n);
00519 
00520             //Valid packet received
00521             error = NO_ERROR;
00522          }
00523          else
00524          {
00525             //The received packet contains an error
00526             error = ERROR_INVALID_PACKET;
00527          }
00528       }
00529       else
00530       {
00531          //The packet is not valid
00532          error = ERROR_INVALID_PACKET;
00533       }
00534 
00535       //Give the ownership of the descriptor back to the DMA
00536       rxCurBufferDesc->control = ETH_RX_CTRL_NPV | ETH_RX_CTRL_EOWN;
00537 
00538       //Point to the next descriptor in the list
00539       rxCurBufferDesc = PA_TO_KVA1(rxCurBufferDesc->next);
00540 
00541       //Decrement BUFCNT counter
00542       ETHCON1SET = _ETHCON1_BUFCDEC_MASK;
00543    }
00544    else
00545    {
00546       //No more data in the receive buffer
00547       error = ERROR_BUFFER_EMPTY;
00548    }
00549 
00550    //Return status code
00551    return error;
00552 }
00553 
00554 
00555 /**
00556  * @brief Configure multicast MAC address filtering
00557  * @param[in] interface Underlying network interface
00558  * @return Error code
00559  **/
00560 
00561 error_t pic32mzEthSetMulticastFilter(NetInterface *interface)
00562 {
00563    uint_t i;
00564    uint_t k;
00565    uint32_t crc;
00566    uint32_t hashTable[2];
00567    MacFilterEntry *entry;
00568 
00569    //Debug message
00570    TRACE_DEBUG("Updating PIC32MZ hash table...\r\n");
00571 
00572    //Clear hash table
00573    hashTable[0] = 0;
00574    hashTable[1] = 0;
00575 
00576    //The MAC filter table contains the multicast MAC addresses
00577    //to accept when receiving an Ethernet frame
00578    for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++)
00579    {
00580       //Point to the current entry
00581       entry = &interface->macMulticastFilter[i];
00582 
00583       //Valid entry?
00584       if(entry->refCount > 0)
00585       {
00586          //Compute CRC over the current MAC address
00587          crc = pic32mzEthCalcCrc(&entry->addr, sizeof(MacAddr));
00588          //Calculate the corresponding index in the table
00589          k = (crc >> 23) & 0x3F;
00590          //Update hash table contents
00591          hashTable[k / 32] |= (1 << (k % 32));
00592       }
00593    }
00594 
00595    //Write the hash table
00596    ETHHT0 = hashTable[0];
00597    ETHHT1 = hashTable[1];
00598 
00599    //Debug message
00600    TRACE_DEBUG("  ETHHT0 = %08" PRIX32 "\r\n", ETHHT0);
00601    TRACE_DEBUG("  ETHHT1 = %08" PRIX32 "\r\n", ETHHT1);
00602 
00603    //Successful processing
00604    return NO_ERROR;
00605 }
00606 
00607 
00608 /**
00609  * @brief Adjust MAC configuration parameters for proper operation
00610  * @param[in] interface Underlying network interface
00611  * @return Error code
00612  **/
00613 
00614 error_t pic32mzEthUpdateMacConfig(NetInterface *interface)
00615 {
00616    //Check current operating speed
00617    if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
00618    {
00619       //100BASE-TX operation mode
00620       EMAC1SUPPSET = _EMAC1SUPP_SPEEDRMII_MASK;
00621    }
00622    else
00623    {
00624       //10BASE-T operation mode
00625       EMAC1SUPPCLR = _EMAC1SUPP_SPEEDRMII_MASK;
00626    }
00627 
00628    //Half-duplex or full-duplex mode?
00629    if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
00630    {
00631       //Configure FULLDPLX bit to match the current duplex mode
00632       EMAC1CFG2SET = _EMAC1CFG2_FULLDPLX_MASK;
00633       //Configure the Back-to-Back Inter-Packet Gap register
00634       EMAC1IPGT = 0x15;
00635    }
00636    else
00637    {
00638       //Configure FULLDPLX bit to match the current duplex mode
00639       EMAC1CFG2CLR = _EMAC1CFG2_FULLDPLX_MASK;
00640       //Configure the Back-to-Back Inter-Packet Gap register
00641       EMAC1IPGT = 0x12;
00642    }
00643 
00644    //Successful processing
00645    return NO_ERROR;
00646 }
00647 
00648 
00649 /**
00650  * @brief Write PHY register
00651  * @param[in] phyAddr PHY address
00652  * @param[in] regAddr Register address
00653  * @param[in] data Register value
00654  **/
00655 
00656 void pic32mzEthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data)
00657 {
00658    uint_t i;
00659 
00660    //Set PHY address and register address
00661    EMAC1MADR = (phyAddr << _EMAC1MADR_PHYADDR_POSITION) | regAddr;
00662    //Start a write operation
00663    EMAC1MWTD = data & _EMAC1MWTD_MWTD_MASK;
00664 
00665    //Wait for busy bit to be set
00666    for(i = 0; i < 16; i++)
00667       __asm__ __volatile__ ("nop;");
00668 
00669    //Wait for the write to complete
00670    while(EMAC1MIND & _EMAC1MIND_MIIMBUSY_MASK);
00671 }
00672 
00673 
00674 /**
00675  * @brief Read PHY register
00676  * @param[in] phyAddr PHY address
00677  * @param[in] regAddr Register address
00678  * @return Register value
00679  **/
00680 
00681 uint16_t pic32mzEthReadPhyReg(uint8_t phyAddr, uint8_t regAddr)
00682 {
00683    uint_t i;
00684 
00685    //Set PHY address and register address
00686    EMAC1MADR = (phyAddr << _EMAC1MADR_PHYADDR_POSITION) | regAddr;
00687    //Start a read operation
00688    EMAC1MCMD = _EMAC1MCMD_READ_MASK;
00689 
00690    //Wait for busy bit to be set
00691    for(i = 0; i < 16; i++)
00692       __asm__ __volatile__ ("nop;");
00693 
00694    //Wait for the read to complete
00695    while(EMAC1MIND & _EMAC1MIND_MIIMBUSY_MASK);
00696 
00697    //Clear command register
00698    EMAC1MCMD = 0;
00699    //Return PHY register contents
00700    return EMAC1MRDD & _EMAC1MRDD_MRDD_MASK;
00701 }
00702 
00703 
00704 /**
00705  * @brief CRC calculation
00706  * @param[in] data Pointer to the data over which to calculate the CRC
00707  * @param[in] length Number of bytes to process
00708  * @return Resulting CRC value
00709  **/
00710 
00711 uint32_t pic32mzEthCalcCrc(const void *data, size_t length)
00712 {
00713    uint_t i;
00714    uint_t j;
00715 
00716    //Point to the data over which to calculate the CRC
00717    const uint8_t *p = (uint8_t *) data;
00718    //CRC preset value
00719    uint32_t crc = 0xFFFFFFFF;
00720 
00721    //Loop through data
00722    for(i = 0; i < length; i++)
00723    {
00724       //The message is processed bit by bit
00725       for(j = 0; j < 8; j++)
00726       {
00727          //Update CRC value
00728          if(((crc >> 31) ^ (p[i] >> j)) & 0x01)
00729             crc = (crc << 1) ^ 0x04C11DB7;
00730          else
00731             crc = crc << 1;
00732       }
00733    }
00734 
00735    //Return CRC value
00736    return crc;
00737 }
00738