Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers m2sxxx_eth.c Source File

m2sxxx_eth.c

Go to the documentation of this file.
00001 /**
00002  * @file m2sxxx_eth.c
00003  * @brief SmartFusion2 (M2Sxxx) 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 "m2sxxx.h"
00034 #include "core/net.h"
00035 #include "drivers/m2sxxx_eth.h"
00036 #include "debug.h"
00037 
00038 //Underlying network interface
00039 static NetInterface *nicDriverInterface;
00040 
00041 //IAR EWARM compiler?
00042 #if defined(__ICCARM__)
00043 
00044 //Transmit buffer
00045 #pragma data_alignment = 4
00046 static uint8_t txBuffer[M2SXXX_ETH_TX_BUFFER_COUNT][M2SXXX_ETH_TX_BUFFER_SIZE];
00047 //Receive buffer
00048 #pragma data_alignment = 4
00049 static uint8_t rxBuffer[M2SXXX_ETH_RX_BUFFER_COUNT][M2SXXX_ETH_RX_BUFFER_SIZE];
00050 //Transmit DMA descriptors
00051 #pragma data_alignment = 4
00052 static M2sxxxTxDmaDesc txDmaDesc[M2SXXX_ETH_TX_BUFFER_COUNT];
00053 //Receive DMA descriptors
00054 #pragma data_alignment = 4
00055 static M2sxxxRxDmaDesc rxDmaDesc[M2SXXX_ETH_RX_BUFFER_COUNT];
00056 
00057 //Keil MDK-ARM or GCC compiler?
00058 #else
00059 
00060 //Transmit buffer
00061 static uint8_t txBuffer[M2SXXX_ETH_TX_BUFFER_COUNT][M2SXXX_ETH_TX_BUFFER_SIZE]
00062    __attribute__((aligned(4)));
00063 //Receive buffer
00064 static uint8_t rxBuffer[M2SXXX_ETH_RX_BUFFER_COUNT][M2SXXX_ETH_RX_BUFFER_SIZE]
00065    __attribute__((aligned(4)));
00066 //Transmit DMA descriptors
00067 static M2sxxxTxDmaDesc txDmaDesc[M2SXXX_ETH_TX_BUFFER_COUNT]
00068    __attribute__((aligned(4)));
00069 //Receive DMA descriptors
00070 static M2sxxxRxDmaDesc rxDmaDesc[M2SXXX_ETH_RX_BUFFER_COUNT]
00071    __attribute__((aligned(4)));
00072 
00073 #endif
00074 
00075 //Pointer to the current TX DMA descriptor
00076 static M2sxxxTxDmaDesc *txCurDmaDesc;
00077 //Pointer to the current RX DMA descriptor
00078 static M2sxxxRxDmaDesc *rxCurDmaDesc;
00079 
00080 
00081 /**
00082  * @brief M2Sxxx Ethernet MAC driver
00083  **/
00084 
00085 const NicDriver m2sxxxEthDriver =
00086 {
00087    NIC_TYPE_ETHERNET,
00088    ETH_MTU,
00089    m2sxxxEthInit,
00090    m2sxxxEthTick,
00091    m2sxxxEthEnableIrq,
00092    m2sxxxEthDisableIrq,
00093    m2sxxxEthEventHandler,
00094    m2sxxxEthSendPacket,
00095    m2sxxxEthSetMulticastFilter,
00096    m2sxxxEthUpdateMacConfig,
00097    m2sxxxEthWritePhyReg,
00098    m2sxxxEthReadPhyReg,
00099    TRUE,
00100    TRUE,
00101    TRUE,
00102    FALSE
00103 };
00104 
00105 
00106 /**
00107  * @brief M2Sxxx Ethernet MAC initialization
00108  * @param[in] interface Underlying network interface
00109  * @return Error code
00110  **/
00111 
00112 error_t m2sxxxEthInit(NetInterface *interface)
00113 {
00114    error_t error;
00115 
00116    //Debug message
00117    TRACE_INFO("Initializing M2Sxxx Ethernet MAC...\r\n");
00118 
00119    //Save underlying network interface
00120    nicDriverInterface = interface;
00121 
00122    //Disable EDAC feature
00123    SYSREG->EDAC_CR &= ~(EDAC_CR_MAC_EDAC_RX_EN | EDAC_CR_MAC_EDAC_TX_EN);
00124 
00125    //Reset the MAC module
00126    MAC->CFG1 = CFG1_SOFT_RESET | CFG1_RESET_RX_MAC_CTRL |
00127       CFG1_RESET_TX_MAC_CTRL | CFG1_RESET_RX_FUNCTION | CFG1_RESET_TX_FUNCTION;
00128 
00129    //Reset the interface module
00130    MAC->INTERFACE_CTRL = INTERFACE_CTRL_RESET;
00131 
00132    //Reset FIFOs
00133    MAC->FIFO_CFG0 = FIFO_CFG0_HSTRSTFT | FIFO_CFG0_HSTRSTST |
00134       FIFO_CFG0_HSTRSTFR | FIFO_CFG0_HSTRSTSR | FIFO_CFG0_HSTRSTWT;
00135 
00136    //Take the MAC module out of reset
00137    MAC->CFG1 = 0;
00138    //Take the interface module out of reset
00139    MAC->INTERFACE_CTRL = 0;
00140    //Take the FIFOs out of reset
00141    MAC->FIFO_CFG0 = 0;
00142 
00143    //Select interface mode (MII, RMII, GMII or TBI)
00144    m2sxxxEthInitGpio(interface);
00145 
00146    //Select the proper divider for the MDC clock
00147    MAC->MII_CONFIG = MII_CONFIG_CLKSEL_DIV28;
00148 
00149    //PHY transceiver initialization
00150    error = interface->phyDriver->init(interface);
00151    //Failed to initialize PHY transceiver?
00152    if(error)
00153       return error;
00154 
00155    //Set the upper 16 bits of the MAC address
00156    MAC->STATION_ADDRESS2 = (interface->macAddr.b[0] << 16) |
00157       (interface->macAddr.b[1] << 24);
00158 
00159    //Set the lower 32 bits of the MAC address
00160    MAC->STATION_ADDRESS1 = interface->macAddr.b[2] |
00161       (interface->macAddr.b[3] << 8) |
00162       (interface->macAddr.b[4] << 16) |
00163       (interface->macAddr.b[5] << 24);
00164 
00165    //Maximum frame length to be accepted
00166    MAC->MAX_FRAME_LENGTH = 1518;
00167 
00168    //Disable flow control
00169    MAC->CFG1 = 0;
00170 
00171    //All short frames will be zero-padded to 60 bytes and a valid CRC is then appended
00172    MAC->CFG2 = CFG2_PREAMBLE_7 | CFG2_INTERFACE_MODE_NIBBLE |
00173       CFG2_LENGTH_FIELD_CHECK | CFG2_PAD_CRC_EN | CFG2_CRC_EN;
00174 
00175    //Enable TX and RX FIFOs
00176    MAC->FIFO_CFG0 = FIFO_CFG0_FTFENREQ | FIFO_CFG0_STFENREQ |
00177       FIFO_CFG0_FRFENREQ | FIFO_CFG0_SRFENREQ | FIFO_CFG0_WTMENREQ;
00178 
00179    //Use default FIFO configuration
00180    MAC->FIFO_CFG1 = FIFO_CFG1_DEFAULT_VALUE;
00181    MAC->FIFO_CFG2 = FIFO_CFG2_DEFAULT_VALUE;
00182    MAC->FIFO_CFG3 = FIFO_CFG3_DEFAULT_VALUE;
00183 
00184    //Drop frames less than 64 bytes
00185    MAC->FIFO_CFG5 = FIFO_CFG5_HSTDRPLT64 | FIFO_CFG5_HSTFLTRFRMDC;
00186 
00187    //Specify the statistics vectors that will be checked
00188    MAC->FIFO_CFG5 &= ~(FIFO_CFG5_TRUNCATED | FIFO_CFG5_RECEPTION_OK |
00189       FIFO_CFG5_INVALID_CRC | FIFO_CFG5_RECEIVE_ERROR);
00190 
00191    //Configure frame filtering
00192    MAC->FIFO_CFG4 = FIFO_CFG4_TRUNCATED |
00193       FIFO_CFG4_INVALID_CRC | FIFO_CFG4_RECEIVE_ERROR;
00194 
00195    //Initialize DMA descriptor lists
00196    m2sxxxEthInitDmaDesc(interface);
00197 
00198    //Enable the desired Ethernet interrupts
00199    MAC->DMA_IRQ_MASK = DMA_IRQ_MASK_RX_PKT_RECEIVED | DMA_IRQ_MASK_TX_PKT_SENT;
00200 
00201    //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority)
00202    NVIC_SetPriorityGrouping(M2SXXX_ETH_IRQ_PRIORITY_GROUPING);
00203 
00204    //Configure Ethernet interrupt priority
00205    NVIC_SetPriority(EthernetMAC_IRQn, NVIC_EncodePriority(M2SXXX_ETH_IRQ_PRIORITY_GROUPING,
00206       M2SXXX_ETH_IRQ_GROUP_PRIORITY, M2SXXX_ETH_IRQ_SUB_PRIORITY));
00207 
00208    //Enable transmission and reception
00209    MAC->CFG1 |= CFG1_TX_EN | CFG1_RX_EN;
00210    //Enable the DMA transfer of received packets
00211    MAC->DMA_RX_CTRL = DMA_RX_CTRL_RX_EN;
00212 
00213    //Accept any packets from the upper layer
00214    osSetEvent(&interface->nicTxEvent);
00215 
00216    //Successful initialization
00217    return NO_ERROR;
00218 }
00219 
00220 
00221 //SF2-STARTER-KIT-ES-2 evaluation board?
00222 #if defined(USE_SF2_STARTER_KIT_ES_2)
00223 
00224 /**
00225  * @brief GPIO configuration
00226  * @param[in] interface Underlying network interface
00227  **/
00228 
00229 void m2sxxxEthInitGpio(NetInterface *interface)
00230 {
00231    //Select MII interface mode
00232    SYSREG->MAC_CR = MAC_CR_ETH_PHY_MODE_MII;
00233 }
00234 
00235 #endif
00236 
00237 
00238 /**
00239  * @brief Initialize DMA descriptor lists
00240  * @param[in] interface Underlying network interface
00241  **/
00242 
00243 void m2sxxxEthInitDmaDesc(NetInterface *interface)
00244 {
00245    uint_t i;
00246 
00247    //Initialize TX DMA descriptor list
00248    for(i = 0; i < M2SXXX_ETH_TX_BUFFER_COUNT; i++)
00249    {
00250       //Transmit buffer address
00251       txDmaDesc[i].addr = (uint32_t) txBuffer[i];
00252       //The descriptor is initially owned by the user
00253       txDmaDesc[i].size = DMA_DESC_EMPTY_FLAG;
00254       //Next descriptor address
00255       txDmaDesc[i].next = (uint32_t) &txDmaDesc[i + 1];
00256    }
00257 
00258    //The last descriptor is chained to the first entry
00259    txDmaDesc[i - 1].next = (uint32_t) &txDmaDesc[0];
00260    //Point to the very first descriptor
00261    txCurDmaDesc = &txDmaDesc[0];
00262 
00263    //Initialize RX DMA descriptor list
00264    for(i = 0; i < M2SXXX_ETH_RX_BUFFER_COUNT; i++)
00265    {
00266       //Receive buffer address
00267       rxDmaDesc[i].addr = (uint32_t) rxBuffer[i];
00268       //The descriptor is initially owned by the DMA
00269       rxDmaDesc[i].size = DMA_DESC_EMPTY_FLAG;
00270       //Next descriptor address
00271       rxDmaDesc[i].next = (uint32_t) &rxDmaDesc[i + 1];
00272    }
00273 
00274    //The last descriptor is chained to the first entry
00275    rxDmaDesc[i - 1].next = (uint32_t) &rxDmaDesc[0];
00276    //Point to the very first descriptor
00277    rxCurDmaDesc = &rxDmaDesc[0];
00278 
00279    //Start location of the TX descriptor list
00280    MAC->DMA_TX_DESC = (uint32_t) txDmaDesc;
00281    //Start location of the RX descriptor list
00282    MAC->DMA_RX_DESC = (uint32_t) rxDmaDesc;
00283 }
00284 
00285 
00286 /**
00287  * @brief M2Sxxx Ethernet MAC timer handler
00288  *
00289  * This routine is periodically called by the TCP/IP stack to
00290  * handle periodic operations such as polling the link state
00291  *
00292  * @param[in] interface Underlying network interface
00293  **/
00294 
00295 void m2sxxxEthTick(NetInterface *interface)
00296 {
00297    //Handle periodic operations
00298    interface->phyDriver->tick(interface);
00299 }
00300 
00301 
00302 /**
00303  * @brief Enable interrupts
00304  * @param[in] interface Underlying network interface
00305  **/
00306 
00307 void m2sxxxEthEnableIrq(NetInterface *interface)
00308 {
00309    //Enable Ethernet MAC interrupts
00310    NVIC_EnableIRQ(EthernetMAC_IRQn);
00311    //Enable Ethernet PHY interrupts
00312    interface->phyDriver->enableIrq(interface);
00313 }
00314 
00315 
00316 /**
00317  * @brief Disable interrupts
00318  * @param[in] interface Underlying network interface
00319  **/
00320 
00321 void m2sxxxEthDisableIrq(NetInterface *interface)
00322 {
00323    //Disable Ethernet MAC interrupts
00324    NVIC_DisableIRQ(EthernetMAC_IRQn);
00325    //Disable Ethernet PHY interrupts
00326    interface->phyDriver->disableIrq(interface);
00327 }
00328 
00329 
00330 /**
00331  * @brief M2Sxxx Ethernet MAC interrupt service routine
00332  **/
00333 
00334 void EthernetMAC_IRQHandler(void)
00335 {
00336    bool_t flag;
00337    uint32_t status;
00338 
00339    //Enter interrupt service routine
00340    osEnterIsr();
00341 
00342    //This flag will be set if a higher priority task must be woken
00343    flag = FALSE;
00344 
00345    //Read interrupt status register
00346    status = MAC->DMA_IRQ;
00347 
00348    //A packet has been transmitted?
00349    if(status & DMA_IRQ_TX_PKT_SENT)
00350    {
00351       //Clear TX interrupt flag
00352       MAC->DMA_TX_STATUS = DMA_TX_STATUS_TX_PKT_SENT;
00353 
00354       //Check whether the TX buffer is available for writing
00355       if(txCurDmaDesc->size & DMA_DESC_EMPTY_FLAG)
00356       {
00357          //Notify the TCP/IP stack that the transmitter is ready to send
00358          flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
00359       }
00360    }
00361 
00362    //A packet has been received?
00363    if(status & DMA_IRQ_RX_PKT_RECEIVED)
00364    {
00365       //Disable RX interrupt
00366       MAC->DMA_IRQ_MASK &= ~DMA_IRQ_MASK_RX_PKT_RECEIVED;
00367 
00368       //Set event flag
00369       nicDriverInterface->nicEvent = TRUE;
00370       //Notify the TCP/IP stack of the event
00371       flag |= osSetEventFromIsr(&netEvent);
00372    }
00373 
00374    //Leave interrupt service routine
00375    osExitIsr(flag);
00376 }
00377 
00378 
00379 /**
00380  * @brief M2Sxxx Ethernet MAC event handler
00381  * @param[in] interface Underlying network interface
00382  **/
00383 
00384 void m2sxxxEthEventHandler(NetInterface *interface)
00385 {
00386    //Packet received?
00387    if(MAC->DMA_RX_STATUS & DMA_RX_STATUS_RX_PKT_RECEIVED)
00388    {
00389       //Process all the pending packets
00390       while(MAC->DMA_RX_STATUS & DMA_RX_STATUS_RX_PKT_RECEIVED)
00391       {
00392          //Clear RX interrupt flag
00393          MAC->DMA_RX_STATUS = DMA_RX_STATUS_RX_PKT_RECEIVED;
00394          //Read incoming packet
00395          m2sxxxEthReceivePacket(interface);
00396       }
00397    }
00398 
00399    //Re-enable Ethernet interrupts
00400    MAC->DMA_IRQ_MASK = DMA_IRQ_MASK_RX_PKT_RECEIVED | DMA_IRQ_MASK_TX_PKT_SENT;
00401 }
00402 
00403 
00404 /**
00405  * @brief Send a packet
00406  * @param[in] interface Underlying network interface
00407  * @param[in] buffer Multi-part buffer containing the data to send
00408  * @param[in] offset Offset to the first data byte
00409  * @return Error code
00410  **/
00411 
00412 error_t m2sxxxEthSendPacket(NetInterface *interface,
00413    const NetBuffer *buffer, size_t offset)
00414 {
00415    size_t length;
00416 
00417    //Retrieve the length of the packet
00418    length = netBufferGetLength(buffer) - offset;
00419 
00420    //Check the frame length
00421    if(length > M2SXXX_ETH_TX_BUFFER_SIZE)
00422    {
00423       //The transmitter can accept another packet
00424       osSetEvent(&interface->nicTxEvent);
00425       //Report an error
00426       return ERROR_INVALID_LENGTH;
00427    }
00428 
00429    //Make sure the current buffer is available for writing
00430    if(!(txCurDmaDesc->size & DMA_DESC_EMPTY_FLAG))
00431       return ERROR_FAILURE;
00432 
00433    //Copy user data to the transmit buffer
00434    netBufferRead((uint8_t *) txCurDmaDesc->addr, buffer, offset, length);
00435 
00436    //Set the packet length and give the ownership of the descriptor to the DMA
00437    txCurDmaDesc->size = length & DMA_DESC_SIZE_MASK;
00438 
00439    //Check whether DMA transfers are suspended
00440    if(!(MAC->DMA_TX_CTRL & DMA_TX_CTRL_TX_EN))
00441    {
00442       //Set the start position in the ring buffer
00443       MAC->DMA_TX_DESC = (uint32_t) txCurDmaDesc;
00444    }
00445 
00446    //Instruct the DMA controller to transfer the packet
00447    MAC->DMA_TX_CTRL = DMA_TX_CTRL_TX_EN;
00448 
00449    //Point to the next descriptor in the list
00450    txCurDmaDesc = (M2sxxxTxDmaDesc *) txCurDmaDesc->next;
00451 
00452    //Check whether the next buffer is available for writing
00453    if(txCurDmaDesc->size & DMA_DESC_EMPTY_FLAG)
00454    {
00455       //The transmitter can accept another packet
00456       osSetEvent(&interface->nicTxEvent);
00457    }
00458 
00459    //Data successfully written
00460    return NO_ERROR;
00461 }
00462 
00463 
00464 /**
00465  * @brief Receive a packet
00466  * @param[in] interface Underlying network interface
00467  * @return Error code
00468  **/
00469 
00470 error_t m2sxxxEthReceivePacket(NetInterface *interface)
00471 {
00472    error_t error;
00473    size_t n;
00474 
00475    //The current buffer is available for reading?
00476    if(!(rxCurDmaDesc->size & DMA_DESC_EMPTY_FLAG))
00477    {
00478       //Retrieve the length of the frame
00479       n = rxCurDmaDesc->size & DMA_DESC_SIZE_MASK;
00480       //Limit the number of data to read
00481       n = MIN(n, M2SXXX_ETH_RX_BUFFER_SIZE);
00482 
00483       //Pass the packet to the upper layer
00484       nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->addr, n);
00485 
00486       //Give the ownership of the descriptor back to the DMA
00487       rxCurDmaDesc->size = DMA_DESC_EMPTY_FLAG;
00488 
00489       //Check whether DMA transfers are suspended
00490       if(!(MAC->DMA_RX_CTRL & DMA_RX_CTRL_RX_EN))
00491       {
00492          //Set the start position in the ring buffer
00493          MAC->DMA_RX_DESC = (uint32_t) rxCurDmaDesc;
00494       }
00495 
00496       //Enable the DMA transfer of received packets
00497       MAC->DMA_RX_CTRL = DMA_RX_CTRL_RX_EN;
00498       //Point to the next descriptor in the list
00499       rxCurDmaDesc = (M2sxxxRxDmaDesc *) rxCurDmaDesc->next;
00500 
00501       //Valid packet received
00502       error = NO_ERROR;
00503    }
00504    else
00505    {
00506       //Check whether DMA transfers are suspended
00507       if(!(MAC->DMA_RX_CTRL & DMA_RX_CTRL_RX_EN))
00508       {
00509          //Set the start position in the ring buffer
00510          MAC->DMA_RX_DESC = (uint32_t) rxCurDmaDesc;
00511       }
00512 
00513       //Enable the DMA transfer of received packets
00514       MAC->DMA_RX_CTRL = DMA_RX_CTRL_RX_EN;
00515 
00516       //No more data in the receive buffer
00517       error = ERROR_BUFFER_EMPTY;
00518    }
00519 
00520    //Return status code
00521    return error;
00522 }
00523 
00524 
00525 /**
00526  * @brief Configure multicast MAC address filtering
00527  * @param[in] interface Underlying network interface
00528  * @return Error code
00529  **/
00530 
00531 error_t m2sxxxEthSetMulticastFilter(NetInterface *interface)
00532 {
00533    //SmartFusion2 Ethernet MAC does not implement any hash table
00534    return NO_ERROR;
00535 }
00536 
00537 
00538 /**
00539  * @brief Adjust MAC configuration parameters for proper operation
00540  * @param[in] interface Underlying network interface
00541  * @return Error code
00542  **/
00543 
00544 error_t m2sxxxEthUpdateMacConfig(NetInterface *interface)
00545 {
00546    uint32_t temp;
00547 
00548    //10BASE-T or 100BASE-TX operation mode?
00549    if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
00550    {
00551       //The link operates at 100 Mbps
00552       temp = SYSREG->MAC_CR & ~MAC_CR_ETH_LINE_SPEED;
00553       SYSREG->MAC_CR = temp | MAC_CR_ETH_LINE_SPEED_100MBPS;
00554 
00555       //Configure the RMII module with the current operating speed
00556       MAC->INTERFACE_CTRL |= INTERFACE_CTRL_SPEED;
00557 
00558       //Use nibble mode
00559       temp = MAC->CFG2 & ~CFG2_INTERFACE_MODE;
00560       MAC->CFG2 = temp | CFG2_INTERFACE_MODE_NIBBLE;
00561    }
00562    else
00563    {
00564       //The link operates at 10 Mbps
00565       temp = SYSREG->MAC_CR & ~MAC_CR_ETH_LINE_SPEED;
00566       SYSREG->MAC_CR = temp | MAC_CR_ETH_LINE_SPEED_10MBPS;
00567 
00568       //Configure the RMII module with the current operating speed
00569       MAC->INTERFACE_CTRL &= ~INTERFACE_CTRL_SPEED;
00570 
00571       //Use nibble mode
00572       temp = MAC->CFG2 & ~CFG2_INTERFACE_MODE;
00573       MAC->CFG2 = temp | CFG2_INTERFACE_MODE_NIBBLE;
00574    }
00575 
00576    //Half-duplex or full-duplex mode?
00577    if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
00578    {
00579       //Configure MAC to operate in full-duplex mode
00580       MAC->CFG2 |= CFG2_FULL_DUPLEX;
00581       MAC->FIFO_CFG5 &= ~FIFO_CFG5_CFGHDPLX;
00582    }
00583    else
00584    {
00585       //Configure MAC to operate in half-duplex mode
00586       MAC->CFG2 &= ~CFG2_FULL_DUPLEX;
00587       MAC->FIFO_CFG5 |= FIFO_CFG5_CFGHDPLX;
00588    }
00589 
00590    //Successful processing
00591    return NO_ERROR;
00592 }
00593 
00594 
00595 /**
00596  * @brief Write PHY register
00597  * @param[in] phyAddr PHY address
00598  * @param[in] regAddr Register address
00599  * @param[in] data Register value
00600  **/
00601 
00602 void m2sxxxEthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data)
00603 {
00604    //Set PHY address and register address
00605    MAC->MII_ADDRESS = (phyAddr << MII_ADDRESS_PHY_ADDR_POS) | regAddr;
00606    //Start a write operation
00607    MAC->MII_CTRL = data;
00608 
00609    //Wait for the write to complete
00610    while(MAC->MII_INDICATORS & MII_INDICATORS_BUSY);
00611 }
00612 
00613 
00614 /**
00615  * @brief Read PHY register
00616  * @param[in] phyAddr PHY address
00617  * @param[in] regAddr Register address
00618  * @return Register value
00619  **/
00620 
00621 uint16_t m2sxxxEthReadPhyReg(uint8_t phyAddr, uint8_t regAddr)
00622 {
00623    //Set PHY address and register address
00624    MAC->MII_ADDRESS = (phyAddr << MII_ADDRESS_PHY_ADDR_POS) | regAddr;
00625    //Start a read operation
00626    MAC->MII_COMMAND = MII_COMMAND_READ;
00627 
00628    //Wait for the read to complete
00629    while(MAC->MII_INDICATORS & MII_INDICATORS_BUSY);
00630 
00631    //Clear command register
00632    MAC->MII_COMMAND = 0;
00633    //Return PHY register contents
00634    return MAC->MII_STATUS;
00635 }
00636