Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers rx63n_eth.c Source File

rx63n_eth.c

Go to the documentation of this file.
00001 /**
00002  * @file rx63n_eth.c
00003  * @brief Renesas RX63N 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 <iorx63n.h>
00034 #include <intrinsics.h>
00035 #include "core/net.h"
00036 #include "drivers/rx63n_eth.h"
00037 #include "debug.h"
00038 
00039 //Underlying network interface
00040 static NetInterface *nicDriverInterface;
00041 
00042 //IAR EWRX compiler?
00043 #if defined(__ICCRX__)
00044 
00045 //Transmit buffer
00046 #pragma data_alignment = 32
00047 static uint8_t txBuffer[RX63N_ETH_TX_BUFFER_COUNT][RX63N_ETH_TX_BUFFER_SIZE];
00048 //Receive buffer
00049 #pragma data_alignment = 32
00050 static uint8_t rxBuffer[RX63N_ETH_RX_BUFFER_COUNT][RX63N_ETH_RX_BUFFER_SIZE];
00051 //Transmit DMA descriptors
00052 #pragma data_alignment = 32
00053 static Rx63nTxDmaDesc txDmaDesc[RX63N_ETH_TX_BUFFER_COUNT];
00054 //Receive DMA descriptors
00055 #pragma data_alignment = 32
00056 static Rx63nRxDmaDesc rxDmaDesc[RX63N_ETH_RX_BUFFER_COUNT];
00057 
00058 //GCC compiler?
00059 #else
00060 
00061 //Transmit buffer
00062 static uint8_t txBuffer[RX63N_ETH_TX_BUFFER_COUNT][RX63N_ETH_TX_BUFFER_SIZE]
00063    __attribute__((aligned(32)));
00064 //Receive buffer
00065 static uint8_t rxBuffer[RX63N_ETH_RX_BUFFER_COUNT][RX63N_ETH_RX_BUFFER_SIZE]
00066    __attribute__((aligned(32)));
00067 //Transmit DMA descriptors
00068 static Rx63nTxDmaDesc txDmaDesc[RX63N_ETH_TX_BUFFER_COUNT]
00069    __attribute__((aligned(32)));
00070 //Receive DMA descriptors
00071 static Rx63nRxDmaDesc rxDmaDesc[RX63N_ETH_RX_BUFFER_COUNT]
00072    __attribute__((aligned(32)));
00073 
00074 #endif
00075 
00076 //Current transmit descriptor
00077 static uint_t txIndex;
00078 //Current receive descriptor
00079 static uint_t rxIndex;
00080 
00081 
00082 /**
00083  * @brief RX63N Ethernet MAC driver
00084  **/
00085 
00086 const NicDriver rx63nEthDriver =
00087 {
00088    NIC_TYPE_ETHERNET,
00089    ETH_MTU,
00090    rx63nEthInit,
00091    rx63nEthTick,
00092    rx63nEthEnableIrq,
00093    rx63nEthDisableIrq,
00094    rx63nEthEventHandler,
00095    rx63nEthSendPacket,
00096    rx63nEthSetMulticastFilter,
00097    rx63nEthUpdateMacConfig,
00098    rx63nEthWritePhyReg,
00099    rx63nEthReadPhyReg,
00100    TRUE,
00101    TRUE,
00102    TRUE,
00103    TRUE
00104 };
00105 
00106 
00107 /**
00108  * @brief RX63N Ethernet MAC initialization
00109  * @param[in] interface Underlying network interface
00110  * @return Error code
00111  **/
00112 
00113 error_t rx63nEthInit(NetInterface *interface)
00114 {
00115    error_t error;
00116 
00117    //Debug message
00118    TRACE_INFO("Initializing RX63N Ethernet MAC...\r\n");
00119 
00120    //Save underlying network interface
00121    nicDriverInterface = interface;
00122 
00123    //Disable protection
00124    SYSTEM.PRCR.WORD = 0xA50B;
00125    //Cancel EDMAC module stop state
00126    MSTP(EDMAC) = 0;
00127    //Enable protection
00128    SYSTEM.PRCR.WORD = 0xA500;
00129 
00130    //GPIO configuration
00131    rx63nEthInitGpio(interface);
00132 
00133    //Reset EDMAC module
00134    EDMAC.EDMR.BIT.SWR = 1;
00135    sleep(10);
00136 
00137    //PHY transceiver initialization
00138    error = interface->phyDriver->init(interface);
00139    //Failed to initialize PHY transceiver?
00140    if(error)
00141       return error;
00142 
00143    //Initialize DMA descriptor lists
00144    rx63nEthInitDmaDesc(interface);
00145 
00146    //Maximum frame length that can be accepted
00147    ETHERC.RFLR.LONG = 1518;
00148    //Set default inter packet gap (96-bit time)
00149    ETHERC.IPGR.LONG = 0x14;
00150 
00151    //Set the upper 32 bits of the MAC address
00152    ETHERC.MAHR = (interface->macAddr.b[0] << 24) | (interface->macAddr.b[1] << 16) |
00153       (interface->macAddr.b[2] << 8) | interface->macAddr.b[3];
00154 
00155    //Set the lower 16 bits of the MAC address
00156    ETHERC.MALR.BIT.MA = (interface->macAddr.b[4] << 8) | interface->macAddr.b[5];
00157 
00158    //Set descriptor length (16 bytes)
00159    EDMAC.EDMR.BIT.DL = 0;
00160    //Select little endian mode
00161    EDMAC.EDMR.BIT.DE = 1;
00162    //Use store and forward mode
00163    EDMAC.TFTR.BIT.TFT = 0;
00164 
00165    //Set transmit FIFO size (2048 bytes)
00166    EDMAC.FDR.BIT.TFD = 7;
00167    //Set receive FIFO size (2048 bytes)
00168    EDMAC.FDR.BIT.RFD = 7;
00169 
00170    //Enable continuous reception of multiple frames
00171    EDMAC.RMCR.BIT.RNR = 1;
00172 
00173    //Accept transmit interrupt notifications
00174    EDMAC.TRIMD.BIT.TIM = 0;
00175    EDMAC.TRIMD.BIT.TIS = 1;
00176 
00177    //Disable all EDMAC interrupts
00178    EDMAC.EESIPR.LONG = 0;
00179    //Enable only the desired EDMAC interrupts
00180    EDMAC.EESIPR.BIT.TWBIP = 1;
00181    EDMAC.EESIPR.BIT.FRIP = 1;
00182 
00183    //Configure EDMAC interrupt priority
00184    IPR(ETHER, EINT) = RX63N_ETH_IRQ_PRIORITY;
00185 
00186    //Enable transmission and reception
00187    ETHERC.ECMR.BIT.TE = 1;
00188    ETHERC.ECMR.BIT.RE = 1;
00189 
00190    //Instruct the DMA to poll the receive descriptor list
00191    EDMAC.EDRRR.BIT.RR = 1;
00192 
00193    //Accept any packets from the upper layer
00194    osSetEvent(&interface->nicTxEvent);
00195 
00196    //Successful initialization
00197    return NO_ERROR;
00198 }
00199 
00200 
00201 //RX63N Demonstration Kit?
00202 #if defined(USE_RDK_RX63N)
00203 
00204 /**
00205  * @brief GPIO configuration
00206  * @param[in] interface Underlying network interface
00207  **/
00208 
00209 void rx63nEthInitGpio(NetInterface *interface)
00210 {
00211    //Unlock MPC registers
00212    MPC.PWPR.BIT.B0WI = 0;
00213    MPC.PWPR.BIT.PFSWE = 1;
00214 
00215    //Select RMII interface mode
00216    MPC.PFENET.BIT.PHYMODE = 0;
00217 
00218    //Configure ET_MDIO (PA3)
00219    PORTA.PMR.BIT.B3 = 1;
00220    MPC.PA3PFS.BYTE = 0x11;
00221 
00222    //Configure ET_MDC (PA4)
00223    PORTA.PMR.BIT.B4 = 1;
00224    MPC.PA4PFS.BYTE = 0x11;
00225 
00226    //Configure ET_LINKSTA (PA5)
00227    PORTA.PMR.BIT.B5 = 1;
00228    MPC.PA5PFS.BYTE = 0x11;
00229 
00230    //Configure RMII_RXD1 (PB0)
00231    PORTB.PMR.BIT.B0 = 1;
00232    MPC.PB0PFS.BYTE = 0x12;
00233 
00234    //Configure RMII_RXD0 (PB1)
00235    PORTB.PMR.BIT.B1 = 1;
00236    MPC.PB1PFS.BYTE = 0x12;
00237 
00238    //Configure REF50CK (PB2)
00239    PORTB.PMR.BIT.B2 = 1;
00240    MPC.PB2PFS.BYTE = 0x12;
00241 
00242    //Configure RMII_RX_ER (PB3)
00243    PORTB.PMR.BIT.B3 = 1;
00244    MPC.PB3PFS.BYTE = 0x12;
00245 
00246    //Configure RMII_TXD_EN (PB4)
00247    PORTB.PMR.BIT.B4 = 1;
00248    MPC.PB4PFS.BYTE = 0x12;
00249 
00250    //Configure RMII_TXD0 (PB5)
00251    PORTB.PMR.BIT.B5 = 1;
00252    MPC.PB5PFS.BYTE = 0x12;
00253 
00254    //Configure RMII_TXD1 (PB6)
00255    PORTB.PMR.BIT.B6 = 1;
00256    MPC.PB6PFS.BYTE = 0x12;
00257 
00258    //Configure RMII_CRS_DV (PB7)
00259    PORTB.PMR.BIT.B7 = 1;
00260    MPC.PB7PFS.BYTE = 0x12;
00261 
00262    //Lock MPC registers
00263    MPC.PWPR.BIT.PFSWE = 0;
00264    MPC.PWPR.BIT.B0WI = 0;
00265 }
00266 
00267 #endif
00268 
00269 
00270 /**
00271  * @brief Initialize DMA descriptor lists
00272  * @param[in] interface Underlying network interface
00273  **/
00274 
00275 void rx63nEthInitDmaDesc(NetInterface *interface)
00276 {
00277    uint_t i;
00278 
00279    //Initialize TX descriptors
00280    for(i = 0; i < RX63N_ETH_TX_BUFFER_COUNT; i++)
00281    {
00282       //The descriptor is initially owned by the application
00283       txDmaDesc[i].td0 = 0;
00284       //Transmit buffer length
00285       txDmaDesc[i].td1 = 0;
00286       //Transmit buffer address
00287       txDmaDesc[i].td2 = (uint32_t) txBuffer[i];
00288       //Clear padding field
00289       txDmaDesc[i].padding = 0;
00290    }
00291 
00292    //Mark the last descriptor entry with the TDLE flag
00293    txDmaDesc[i - 1].td0 |= EDMAC_TD0_TDLE;
00294    //Initialize TX descriptor index
00295    txIndex = 0;
00296 
00297    //Initialize RX descriptors
00298    for(i = 0; i < RX63N_ETH_RX_BUFFER_COUNT; i++)
00299    {
00300       //The descriptor is initially owned by the DMA
00301       rxDmaDesc[i].rd0 = EDMAC_RD0_RACT;
00302       //Receive buffer length
00303       rxDmaDesc[i].rd1 = (RX63N_ETH_RX_BUFFER_SIZE << 16) & EDMAC_RD1_RBL;
00304       //Receive buffer address
00305       rxDmaDesc[i].rd2 = (uint32_t) rxBuffer[i];
00306       //Clear padding field
00307       rxDmaDesc[i].padding = 0;
00308    }
00309 
00310    //Mark the last descriptor entry with the RDLE flag
00311    rxDmaDesc[i - 1].rd0 |= EDMAC_RD0_RDLE;
00312    //Initialize RX descriptor index
00313    rxIndex = 0;
00314 
00315    //Start address of the TX descriptor list
00316    EDMAC.TDLAR = txDmaDesc;
00317    //Start address of the RX descriptor list
00318    EDMAC.RDLAR = rxDmaDesc;
00319 }
00320 
00321 
00322 /**
00323  * @brief RX63N Ethernet MAC timer handler
00324  *
00325  * This routine is periodically called by the TCP/IP stack to
00326  * handle periodic operations such as polling the link state
00327  *
00328  * @param[in] interface Underlying network interface
00329  **/
00330 
00331 void rx63nEthTick(NetInterface *interface)
00332 {
00333    //Handle periodic operations
00334    interface->phyDriver->tick(interface);
00335 }
00336 
00337 
00338 /**
00339  * @brief Enable interrupts
00340  * @param[in] interface Underlying network interface
00341  **/
00342 
00343 void rx63nEthEnableIrq(NetInterface *interface)
00344 {
00345    //Enable Ethernet MAC interrupts
00346    IEN(ETHER, EINT) = 1;
00347    //Enable Ethernet PHY interrupts
00348    interface->phyDriver->enableIrq(interface);
00349 }
00350 
00351 
00352 /**
00353  * @brief Disable interrupts
00354  * @param[in] interface Underlying network interface
00355  **/
00356 
00357 void rx63nEthDisableIrq(NetInterface *interface)
00358 {
00359    //Disable Ethernet MAC interrupts
00360    IEN(ETHER, EINT) = 0;
00361    //Disable Ethernet PHY interrupts
00362    interface->phyDriver->disableIrq(interface);
00363 }
00364 
00365 
00366 /**
00367  * @brief RX63N Ethernet MAC interrupt service routine
00368  **/
00369 
00370 #pragma vector = VECT_ETHER_EINT
00371 __interrupt void rx63nEthIrqHandler(void)
00372 {
00373    bool_t flag;
00374    uint32_t status;
00375 
00376    //Allow nested interrupts
00377    __enable_interrupt();
00378 
00379    //This flag will be set if a higher priority task must be woken
00380    flag = FALSE;
00381 
00382    //Read interrupt status register
00383    status = EDMAC.EESR.LONG;
00384 
00385    //A packet has been transmitted?
00386    if(status & EDMAC_EESR_TWB)
00387    {
00388       //Clear TWB interrupt flag
00389       EDMAC.EESR.LONG = EDMAC_EESR_TWB;
00390 
00391       //Check whether the TX buffer is available for writing
00392       if(!(txDmaDesc[txIndex].td0 & EDMAC_TD0_TACT))
00393       {
00394          //Notify the TCP/IP stack that the transmitter is ready to send
00395          flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
00396       }
00397    }
00398 
00399    //A packet has been received?
00400    if(status & EDMAC_EESR_FR)
00401    {
00402       //Disable FR interrupts
00403       EDMAC.EESIPR.BIT.FRIP = 0;
00404 
00405       //Set event flag
00406       nicDriverInterface->nicEvent = TRUE;
00407       //Notify the TCP/IP stack of the event
00408       flag |= osSetEventFromIsr(&netEvent);
00409    }
00410 
00411    //Leave interrupt service routine
00412    osExitIsr(flag);
00413 }
00414 
00415 
00416 /**
00417  * @brief RX63N Ethernet MAC event handler
00418  * @param[in] interface Underlying network interface
00419  **/
00420 
00421 void rx63nEthEventHandler(NetInterface *interface)
00422 {
00423    error_t error;
00424 
00425    //Packet received?
00426    if(EDMAC.EESR.LONG & EDMAC_EESR_FR)
00427    {
00428       //Clear FR interrupt flag
00429       EDMAC.EESR.LONG = EDMAC_EESR_FR;
00430 
00431       //Process all pending packets
00432       do
00433       {
00434          //Read incoming packet
00435          error = rx63nEthReceivePacket(interface);
00436 
00437          //No more data in the receive buffer?
00438       } while(error != ERROR_BUFFER_EMPTY);
00439    }
00440 
00441    //Re-enable EDMAC interrupts
00442    EDMAC.EESIPR.BIT.TWBIP = 1;
00443    EDMAC.EESIPR.BIT.FRIP = 1;
00444 }
00445 
00446 
00447 /**
00448  * @brief Send a packet
00449  * @param[in] interface Underlying network interface
00450  * @param[in] buffer Multi-part buffer containing the data to send
00451  * @param[in] offset Offset to the first data byte
00452  * @return Error code
00453  **/
00454 
00455 error_t rx63nEthSendPacket(NetInterface *interface,
00456    const NetBuffer *buffer, size_t offset)
00457 {
00458    //Retrieve the length of the packet
00459    size_t length = netBufferGetLength(buffer) - offset;
00460 
00461    //Check the frame length
00462    if(length > RX63N_ETH_TX_BUFFER_SIZE)
00463    {
00464       //The transmitter can accept another packet
00465       osSetEvent(&interface->nicTxEvent);
00466       //Report an error
00467       return ERROR_INVALID_LENGTH;
00468    }
00469 
00470    //Make sure the current buffer is available for writing
00471    if(txDmaDesc[txIndex].td0 & EDMAC_TD0_TACT)
00472       return ERROR_FAILURE;
00473 
00474    //Copy user data to the transmit buffer
00475    netBufferRead(txBuffer[txIndex], buffer, offset, length);
00476 
00477    //Write the number of bytes to send
00478    txDmaDesc[txIndex].td1 = (length << 16) & EDMAC_TD1_TBL;
00479 
00480    //Check current index
00481    if(txIndex < (RX63N_ETH_TX_BUFFER_COUNT - 1))
00482    {
00483       //Give the ownership of the descriptor to the DMA engine
00484       txDmaDesc[txIndex].td0 = EDMAC_TD0_TACT | EDMAC_TD0_TFP_SOF |
00485          EDMAC_TD0_TFP_EOF | EDMAC_TD0_TWBI;
00486 
00487       //Point to the next descriptor
00488       txIndex++;
00489    }
00490    else
00491    {
00492       //Give the ownership of the descriptor to the DMA engine
00493       txDmaDesc[txIndex].td0 = EDMAC_TD0_TACT | EDMAC_TD0_TDLE |
00494          EDMAC_TD0_TFP_SOF | EDMAC_TD0_TFP_EOF | EDMAC_TD0_TWBI;
00495 
00496       //Wrap around
00497       txIndex = 0;
00498    }
00499 
00500    //Instruct the DMA to poll the transmit descriptor list
00501    EDMAC.EDTRR.BIT.TR = 1;
00502 
00503    //Check whether the next buffer is available for writing
00504    if(!(txDmaDesc[txIndex].td0 & EDMAC_TD0_TACT))
00505    {
00506       //The transmitter can accept another packet
00507       osSetEvent(&interface->nicTxEvent);
00508    }
00509 
00510    //Successful write operation
00511    return NO_ERROR;
00512 }
00513 
00514 
00515 /**
00516  * @brief Receive a packet
00517  * @param[in] interface Underlying network interface
00518  * @return Error code
00519  **/
00520 
00521 error_t rx63nEthReceivePacket(NetInterface *interface)
00522 {
00523    error_t error;
00524    size_t n;
00525 
00526    //The current buffer is available for reading?
00527    if(!(rxDmaDesc[rxIndex].rd0 & EDMAC_RD0_RACT))
00528    {
00529       //SOF and EOF flags should be set
00530       if((rxDmaDesc[rxIndex].rd0 & EDMAC_RD0_RFP_SOF) &&
00531          (rxDmaDesc[rxIndex].rd0 & EDMAC_RD0_RFP_EOF))
00532       {
00533          //Make sure no error occurred
00534          if(!(rxDmaDesc[rxIndex].rd0 & (EDMAC_RD0_RFS_MASK & ~EDMAC_RD0_RFS_RMAF)))
00535          {
00536             //Retrieve the length of the frame
00537             n = rxDmaDesc[rxIndex].rd1 & EDMAC_RD1_RFL;
00538             //Limit the number of data to read
00539             n = MIN(n, RX63N_ETH_RX_BUFFER_SIZE);
00540 
00541             //Pass the packet to the upper layer
00542             nicProcessPacket(interface, rxBuffer[rxIndex], n);
00543 
00544             //Valid packet received
00545             error = NO_ERROR;
00546          }
00547          else
00548          {
00549             //The received packet contains an error
00550             error = ERROR_INVALID_PACKET;
00551          }
00552       }
00553       else
00554       {
00555          //The packet is not valid
00556          error = ERROR_INVALID_PACKET;
00557       }
00558 
00559       //Check current index
00560       if(rxIndex < (RX63N_ETH_RX_BUFFER_COUNT - 1))
00561       {
00562          //Give the ownership of the descriptor back to the DMA
00563          rxDmaDesc[rxIndex].rd0 = EDMAC_RD0_RACT;
00564          //Point to the next descriptor
00565          rxIndex++;
00566       }
00567       else
00568       {
00569          //Give the ownership of the descriptor back to the DMA
00570          rxDmaDesc[rxIndex].rd0 = EDMAC_RD0_RACT | EDMAC_RD0_RDLE;
00571          //Wrap around
00572          rxIndex = 0;
00573       }
00574 
00575       //Instruct the DMA to poll the receive descriptor list
00576       EDMAC.EDRRR.BIT.RR = 1;
00577    }
00578    else
00579    {
00580       //No more data in the receive buffer
00581       error = ERROR_BUFFER_EMPTY;
00582    }
00583 
00584    //Return status code
00585    return error;
00586 }
00587 
00588 
00589 /**
00590  * @brief Configure multicast MAC address filtering
00591  * @param[in] interface Underlying network interface
00592  * @return Error code
00593  **/
00594 
00595 error_t rx63nEthSetMulticastFilter(NetInterface *interface)
00596 {
00597    uint_t i;
00598    bool_t acceptMulticast;
00599 
00600    //This flag will be set if multicast addresses should be accepted
00601    acceptMulticast = FALSE;
00602 
00603    //The MAC filter table contains the multicast MAC addresses
00604    //to accept when receiving an Ethernet frame
00605    for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++)
00606    {
00607       //Valid entry?
00608       if(interface->macMulticastFilter[i].refCount > 0)
00609       {
00610          //Accept multicast addresses
00611          acceptMulticast = TRUE;
00612          //We are done
00613          break;
00614       }
00615    }
00616 
00617    //Enable the reception of multicast frames if necessary
00618    if(acceptMulticast)
00619       EDMAC.EESR.BIT.RMAF = 1;
00620    else
00621       EDMAC.EESR.BIT.RMAF = 0;
00622 
00623    //Successful processing
00624    return NO_ERROR;
00625 }
00626 
00627 
00628 /**
00629  * @brief Adjust MAC configuration parameters for proper operation
00630  * @param[in] interface Underlying network interface
00631  * @return Error code
00632  **/
00633 
00634 error_t rx63nEthUpdateMacConfig(NetInterface *interface)
00635 {
00636    //10BASE-T or 100BASE-TX operation mode?
00637    if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
00638       ETHERC.ECMR.BIT.RTM = 1;
00639    else
00640       ETHERC.ECMR.BIT.RTM = 0;
00641 
00642    //Half-duplex or full-duplex mode?
00643    if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
00644       ETHERC.ECMR.BIT.DM = 1;
00645    else
00646       ETHERC.ECMR.BIT.DM = 0;
00647 
00648    //Successful processing
00649    return NO_ERROR;
00650 }
00651 
00652 
00653 /**
00654  * @brief Write PHY register
00655  * @param[in] phyAddr PHY address
00656  * @param[in] regAddr Register address
00657  * @param[in] data Register value
00658  **/
00659 
00660 void rx63nEthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data)
00661 {
00662    //Synchronization pattern
00663    rx63nEthWriteSmi(SMI_SYNC, 32);
00664    //Start of frame
00665    rx63nEthWriteSmi(SMI_START, 2);
00666    //Set up a write operation
00667    rx63nEthWriteSmi(SMI_WRITE, 2);
00668    //Write PHY address
00669    rx63nEthWriteSmi(phyAddr, 5);
00670    //Write register address
00671    rx63nEthWriteSmi(regAddr, 5);
00672    //Turnaround
00673    rx63nEthWriteSmi(SMI_TA, 2);
00674    //Write register value
00675    rx63nEthWriteSmi(data, 16);
00676    //Release MDIO
00677    rx63nEthReadSmi(1);
00678 }
00679 
00680 
00681 /**
00682  * @brief Read PHY register
00683  * @param[in] phyAddr PHY address
00684  * @param[in] regAddr Register address
00685  * @return Register value
00686  **/
00687 
00688 uint16_t rx63nEthReadPhyReg(uint8_t phyAddr, uint8_t regAddr)
00689 {
00690    uint16_t data;
00691 
00692    //Synchronization pattern
00693    rx63nEthWriteSmi(SMI_SYNC, 32);
00694    //Start of frame
00695    rx63nEthWriteSmi(SMI_START, 2);
00696    //Set up a read operation
00697    rx63nEthWriteSmi(SMI_READ, 2);
00698    //Write PHY address
00699    rx63nEthWriteSmi(phyAddr, 5);
00700    //Write register address
00701    rx63nEthWriteSmi(regAddr, 5);
00702    //Turnaround to avoid contention
00703    rx63nEthReadSmi(1);
00704    //Read register value
00705    data = rx63nEthReadSmi(16);
00706    //Force the PHY to release the MDIO pin
00707    rx63nEthReadSmi(1);
00708 
00709    //Return PHY register contents
00710    return data;
00711 }
00712 
00713 
00714 /**
00715  * @brief SMI write operation
00716  * @param[in] data Raw data to be written
00717  * @param[in] length Number of bits to be written
00718  **/
00719 
00720 void rx63nEthWriteSmi(uint32_t data, uint_t length)
00721 {
00722    //Skip the most significant bits since they are meaningless
00723    data <<= 32 - length;
00724 
00725    //Configure MDIO as an output
00726    ETHERC.PIR.BIT.MMD = 1;
00727 
00728    //Write the specified number of bits
00729    while(length--)
00730    {
00731       //Write MDIO
00732       if(data & 0x80000000)
00733          ETHERC.PIR.BIT.MDO = 1;
00734       else
00735          ETHERC.PIR.BIT.MDO = 0;
00736 
00737       //Assert MDC
00738       usleep(1);
00739       ETHERC.PIR.BIT.MDC = 1;
00740       //Deassert MDC
00741       usleep(1);
00742       ETHERC.PIR.BIT.MDC = 0;
00743 
00744       //Rotate data
00745       data <<= 1;
00746    }
00747 }
00748 
00749 
00750 /**
00751  * @brief SMI read operation
00752  * @param[in] length Number of bits to be read
00753  * @return Data resulting from the MDIO read operation
00754  **/
00755 
00756 uint32_t rx63nEthReadSmi(uint_t length)
00757 {
00758    uint32_t data = 0;
00759 
00760    //Configure MDIO as an input
00761    ETHERC.PIR.BIT.MMD = 0;
00762 
00763    //Read the specified number of bits
00764    while(length--)
00765    {
00766       //Rotate data
00767       data <<= 1;
00768 
00769       //Assert MDC
00770       ETHERC.PIR.BIT.MDC = 1;
00771       usleep(1);
00772       //Deassert MDC
00773       ETHERC.PIR.BIT.MDC = 0;
00774       usleep(1);
00775 
00776       //Check MDIO state
00777       if(ETHERC.PIR.BIT.MDI)
00778          data |= 0x00000001;
00779    }
00780 
00781    //Return the received data
00782    return data;
00783 }
00784