This is Webservice SDK for mbed. LPCXpresso1769/LPC1768/FRDM-K64F/LPC4088

Dependents:   MbedFileServer_1768MiniDK2 RedWireBridge IssueDebug_gcc MiMicRemoteMCU-for-Mbed ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers fsl_enet_driver.c Source File

fsl_enet_driver.c

00001 /*
00002 * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
00003 * All rights reserved.
00004 *
00005 * Redistribution and use in source and binary forms, with or without modification,
00006 * are permitted provided that the following conditions are met:
00007 *
00008 * o Redistributions of source code must retain the above copyright notice, this list
00009 *   of conditions and the following disclaimer.
00010 *
00011 * o Redistributions in binary form must reproduce the above copyright notice, this
00012 *   list of conditions and the following disclaimer in the documentation and/or
00013 *   other materials provided with the distribution.
00014 *
00015 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
00016 *   contributors may be used to endorse or promote products derived from this
00017 *   software without specific prior written permission.
00018 *
00019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
00023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 */
00030 
00031 /* Modified by mbed for the lwIP port */
00032 #include "NyLPC_config.h"
00033 #if NyLPC_MCU==NyLPC_MCU_K64F
00034 #include "fsl_enet_driver.h"
00035 #include "fsl_enet_hal.h"
00036 #include "fsl_clock_manager.h"
00037 #include "fsl_interrupt_manager.h"
00038 #include <string.h>
00039 
00040 //#include "sys_arch.h"
00041 
00042 /*******************************************************************************
00043  * Variables
00044  ******************************************************************************/
00045 /*! @brief Define ENET's IRQ list */
00046 
00047 void *enetIfHandle;
00048 
00049 /*! @brief Define MAC driver API structure and for application of stack adaptor layer*/
00050 const enet_mac_api_t g_enetMacApi = 
00051 {
00052     enet_mac_init,
00053     NULL, // enet_mac_deinit,
00054     NULL, // enet_mac_send,
00055 #if !ENET_RECEIVE_ALL_INTERRUPT
00056     NULL, // enet_mac_receive,
00057 #endif
00058     enet_mii_read,
00059     enet_mii_write,
00060     NULL, // enet_mac_add_multicast_group,
00061     NULL, //enet_mac_leave_multicast_group,
00062 };
00063 /*******************************************************************************
00064  * Code
00065  ******************************************************************************/
00066 
00067 // NOTE: we need these functions to be non-blocking fpr the PHY task, hence the
00068 // osDelay() below
00069 
00070 /*FUNCTION****************************************************************
00071  *
00072  * Function Name: enet_mii_read
00073  * Return Value: The execution status.
00074  * Description: Read function.
00075  * This interface read data over the (R)MII bus from the specified PHY register,
00076  * This function is called by all PHY interfaces.
00077  *END*********************************************************************/
00078 uint32_t enet_mii_read(uint32_t instance, uint32_t phyAddr, uint32_t phyReg, uint32_t *dataPtr)
00079 {
00080     uint32_t  counter;
00081     
00082     /* Check the input parameters*/
00083     if (!dataPtr)
00084     {
00085         return kStatus_ENET_InvalidInput;
00086     }
00087 
00088     /* Check if the mii is enabled*/
00089     if (!enet_hal_is_mii_enabled(instance))
00090     {
00091         return kStatus_ENET_Miiuninitialized;
00092     }
00093 
00094     /* Clear the MII interrupt event*/
00095     enet_hal_clear_interrupt(instance, kEnetMiiInterrupt);
00096 
00097     /* Read command operation*/
00098     enet_hal_set_mii_command(instance, phyAddr, phyReg, kEnetReadValidFrame, 0);
00099 
00100     /* Poll for MII complete*/
00101     for (counter = 0; counter < kEnetMaxTimeout; counter++)
00102     {
00103         if (enet_hal_get_interrupt_status(instance, kEnetMiiInterrupt))
00104         {
00105             break;
00106         }   
00107         osDelay(1);
00108     }
00109 
00110     /* Check for timeout*/
00111     if (counter == kEnetMaxTimeout)
00112     {
00113         return kStatus_ENET_TimeOut;
00114     }
00115 
00116     /* Get data from mii register*/
00117     *dataPtr = enet_hal_get_mii_data(instance);
00118 
00119     /* Clear MII interrupt event*/
00120     enet_hal_clear_interrupt(instance, kEnetMiiInterrupt);
00121     
00122     return kStatus_ENET_Success;
00123 }
00124 
00125 /*FUNCTION****************************************************************
00126  *
00127  * Function Name: enet_mii_write
00128  * Return Value: The execution status.
00129  * Description: Write function.
00130  * This interface write data over the (R)MII bus to the specified PHY register.   
00131  * This function is called by all PHY interfaces.
00132  *END*********************************************************************/
00133 uint32_t enet_mii_write(uint32_t instance, uint32_t phyAddr, uint32_t phyReg, uint32_t data)
00134 {
00135     uint32_t counter;
00136 
00137     /* Check if the mii is enabled*/
00138     if (!enet_hal_is_mii_enabled(instance))
00139     {
00140         return kStatus_ENET_Miiuninitialized;
00141     }
00142 
00143     /* Clear the MII interrupt event*/
00144     enet_hal_clear_interrupt(instance, kEnetMiiInterrupt);
00145 
00146     /* Read command operation*/
00147     enet_hal_set_mii_command(instance, phyAddr, phyReg, kEnetWriteValidFrame, data);
00148 
00149     /* Poll for MII complete*/
00150     for (counter = 0; counter < kEnetMaxTimeout; counter++)
00151     {
00152         if (enet_hal_get_interrupt_status(instance, kEnetMiiInterrupt))
00153         {
00154             break;
00155         }       
00156         osDelay(1);
00157     }
00158 
00159     /* Check for timeout*/
00160     if (counter == kEnetMaxTimeout)
00161     {
00162         return kStatus_ENET_TimeOut;
00163     }
00164 
00165     /* Clear MII intrrupt event*/
00166     enet_hal_clear_interrupt(instance, kEnetMiiInterrupt);
00167     
00168     return kStatus_ENET_Success;
00169 }
00170 /*FUNCTION****************************************************************
00171  *
00172  * Function Name: enet_mac_mii_init
00173  * Return Value: The execution status.
00174  * Description:Initialize the ENET Mac mii(mdc/mdio)interface.
00175  *END*********************************************************************/
00176 uint32_t enet_mac_mii_init(enet_dev_if_t * enetIfPtr)
00177 {
00178     uint32_t frequency;
00179     
00180     /* Check the input parameters*/
00181     if (enetIfPtr == NULL)
00182     {
00183         return kStatus_ENET_InvalidInput;
00184     }   
00185 
00186     /* Configure mii speed*/
00187     clock_manager_get_frequency(kSystemClock, &frequency);
00188     enet_hal_config_mii(enetIfPtr->deviceNumber, (frequency/(2 * enetIfPtr->macCfgPtr->miiClock) + 1), 
00189                  kEnetMdioHoldOneClkCycle, false);
00190 
00191     return kStatus_ENET_Success;
00192 }
00193 
00194 /*FUNCTION****************************************************************
00195  *
00196  * Function Name: enet_mac_rxbd_init
00197  * Return Value: The execution status.
00198  * Description:Initialize the ENET receive buffer descriptors.
00199  * Note: If you do receive on receive interrupt handler the receive 
00200  * data buffer number can be the same as the receive descriptor numbers. 
00201  * But if you are polling receive frames please make sure the receive data 
00202  * buffers are more than buffer descriptors to guarantee a good performance.
00203  *END*********************************************************************/
00204 uint32_t enet_mac_rxbd_init(enet_dev_if_t * enetIfPtr, enet_rxbd_config_t *rxbdCfg)
00205 {
00206     /* Check the input parameters*/
00207     if ((!enetIfPtr) || (!rxbdCfg))
00208     {
00209         return kStatus_ENET_InvalidInput;
00210     }
00211 
00212     enetIfPtr->macContextPtr->bufferdescSize = enet_hal_get_bd_size();
00213 
00214     /* Initialize the bd status*/
00215     enetIfPtr->macContextPtr->isRxFull = false;
00216         
00217     /* Initialize receive bd base address and current address*/
00218     enetIfPtr->macContextPtr->rxBdBasePtr = rxbdCfg->rxBdPtrAlign;
00219     enetIfPtr->macContextPtr->rxBdCurPtr = enetIfPtr->macContextPtr->rxBdBasePtr;
00220     enetIfPtr->macContextPtr->rxBdDirtyPtr = enetIfPtr->macContextPtr->rxBdBasePtr; 
00221     enet_hal_set_rxbd_address(enetIfPtr->deviceNumber, (uint32_t)(enetIfPtr->macContextPtr->rxBdBasePtr));
00222     
00223     return kStatus_ENET_Success;
00224 }
00225 
00226 /*FUNCTION****************************************************************
00227  *
00228  * Function Name: enet_mac_txbd_init
00229  * Return Value: The execution status.
00230  * Description:Initialize the ENET transmit buffer descriptors.
00231  * This function prepare all of the transmit buffer descriptors.
00232  *END*********************************************************************/
00233 uint32_t enet_mac_txbd_init(enet_dev_if_t * enetIfPtr, enet_txbd_config_t *txbdCfg)
00234 {
00235     /* Check the input parameters*/
00236     if ((!enetIfPtr) || (!txbdCfg))
00237     {
00238         return kStatus_ENET_InvalidInput;
00239     }
00240 
00241     /* Initialize the bd status*/
00242     enetIfPtr->macContextPtr->isTxFull = false;
00243 
00244     /* Initialize transmit bd base address and current address*/
00245     enetIfPtr->macContextPtr->txBdBasePtr = txbdCfg->txBdPtrAlign;
00246     enetIfPtr->macContextPtr->txBdCurPtr = enetIfPtr->macContextPtr->txBdBasePtr;
00247     enetIfPtr->macContextPtr->txBdDirtyPtr = enetIfPtr->macContextPtr->txBdBasePtr;
00248     enet_hal_set_txbd_address(enetIfPtr->deviceNumber, (uint32_t)(enetIfPtr->macContextPtr->txBdBasePtr));
00249     return kStatus_ENET_Success;
00250 }
00251 
00252 /*FUNCTION****************************************************************
00253  *
00254  * Function Name: enet_mac_configure_fifo_accel
00255  * Return Value: The execution status.
00256  * Description: Configure the ENET FIFO and Accelerator.
00257  *END*********************************************************************/
00258 uint32_t enet_mac_configure_fifo_accel(enet_dev_if_t * enetIfPtr)
00259 {
00260     enet_config_rx_fifo_t rxFifo;
00261     enet_config_tx_fifo_t txFifo;
00262     
00263     /* Check the input parameters*/
00264     if (!enetIfPtr)
00265     {
00266         return kStatus_ENET_InvalidInput;
00267     }
00268         
00269         /* Initialize values that will not be initialized later on */
00270     rxFifo.rxEmpty = 0;
00271     rxFifo.rxFull = 0;
00272     txFifo.isStoreForwardEnabled = 0;
00273     txFifo.txFifoWrite = 0;
00274     txFifo.txEmpty = 0;
00275 
00276     /* Configure tx/rx accelerator*/
00277     if (enetIfPtr->macCfgPtr->isRxAccelEnabled)
00278     {
00279         enet_hal_config_rx_accelerator(enetIfPtr->deviceNumber, 
00280            (enet_config_rx_accelerator_t *)&(enetIfPtr->macCfgPtr->rxAcceler));
00281         if ((enetIfPtr->macCfgPtr->rxAcceler.isIpcheckEnabled) || (enetIfPtr->macCfgPtr->rxAcceler.isProtocolCheckEnabled))
00282         {
00283             rxFifo.rxFull = 0;
00284         }
00285     }
00286     if (enetIfPtr->macCfgPtr->isTxAccelEnabled)
00287     {
00288         enet_hal_config_tx_accelerator(enetIfPtr->deviceNumber, 
00289             (enet_config_tx_accelerator_t *)&(enetIfPtr->macCfgPtr->txAcceler));
00290         if ((enetIfPtr->macCfgPtr->txAcceler.isIpCheckEnabled) || (enetIfPtr->macCfgPtr->txAcceler.isProtocolCheckEnabled))
00291         {
00292             txFifo.isStoreForwardEnabled = 1;
00293         }
00294     }
00295     if (enetIfPtr->macCfgPtr->isStoreAndFwEnabled)
00296     {
00297           rxFifo.rxFull = 0;
00298           txFifo.isStoreForwardEnabled = 1;
00299     }
00300 
00301 
00302     /* Set TFWR value if STRFWD is not being used  */       
00303     if (txFifo.isStoreForwardEnabled == 1)
00304           txFifo.txFifoWrite = 0;
00305     else
00306           /* TFWR value is a trade-off between transmit latency and risk of transmit FIFO underrun due to contention for the system bus
00307               TFWR = 15 means transmission will begin once 960 bytes has been written to the Tx FIFO (for frames larger than 960 bytes)
00308           See Section 45.4.18 - Transmit FIFO Watermark Register of the K64F Reference Manual for details       */
00309           txFifo.txFifoWrite = 15;
00310         
00311     /* Configure tx/rx FIFO with default value*/
00312     rxFifo.rxAlmostEmpty = 4;
00313     rxFifo.rxAlmostFull = 4;
00314     txFifo.txAlmostEmpty = 4;
00315     txFifo.txAlmostFull = 8;
00316     enet_hal_config_rx_fifo(enetIfPtr->deviceNumber, &rxFifo);
00317     enet_hal_config_tx_fifo(enetIfPtr->deviceNumber, &txFifo); 
00318 
00319     return kStatus_ENET_Success;
00320 }
00321 
00322 /*FUNCTION****************************************************************
00323  *
00324  * Function Name: enet_mac_configure_controller
00325  * Return Value: The execution status.
00326  * Description: Configure the ENET controller with the basic configuration.
00327  *END*********************************************************************/
00328 uint32_t enet_mac_configure_controller(enet_dev_if_t * enetIfPtr)
00329 {
00330     uint32_t macCtlCfg;
00331 
00332     /* Check the input parameters*/
00333     if (enetIfPtr == NULL)
00334     {
00335         return kStatus_ENET_InvalidInput;
00336     }   
00337 
00338     macCtlCfg = enetIfPtr->macCfgPtr->macCtlConfigure;  
00339     /* Configure rmii/mii interface*/
00340     enet_hal_config_rmii(enetIfPtr->deviceNumber, enetIfPtr->macCfgPtr->rmiiCfgMode, 
00341         enetIfPtr->macCfgPtr->speed, enetIfPtr->macCfgPtr->duplex, false, 
00342         (macCtlCfg & kEnetRxMiiLoopback));
00343      /* Configure receive buffer size*/
00344     if (enetIfPtr->macCfgPtr->isVlanEnabled)
00345     {
00346         enetIfPtr->maxFrameSize = kEnetMaxFrameVlanSize;
00347         enet_hal_set_rx_max_size(enetIfPtr->deviceNumber, 
00348               enetIfPtr->macContextPtr->rxBufferSizeAligned, kEnetMaxFrameVlanSize);
00349     }
00350     else
00351     {   
00352         enetIfPtr->maxFrameSize = kEnetMaxFrameSize;
00353         enet_hal_set_rx_max_size(enetIfPtr->deviceNumber, 
00354               enetIfPtr->macContextPtr->rxBufferSizeAligned, kEnetMaxFrameSize); 
00355     }
00356 
00357     /* Set receive controller promiscuous */
00358     enet_hal_config_promiscuous(enetIfPtr->deviceNumber, macCtlCfg & kEnetRxPromiscuousEnable);
00359     /* Set receive flow control*/
00360     enet_hal_enable_flowcontrol(enetIfPtr->deviceNumber, (macCtlCfg & kEnetRxFlowControlEnable));
00361     /* Set received PAUSE frames are forwarded/terminated*/
00362     enet_hal_enable_pauseforward(enetIfPtr->deviceNumber, (macCtlCfg & kEnetRxPauseFwdEnable));
00363     /* Set receive broadcast frame reject*/
00364     enet_hal_enable_broadcastreject(enetIfPtr->deviceNumber, (macCtlCfg & kEnetRxBcRejectEnable));
00365     /* Set padding is removed from the received frame*/
00366     enet_hal_enable_padremove(enetIfPtr->deviceNumber, (macCtlCfg & kEnetRxPadRemoveEnable));
00367     /* Set the crc of the received frame is stripped from the frame*/
00368     enet_hal_enable_rxcrcforward(enetIfPtr->deviceNumber, (macCtlCfg & kEnetRxCrcFwdEnable));
00369     /* Set receive payload length check*/
00370     enet_hal_enable_payloadcheck(enetIfPtr->deviceNumber, (macCtlCfg & kEnetPayloadlenCheckEnable));
00371     /* Set control sleep mode*/
00372     enet_hal_enable_sleep(enetIfPtr->deviceNumber, (macCtlCfg & kEnetSleepModeEnable));
00373     return kStatus_ENET_Success;
00374 }
00375 
00376 /*FUNCTION****************************************************************
00377  *
00378  * Function Name: enet_mac_init
00379  * Return Value: The execution status.
00380  * Description:Initialize the ENET device with the basic configuration
00381  * When ENET is used, this function need to be called by the NET initialize 
00382  * interface.
00383  *END*********************************************************************/
00384 uint32_t enet_mac_init(enet_dev_if_t * enetIfPtr, enet_rxbd_config_t *rxbdCfg,
00385                             enet_txbd_config_t *txbdCfg)
00386 {   
00387     uint32_t timeOut = 0;
00388     uint32_t devNumber, result = 0; 
00389     
00390     /* Check the input parameters*/
00391     if (enetIfPtr == NULL)
00392     {
00393         return kStatus_ENET_InvalidInput;
00394     }
00395 
00396     /* Get device number and check the parameter*/
00397     devNumber = enetIfPtr->deviceNumber;
00398 
00399     /* Store the global ENET structure for ISR input parameters for instance 0*/
00400     if (!devNumber)
00401     {
00402         enetIfHandle = enetIfPtr;
00403     }
00404 
00405     /* Turn on ENET module clock gate */
00406     clock_manager_set_gate(kClockModuleENET, 0U, true);
00407 
00408     /* Reset ENET mac*/
00409     enet_hal_reset_ethernet(devNumber);
00410     while ((!enet_hal_is_reset_completed(devNumber)) && (timeOut < kEnetMaxTimeout))
00411     {
00412         time_delay(1);
00413         timeOut++;
00414     }
00415 
00416     /* Check out if timeout*/
00417     if (timeOut == kEnetMaxTimeout)
00418     {
00419         return kStatus_ENET_TimeOut;
00420     }
00421     
00422     /* Disable all ENET mac interrupt and Clear all interrupt events*/
00423     enet_hal_config_interrupt(devNumber, kEnetAllInterrupt, false);
00424     enet_hal_clear_interrupt(devNumber, kEnetAllInterrupt);
00425     
00426     /* Program this station's physical address*/
00427     enet_hal_set_mac_address(devNumber, enetIfPtr->macCfgPtr->macAddr);
00428 
00429     /* Clear group and individual hash register*/
00430     enet_hal_set_group_hashtable(devNumber, 0, kEnetSpecialAddressInit);
00431     enet_hal_set_individual_hashtable(devNumber, 0, kEnetSpecialAddressInit);
00432 
00433       /* Configure mac controller*/
00434     result = enet_mac_configure_controller(enetIfPtr);
00435     if(result != kStatus_ENET_Success)
00436     {
00437         return result;
00438     }
00439     /* Clear mib zero counters*/
00440     enet_hal_clear_mib(devNumber, true);
00441 
00442     /* Initialize FIFO and accelerator*/
00443     result = enet_mac_configure_fifo_accel(enetIfPtr);
00444     if(result != kStatus_ENET_Success)
00445     {
00446         return result;
00447     }
00448     /* Initialize receive buffer descriptors*/
00449     result = enet_mac_rxbd_init(enetIfPtr, rxbdCfg);
00450     if(result != kStatus_ENET_Success)
00451     {
00452         return result;
00453     }
00454     /* Initialize transmit buffer descriptors*/
00455       result = enet_mac_txbd_init(enetIfPtr, txbdCfg);
00456     if(result != kStatus_ENET_Success)
00457     {
00458         return result;
00459     }   
00460     /* Initialize rmii/mii interface*/
00461     result = enet_mac_mii_init(enetIfPtr);
00462     if (result != kStatus_ENET_Success)
00463     {
00464         return result;
00465     }
00466     
00467     return kStatus_ENET_Success;
00468 }
00469 
00470 /*******************************************************************************
00471  * EOF
00472  ******************************************************************************/
00473 
00474 #endif
00475