Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pic32mx_eth.c Source File

pic32mx_eth.c

Go to the documentation of this file.
00001 /**
00002  * @file pic32mx_eth.c
00003  * @brief PIC32MX 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/pic32mx_eth.h"
00037 #include "debug.h"
00038 
00039 //Underlying network interface
00040 static NetInterface *nicDriverInterface;
00041 
00042 //Transmit buffer
00043 static uint8_t txBuffer[PIC32MX_ETH_TX_BUFFER_COUNT][PIC32MX_ETH_TX_BUFFER_SIZE]
00044    __attribute__((aligned(4)));
00045 //Receive buffer
00046 static uint8_t rxBuffer[PIC32MX_ETH_RX_BUFFER_COUNT][PIC32MX_ETH_RX_BUFFER_SIZE]
00047    __attribute__((aligned(4)));
00048 //Transmit buffer descriptors
00049 static Pic32mxTxBufferDesc txBufferDesc[PIC32MX_ETH_TX_BUFFER_COUNT]
00050    __attribute__((aligned(4)));
00051 //Receive buffer descriptors
00052 static Pic32mxRxBufferDesc rxBufferDesc[PIC32MX_ETH_RX_BUFFER_COUNT]
00053    __attribute__((aligned(4)));
00054 
00055 //Pointer to the current TX buffer descriptor
00056 static Pic32mxTxBufferDesc *txCurBufferDesc;
00057 //Pointer to the current RX buffer descriptor
00058 static Pic32mxRxBufferDesc *rxCurBufferDesc;
00059 
00060 
00061 /**
00062  * @brief PIC32MX Ethernet MAC driver
00063  **/
00064 
00065 const NicDriver pic32mxEthDriver =
00066 {
00067    NIC_TYPE_ETHERNET,
00068    ETH_MTU,
00069    pic32mxEthInit,
00070    pic32mxEthTick,
00071    pic32mxEthEnableIrq,
00072    pic32mxEthDisableIrq,
00073    pic32mxEthEventHandler,
00074    pic32mxEthSendPacket,
00075    pic32mxEthSetMulticastFilter,
00076    pic32mxEthUpdateMacConfig,
00077    pic32mxEthWritePhyReg,
00078    pic32mxEthReadPhyReg,
00079    TRUE,
00080    TRUE,
00081    TRUE,
00082    FALSE
00083 };
00084 
00085 
00086 /**
00087  * @brief PIC32MX Ethernet MAC initialization
00088  * @param[in] interface Underlying network interface
00089  * @return Error code
00090  **/
00091 
00092 error_t pic32mxEthInit(NetInterface *interface)
00093 {
00094    error_t error;
00095 
00096    //Debug message
00097    TRACE_INFO("Initializing PIC32MX Ethernet MAC...\r\n");
00098 
00099    //Save underlying network interface
00100    nicDriverInterface = interface;
00101 
00102    //GPIO configuration
00103    pic32mxEthInitGpio(interface);
00104 
00105    //Disable Ethernet interrupts
00106    IEC1CLR = _IEC1_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    IFS1CLR = _IFS1_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_DIV40;
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    pic32mxEthInitBufferDesc(interface);
00182 
00183    //Enable desired interrupts
00184    ETHIENSET = _ETHIEN_PKTPENDIE_MASK | _ETHIEN_TXDONEIE_MASK;
00185 
00186    //Set interrupt priority
00187    IPC12CLR = _IPC12_ETHIP_MASK;
00188    IPC12SET = (PIC32MX_ETH_IRQ_PRIORITY << _IPC12_ETHIP_POSITION);
00189    //Set interrupt subpriority
00190    IPC12CLR = _IPC12_ETHIS_MASK;
00191    IPC12SET = (PIC32MX_ETH_IRQ_SUB_PRIORITY << _IPC12_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 //PIC32 Ethernet Starter Kit?
00205 #if defined(USE_PIC32_ETH_STARTER_KIT) || defined(USE_PIC32_ETH_STARTER_KIT_2)
00206 
00207 /**
00208  * @brief GPIO configuration
00209  * @param[in] interface Underlying network interface
00210  **/
00211 
00212 void pic32mxEthInitGpio(NetInterface *interface)
00213 {
00214    //No analog pins are shared with the alternate RMII interface
00215 }
00216 
00217 #endif
00218 
00219 
00220 /**
00221  * @brief Initialize DMA descriptor lists
00222  * @param[in] interface Underlying network interface
00223  **/
00224 
00225 void pic32mxEthInitBufferDesc(NetInterface *interface)
00226 {
00227    uint_t i;
00228 
00229    //Initialize TX descriptor list
00230    for(i = 0; i < PIC32MX_ETH_TX_BUFFER_COUNT; i++)
00231    {
00232       //Point to the current descriptor
00233       txCurBufferDesc = KVA0_TO_KVA1(&txBufferDesc[i]);
00234 
00235       //Use linked list rather than linear list
00236       txCurBufferDesc->control = ETH_TX_CTRL_NPV;
00237       //Transmit buffer address
00238       txCurBufferDesc->address = (uint32_t) KVA_TO_PA(txBuffer[i]);
00239       //Transmit status vector
00240       txCurBufferDesc->status1 = 0;
00241       txCurBufferDesc->status2 = 0;
00242       //Next descriptor address
00243       txCurBufferDesc->next = (uint32_t) KVA_TO_PA(&txBufferDesc[i + 1]);
00244    }
00245 
00246    //The last descriptor is chained to the first entry
00247    txCurBufferDesc->next = (uint32_t) KVA_TO_PA(&txBufferDesc[0]);
00248    //Point to the very first descriptor
00249    txCurBufferDesc = KVA0_TO_KVA1(&txBufferDesc[0]);
00250 
00251    //Initialize RX descriptor list
00252    for(i = 0; i < PIC32MX_ETH_RX_BUFFER_COUNT; i++)
00253    {
00254       //Point to the current descriptor
00255       rxCurBufferDesc = KVA0_TO_KVA1(&rxBufferDesc[i]);
00256 
00257       //The descriptor is initially owned by the DMA
00258       rxCurBufferDesc->control = ETH_RX_CTRL_NPV | ETH_RX_CTRL_EOWN;
00259       //Receive buffer address
00260       rxCurBufferDesc->address = (uint32_t) KVA_TO_PA(rxBuffer[i]);
00261       //Receive status vector
00262       rxCurBufferDesc->status1 = 0;
00263       rxCurBufferDesc->status2 = 0;
00264       //Next descriptor address
00265       rxCurBufferDesc->next = (uint32_t) KVA_TO_PA(&rxBufferDesc[i + 1]);
00266    }
00267 
00268    //The last descriptor is chained to the first entry
00269    rxCurBufferDesc->next = (uint32_t) KVA_TO_PA(&rxBufferDesc[0]);
00270    //Point to the very first descriptor
00271    rxCurBufferDesc = KVA0_TO_KVA1(&rxBufferDesc[0]);
00272 
00273    //Starting address of TX descriptor table
00274    ETHTXST = (uint32_t) KVA_TO_PA(&txBufferDesc[0]);
00275    //Starting address of RX descriptor table
00276    ETHRXST = (uint32_t) KVA_TO_PA(&rxBufferDesc[0]);
00277    //Set receive buffer size
00278    ETHCON2 = PIC32MX_ETH_RX_BUFFER_SIZE;
00279 }
00280 
00281 
00282 /**
00283  * @brief PIC32MX Ethernet MAC timer handler
00284  *
00285  * This routine is periodically called by the TCP/IP stack to
00286  * handle periodic operations such as polling the link state
00287  *
00288  * @param[in] interface Underlying network interface
00289  **/
00290 
00291 void pic32mxEthTick(NetInterface *interface)
00292 {
00293    //Handle periodic operations
00294    interface->phyDriver->tick(interface);
00295 }
00296 
00297 
00298 /**
00299  * @brief Enable interrupts
00300  * @param[in] interface Underlying network interface
00301  **/
00302 
00303 void pic32mxEthEnableIrq(NetInterface *interface)
00304 {
00305    //Enable Ethernet MAC interrupts
00306    IEC1SET = _IEC1_ETHIE_MASK;
00307    //Enable Ethernet PHY interrupts
00308    interface->phyDriver->enableIrq(interface);
00309 }
00310 
00311 
00312 /**
00313  * @brief Disable interrupts
00314  * @param[in] interface Underlying network interface
00315  **/
00316 
00317 void pic32mxEthDisableIrq(NetInterface *interface)
00318 {
00319    //Disable Ethernet MAC interrupts
00320    IEC1CLR = _IEC1_ETHIE_MASK;
00321    //Disable Ethernet PHY interrupts
00322    interface->phyDriver->disableIrq(interface);
00323 }
00324 
00325 
00326 /**
00327  * @brief PIC32MX Ethernet MAC interrupt service routine
00328  **/
00329 
00330 void pic32mxEthIrqHandler(void)
00331 {
00332    bool_t flag;
00333    uint32_t status;
00334 
00335    //Enter interrupt service routine
00336    osEnterIsr();
00337 
00338    //This flag will be set if a higher priority task must be woken
00339    flag = FALSE;
00340 
00341    //Read interrupt status register
00342    status = ETHIRQ;
00343 
00344    //A packet has been transmitted?
00345    if(status & _ETHIRQ_TXDONE_MASK)
00346    {
00347       //Clear TXDONE interrupt flag
00348       ETHIRQCLR = _ETHIRQ_TXDONE_MASK;
00349 
00350       //Check whether the TX buffer is available for writing
00351       if(!(txCurBufferDesc->control & ETH_TX_CTRL_EOWN))
00352       {
00353          //Notify the TCP/IP stack that the transmitter is ready to send
00354          flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
00355       }
00356    }
00357 
00358    //A packet has been received?
00359    if(status & _ETHIRQ_PKTPEND_MASK)
00360    {
00361       //Disable PKTPEND interrupt
00362       ETHIENCLR = _ETHIEN_PKTPENDIE_MASK;
00363 
00364       //Set event flag
00365       nicDriverInterface->nicEvent = TRUE;
00366       //Notify the TCP/IP stack of the event
00367       flag |= osSetEventFromIsr(&netEvent);
00368    }
00369 
00370    //Clear ETHIF interrupt flag before exiting the service routine
00371    IFS1CLR = _IFS1_ETHIF_MASK;
00372 
00373    //Leave interrupt service routine
00374    osExitIsr(flag);
00375 }
00376 
00377 
00378 /**
00379  * @brief PIC32MX Ethernet MAC event handler
00380  * @param[in] interface Underlying network interface
00381  **/
00382 
00383 void pic32mxEthEventHandler(NetInterface *interface)
00384 {
00385    error_t error;
00386 
00387    //Packet received?
00388    if(ETHIRQ & _ETHIRQ_PKTPEND_MASK)
00389    {
00390       //Process all pending packets
00391       do
00392       {
00393          //Read incoming packet
00394          error = pic32mxEthReceivePacket(interface);
00395 
00396          //No more data in the receive buffer?
00397       } while(error != ERROR_BUFFER_EMPTY);
00398    }
00399 
00400    //Re-enable PKTPEND interrupt
00401    ETHIENSET = _ETHIEN_PKTPENDIE_MASK;
00402 }
00403 
00404 
00405 /**
00406  * @brief Send a packet
00407  * @param[in] interface Underlying network interface
00408  * @param[in] buffer Multi-part buffer containing the data to send
00409  * @param[in] offset Offset to the first data byte
00410  * @return Error code
00411  **/
00412 
00413 error_t pic32mxEthSendPacket(NetInterface *interface,
00414    const NetBuffer *buffer, size_t offset)
00415 {
00416    size_t length;
00417    uint32_t value;
00418 
00419    //Retrieve the length of the packet
00420    length = netBufferGetLength(buffer) - offset;
00421 
00422    //Check the frame length
00423    if(length > PIC32MX_ETH_TX_BUFFER_SIZE)
00424    {
00425       //The transmitter can accept another packet
00426       osSetEvent(&interface->nicTxEvent);
00427       //Report an error
00428       return ERROR_INVALID_LENGTH;
00429    }
00430 
00431    //Make sure the current buffer is available for writing
00432    if(txCurBufferDesc->control & ETH_TX_CTRL_EOWN)
00433       return ERROR_FAILURE;
00434 
00435    //Copy user data to the transmit buffer
00436    netBufferRead(PA_TO_KVA1(txCurBufferDesc->address), buffer, offset, length);
00437 
00438    //Write the number of bytes to send
00439    value = (length << 16) & ETH_TX_CTRL_BYTE_COUNT;
00440    //Set SOP and EOP flags since the data fits in a single buffer
00441    value |= ETH_TX_CTRL_SOP | ETH_TX_CTRL_EOP | ETH_TX_CTRL_NPV;
00442    //Give the ownership of the descriptor to the DMA
00443    txCurBufferDesc->control = value | ETH_TX_CTRL_EOWN;
00444 
00445    //Set TXRTS bit to start the transmission
00446    ETHCON1SET = _ETHCON1_TXRTS_MASK;
00447 
00448    //Point to the next descriptor in the list
00449    txCurBufferDesc = PA_TO_KVA1(txCurBufferDesc->next);
00450 
00451    //Check whether the next buffer is available for writing
00452    if(!(txCurBufferDesc->control & ETH_TX_CTRL_EOWN))
00453    {
00454       //The transmitter can accept another packet
00455       osSetEvent(&interface->nicTxEvent);
00456    }
00457 
00458    //Data successfully written
00459    return NO_ERROR;
00460 }
00461 
00462 
00463 /**
00464  * @brief Receive a packet
00465  * @param[in] interface Underlying network interface
00466  * @return Error code
00467  **/
00468 
00469 error_t pic32mxEthReceivePacket(NetInterface *interface)
00470 {
00471    static uint8_t temp[PIC32MX_ETH_RX_BUFFER_SIZE];
00472    error_t error;
00473    size_t n;
00474 
00475    //The current buffer is available for reading?
00476    if(!(rxCurBufferDesc->control & ETH_RX_CTRL_EOWN))
00477    {
00478       //SOP and EOP flags should be set
00479       if((rxCurBufferDesc->control & ETH_RX_CTRL_SOP) &&
00480          (rxCurBufferDesc->control & ETH_RX_CTRL_EOP))
00481       {
00482          //Make sure no error occurred
00483          if(rxCurBufferDesc->status2 & ETH_RX_STATUS2_OK)
00484          {
00485             //Retrieve the length of the frame
00486             n = (rxCurBufferDesc->control & ETH_RX_CTRL_BYTE_COUNT) >> 16;
00487             //Limit the number of data to read
00488             n = MIN(n, PIC32MX_ETH_RX_BUFFER_SIZE);
00489 
00490             //Copy data from the receive buffer
00491             memcpy(temp, PA_TO_KVA1(rxCurBufferDesc->address), n);
00492 
00493             //Pass the packet to the upper layer
00494             nicProcessPacket(interface, temp, n);
00495 
00496             //Valid packet received
00497             error = NO_ERROR;
00498          }
00499          else
00500          {
00501             //The received packet contains an error
00502             error = ERROR_INVALID_PACKET;
00503          }
00504       }
00505       else
00506       {
00507          //The packet is not valid
00508          error = ERROR_INVALID_PACKET;
00509       }
00510 
00511       //Give the ownership of the descriptor back to the DMA
00512       rxCurBufferDesc->control = ETH_RX_CTRL_NPV | ETH_RX_CTRL_EOWN;
00513 
00514       //Point to the next descriptor in the list
00515       rxCurBufferDesc = PA_TO_KVA1(rxCurBufferDesc->next);
00516 
00517       //Decrement BUFCNT counter
00518       ETHCON1SET = _ETHCON1_BUFCDEC_MASK;
00519    }
00520    else
00521    {
00522       //No more data in the receive buffer
00523       error = ERROR_BUFFER_EMPTY;
00524    }
00525 
00526    //Return status code
00527    return error;
00528 }
00529 
00530 
00531 /**
00532  * @brief Configure multicast MAC address filtering
00533  * @param[in] interface Underlying network interface
00534  * @return Error code
00535  **/
00536 
00537 error_t pic32mxEthSetMulticastFilter(NetInterface *interface)
00538 {
00539    uint_t i;
00540    uint_t k;
00541    uint32_t crc;
00542    uint32_t hashTable[2];
00543    MacFilterEntry *entry;
00544 
00545    //Debug message
00546    TRACE_DEBUG("Updating PIC32MX hash table...\r\n");
00547 
00548    //Clear hash table
00549    hashTable[0] = 0;
00550    hashTable[1] = 0;
00551 
00552    //The MAC filter table contains the multicast MAC addresses
00553    //to accept when receiving an Ethernet frame
00554    for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++)
00555    {
00556       //Point to the current entry
00557       entry = &interface->macMulticastFilter[i];
00558 
00559       //Valid entry?
00560       if(entry->refCount > 0)
00561       {
00562          //Compute CRC over the current MAC address
00563          crc = pic32mxEthCalcCrc(&entry->addr, sizeof(MacAddr));
00564          //Calculate the corresponding index in the table
00565          k = (crc >> 23) & 0x3F;
00566          //Update hash table contents
00567          hashTable[k / 32] |= (1 << (k % 32));
00568       }
00569    }
00570 
00571    //Write the hash table
00572    ETHHT0 = hashTable[0];
00573    ETHHT1 = hashTable[1];
00574 
00575    //Debug message
00576    TRACE_DEBUG("  ETHHT0 = %08" PRIX32 "\r\n", ETHHT0);
00577    TRACE_DEBUG("  ETHHT1 = %08" PRIX32 "\r\n", ETHHT1);
00578 
00579    //Successful processing
00580    return NO_ERROR;
00581 }
00582 
00583 
00584 /**
00585  * @brief Adjust MAC configuration parameters for proper operation
00586  * @param[in] interface Underlying network interface
00587  * @return Error code
00588  **/
00589 
00590 error_t pic32mxEthUpdateMacConfig(NetInterface *interface)
00591 {
00592    //Check current operating speed
00593    if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
00594    {
00595       //100BASE-TX operation mode
00596       EMAC1SUPPSET = _EMAC1SUPP_SPEEDRMII_MASK;
00597    }
00598    else
00599    {
00600       //10BASE-T operation mode
00601       EMAC1SUPPCLR = _EMAC1SUPP_SPEEDRMII_MASK;
00602    }
00603 
00604    //Half-duplex or full-duplex mode?
00605    if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
00606    {
00607       //Configure FULLDPLX bit to match the current duplex mode
00608       EMAC1CFG2SET = _EMAC1CFG2_FULLDPLX_MASK;
00609       //Configure the Back-to-Back Inter-Packet Gap register
00610       EMAC1IPGT = 0x15;
00611    }
00612    else
00613    {
00614       //Configure FULLDPLX bit to match the current duplex mode
00615       EMAC1CFG2CLR = _EMAC1CFG2_FULLDPLX_MASK;
00616       //Configure the Back-to-Back Inter-Packet Gap register
00617       EMAC1IPGT = 0x12;
00618    }
00619 
00620    //Successful processing
00621    return NO_ERROR;
00622 }
00623 
00624 
00625 /**
00626  * @brief Write PHY register
00627  * @param[in] phyAddr PHY address
00628  * @param[in] regAddr Register address
00629  * @param[in] data Register value
00630  **/
00631 
00632 void pic32mxEthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data)
00633 {
00634    //Set PHY address and register address
00635    EMAC1MADR = (phyAddr << _EMAC1MADR_PHYADDR_POSITION) | regAddr;
00636    //Start a write operation
00637    EMAC1MWTD = data & _EMAC1MWTD_MWTD_MASK;
00638 
00639    //Wait for busy bit to be set
00640    __asm__ __volatile__ ("nop;");
00641    __asm__ __volatile__ ("nop;");
00642    __asm__ __volatile__ ("nop;");
00643 
00644    //Wait for the write to complete
00645    while(EMAC1MIND & _EMAC1MIND_MIIMBUSY_MASK);
00646 }
00647 
00648 
00649 /**
00650  * @brief Read PHY register
00651  * @param[in] phyAddr PHY address
00652  * @param[in] regAddr Register address
00653  * @return Register value
00654  **/
00655 
00656 uint16_t pic32mxEthReadPhyReg(uint8_t phyAddr, uint8_t regAddr)
00657 {
00658    //Set PHY address and register address
00659    EMAC1MADR = (phyAddr << _EMAC1MADR_PHYADDR_POSITION) | regAddr;
00660    //Start a read operation
00661    EMAC1MCMD = _EMAC1MCMD_READ_MASK;
00662 
00663    //Wait for busy bit to be set
00664    __asm__ __volatile__ ("nop;");
00665    __asm__ __volatile__ ("nop;");
00666    __asm__ __volatile__ ("nop;");
00667 
00668    //Wait for the read to complete
00669    while(EMAC1MIND & _EMAC1MIND_MIIMBUSY_MASK);
00670 
00671    //Clear command register
00672    EMAC1MCMD = 0;
00673    //Return PHY register contents
00674    return EMAC1MRDD & _EMAC1MRDD_MRDD_MASK;
00675 }
00676 
00677 
00678 /**
00679  * @brief CRC calculation
00680  * @param[in] data Pointer to the data over which to calculate the CRC
00681  * @param[in] length Number of bytes to process
00682  * @return Resulting CRC value
00683  **/
00684 
00685 uint32_t pic32mxEthCalcCrc(const void *data, size_t length)
00686 {
00687    uint_t i;
00688    uint_t j;
00689 
00690    //Point to the data over which to calculate the CRC
00691    const uint8_t *p = (uint8_t *) data;
00692    //CRC preset value
00693    uint32_t crc = 0xFFFFFFFF;
00694 
00695    //Loop through data
00696    for(i = 0; i < length; i++)
00697    {
00698       //The message is processed bit by bit
00699       for(j = 0; j < 8; j++)
00700       {
00701          //Update CRC value
00702          if(((crc >> 31) ^ (p[i] >> j)) & 0x01)
00703             crc = (crc << 1) ^ 0x04C11DB7;
00704          else
00705             crc = crc << 1;
00706       }
00707    }
00708 
00709    //Return CRC value
00710    return crc;
00711 }
00712