Benoît Locher / mbedNet
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lpc17xx_emac.cpp Source File

lpc17xx_emac.cpp

00001 /* @cond */
00002 /**
00003  * @file        lpc17xx_emac.c
00004  * @brief       Contains all functions support for Ethernet MAC firmware library on LPC17xx
00005  * @version     2.0
00006  * @date        21. May. 2010
00007  * @author      NXP MCU SW Application Team
00008  **************************************************************************
00009  * Software that is described herein is for illustrative purposes only
00010  * which provides customers with programming information regarding the
00011  * products. This software is supplied "AS IS" without any warranties.
00012  * NXP Semiconductors assumes no responsibility or liability for the
00013  * use of the software, conveys no license or title under any patent,
00014  * copyright, or mask work right to the product. NXP Semiconductors
00015  * reserves the right to make changes in the software without
00016  * notification. NXP Semiconductors also make no representation or
00017  * warranty that such application will be suitable for the specified
00018  * use without further testing or modification.
00019  **********************************************************************/
00020 
00021 /* Peripheral group ----------------------------------------------------------- */
00022 /** @addtogroup EMAC
00023  * @{
00024  */
00025 
00026 /* Includes ------------------------------------------------------------------- */
00027 #include "lpc17xx_emac.h"
00028 #include "lpc17xx_clkpwr.h"
00029 
00030 /* If this source file built with example, the LPC17xx FW library configuration
00031  * file in each example directory ("lpc17xx_libcfg.h") must be included,
00032  * otherwise the default FW library configuration file must be included instead
00033  */
00034 #ifdef __BUILD_WITH_EXAMPLE__
00035 #include "lpc17xx_libcfg.h"
00036 #else
00037 #include "lpc17xx_libcfg_default.h"
00038 #endif /* __BUILD_WITH_EXAMPLE__ */
00039 
00040 
00041 #ifdef _EMAC
00042 
00043 /* Private Variables ---------------------------------------------------------- */
00044 /** @defgroup EMAC_Private_Variables EMAC Private Variables
00045  * @{
00046  */
00047 
00048 /* MII Mgmt Configuration register - Clock divider setting */
00049 const uint8_t EMAC_clkdiv[] = { 4, 6, 8, 10, 14, 20, 28 };
00050 
00051 /* EMAC local DMA Descriptors */
00052 
00053 /** Rx Descriptor data array */
00054 static RX_Desc Rx_Desc[EMAC_NUM_RX_FRAG];
00055 
00056 /** Rx Status data array - Must be 8-Byte aligned */
00057 #if defined ( __CC_ARM   )
00058 static __align(8) RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG];
00059 #elif defined ( __ICCARM__ )
00060 #pragma data_alignment=8
00061 static RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG];
00062 #elif defined   (  __GNUC__  )
00063 static __attribute__ ((aligned (8))) RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG];
00064 #endif
00065 
00066 /** Tx Descriptor data array */
00067 static TX_Desc Tx_Desc[EMAC_NUM_TX_FRAG];
00068 /** Tx Status data array */
00069 static TX_Stat Tx_Stat[EMAC_NUM_TX_FRAG];
00070 
00071 /* EMAC local DMA buffers */
00072 /** Rx buffer data */
00073 static __align(8) uint32_t rx_buf[EMAC_NUM_RX_FRAG][EMAC_ETH_MAX_FLEN>>2] __attribute((section("AHBSRAM1"),aligned)) ;
00074 /** Tx buffer data */
00075 static __align(8) uint32_t tx_buf[EMAC_NUM_TX_FRAG][EMAC_ETH_MAX_FLEN>>2] __attribute((section("AHBSRAM1"),aligned)) ;
00076 
00077 /**
00078  * @}
00079  */
00080 
00081 /* Private Functions ---------------------------------------------------------- */
00082 static void rx_descr_init (void);
00083 static void tx_descr_init (void);
00084 static int32_t write_PHY (uint32_t PhyReg, uint16_t Value);
00085 static int32_t  read_PHY (uint32_t PhyReg);
00086 
00087 static void setEmacAddr(uint8_t abStationAddr[]);
00088 static int32_t emac_CRCCalc(uint8_t frame_no_fcs[], int32_t frame_len);
00089 
00090 
00091 /*--------------------------- rx_descr_init ---------------------------------*/
00092 /*********************************************************************//**
00093  * @brief       Initializes RX Descriptor
00094  * @param[in]   None
00095  * @return      None
00096  ***********************************************************************/
00097 static void rx_descr_init (void)
00098 {
00099     /* Initialize Receive Descriptor and Status array. */
00100     uint32_t i;
00101 
00102     for (i = 0; i < EMAC_NUM_RX_FRAG; i++) {
00103         Rx_Desc[i].Packet  = (uint32_t)&rx_buf[i];
00104         Rx_Desc[i].Ctrl    = EMAC_RCTRL_INT | (EMAC_ETH_MAX_FLEN - 1);
00105         Rx_Stat[i].Info    = 0;
00106         Rx_Stat[i].HashCRC = 0;
00107     }
00108 
00109     /* Set EMAC Receive Descriptor Registers. */
00110     LPC_EMAC->RxDescriptor       = (uint32_t)&Rx_Desc[0];
00111     LPC_EMAC->RxStatus           = (uint32_t)&Rx_Stat[0];
00112     LPC_EMAC->RxDescriptorNumber = EMAC_NUM_RX_FRAG - 1;
00113 
00114     /* Rx Descriptors Point to 0 */
00115     LPC_EMAC->RxConsumeIndex  = 0;
00116 }
00117 
00118 
00119 /*--------------------------- tx_descr_init ---- ----------------------------*/
00120 /*********************************************************************//**
00121  * @brief       Initializes TX Descriptor
00122  * @param[in]   None
00123  * @return      None
00124  ***********************************************************************/
00125 static void tx_descr_init (void) {
00126     /* Initialize Transmit Descriptor and Status array. */
00127     uint32_t i;
00128 
00129     for (i = 0; i < EMAC_NUM_TX_FRAG; i++) {
00130         Tx_Desc[i].Packet = (uint32_t)&tx_buf[i];
00131         Tx_Desc[i].Ctrl   = 0;
00132         Tx_Stat[i].Info   = 0;
00133     }
00134 
00135     /* Set EMAC Transmit Descriptor Registers. */
00136     LPC_EMAC->TxDescriptor       = (uint32_t)&Tx_Desc[0];
00137     LPC_EMAC->TxStatus           = (uint32_t)&Tx_Stat[0];
00138     LPC_EMAC->TxDescriptorNumber = EMAC_NUM_TX_FRAG - 1;
00139 
00140     /* Tx Descriptors Point to 0 */
00141     LPC_EMAC->TxProduceIndex  = 0;
00142 }
00143 
00144 
00145 /*--------------------------- write_PHY -------------------------------------*/
00146 /*********************************************************************//**
00147  * @brief       Write value to PHY device
00148  * @param[in]   PhyReg: PHY Register address
00149  * @param[in]   Value:  Value to write
00150  * @return      0 - if success
00151  *              1 - if fail
00152  ***********************************************************************/
00153 static int32_t write_PHY (uint32_t PhyReg, uint16_t Value)
00154 {
00155     /* Write a data 'Value' to PHY register 'PhyReg'. */
00156     uint32_t tout;
00157 
00158     LPC_EMAC->MADR = EMAC_DEF_ADR | PhyReg;
00159     LPC_EMAC->MWTD = Value;
00160 
00161     /* Wait until operation completed */
00162     tout = 0;
00163     for (tout = 0; tout < EMAC_MII_WR_TOUT; tout++) {
00164         if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0) {
00165             return (0);
00166         }
00167     }
00168     // Time out!
00169     return (-1);
00170 }
00171 
00172 
00173 /*--------------------------- read_PHY --------------------------------------*/
00174 /*********************************************************************//**
00175  * @brief       Read value from PHY device
00176  * @param[in]   PhyReg: PHY Register address
00177  * @return      0 - if success
00178  *              1 - if fail
00179  ***********************************************************************/
00180 static int32_t read_PHY (uint32_t PhyReg)
00181 {
00182     /* Read a PHY register 'PhyReg'. */
00183     uint32_t tout;
00184 
00185     LPC_EMAC->MADR = EMAC_DEF_ADR | PhyReg;
00186     LPC_EMAC->MCMD = EMAC_MCMD_READ;
00187 
00188     /* Wait until operation completed */
00189     tout = 0;
00190     for (tout = 0; tout < EMAC_MII_RD_TOUT; tout++) {
00191         if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0) {
00192             LPC_EMAC->MCMD = 0;
00193             return (LPC_EMAC->MRDD);
00194         }
00195     }
00196     // Time out!
00197     return (-1);
00198 }
00199 
00200 /*********************************************************************//**
00201  * @brief       Set Station MAC address for EMAC module
00202  * @param[in]   abStationAddr Pointer to Station address that contains 6-bytes
00203  *              of MAC address (should be in order from MAC Address 1 to MAC Address 6)
00204  * @return      None
00205  **********************************************************************/
00206 static void setEmacAddr(uint8_t abStationAddr[])
00207 {
00208     /* Set the Ethernet MAC Address registers */
00209     LPC_EMAC->SA0 = ((uint32_t)abStationAddr[5] << 8) | (uint32_t)abStationAddr[4];
00210     LPC_EMAC->SA1 = ((uint32_t)abStationAddr[3] << 8) | (uint32_t)abStationAddr[2];
00211     LPC_EMAC->SA2 = ((uint32_t)abStationAddr[1] << 8) | (uint32_t)abStationAddr[0];
00212 }
00213 
00214 
00215 /*********************************************************************//**
00216  * @brief       Calculates CRC code for number of bytes in the frame
00217  * @param[in]   frame_no_fcs    Pointer to the first byte of the frame
00218  * @param[in]   frame_len       length of the frame without the FCS
00219  * @return      the CRC as a 32 bit integer
00220  **********************************************************************/
00221 static int32_t emac_CRCCalc(uint8_t frame_no_fcs[], int32_t frame_len)
00222 {
00223     int i;      // iterator
00224     int j;      // another iterator
00225     char byte;  // current byte
00226     int crc;    // CRC result
00227     int q0, q1, q2, q3; // temporary variables
00228     crc = 0xFFFFFFFF;
00229     for (i = 0; i < frame_len; i++) {
00230         byte = *frame_no_fcs++;
00231         for (j = 0; j < 2; j++) {
00232             if (((crc >> 28) ^ (byte >> 3)) & 0x00000001) {
00233                 q3 = 0x04C11DB7;
00234             } else {
00235                 q3 = 0x00000000;
00236             }
00237             if (((crc >> 29) ^ (byte >> 2)) & 0x00000001) {
00238                 q2 = 0x09823B6E;
00239             } else {
00240                 q2 = 0x00000000;
00241             }
00242             if (((crc >> 30) ^ (byte >> 1)) & 0x00000001) {
00243                 q1 = 0x130476DC;
00244             } else {
00245                 q1 = 0x00000000;
00246             }
00247             if (((crc >> 31) ^ (byte >> 0)) & 0x00000001) {
00248                 q0 = 0x2608EDB8;
00249             } else {
00250                 q0 = 0x00000000;
00251             }
00252             crc = (crc << 4) ^ q3 ^ q2 ^ q1 ^ q0;
00253             byte >>= 4;
00254         }
00255     }
00256     return crc;
00257 }
00258 /* End of Private Functions --------------------------------------------------- */
00259 
00260 
00261 /* Public Functions ----------------------------------------------------------- */
00262 /** @addtogroup EMAC_Public_Functions
00263  * @{
00264  */
00265 
00266 
00267 /*********************************************************************//**
00268  * @brief       Initializes the EMAC peripheral according to the specified
00269 *               parameters in the EMAC_ConfigStruct.
00270  * @param[in]   EMAC_ConfigStruct Pointer to a EMAC_CFG_Type structure
00271 *                    that contains the configuration information for the
00272 *                    specified EMAC peripheral.
00273  * @return      None
00274  *
00275  * Note: This function will initialize EMAC module according to procedure below:
00276  *  - Remove the soft reset condition from the MAC
00277  *  - Configure the PHY via the MIIM interface of the MAC
00278  *  - Select RMII mode
00279  *  - Configure the transmit and receive DMA engines, including the descriptor arrays
00280  *  - Configure the host registers (MAC1,MAC2 etc.) in the MAC
00281  *  - Enable the receive and transmit data paths
00282  *  In default state after initializing, only Rx Done and Tx Done interrupt are enabled,
00283  *  all remain interrupts are disabled
00284  *  (Ref. from LPC17xx UM)
00285  **********************************************************************/
00286 Status EMAC_Init(EMAC_CFG_Type *EMAC_ConfigStruct)
00287 {
00288     /* Initialize the EMAC Ethernet controller. */
00289     int32_t regv,tout, tmp;
00290 
00291     /* Set up clock and power for Ethernet module */
00292     CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCENET, ENABLE);
00293 
00294     /* Reset all EMAC internal modules */
00295     LPC_EMAC->MAC1    = EMAC_MAC1_RES_TX | EMAC_MAC1_RES_MCS_TX | EMAC_MAC1_RES_RX |
00296                     EMAC_MAC1_RES_MCS_RX | EMAC_MAC1_SIM_RES | EMAC_MAC1_SOFT_RES;
00297 
00298     LPC_EMAC->Command = EMAC_CR_REG_RES | EMAC_CR_TX_RES | EMAC_CR_RX_RES | EMAC_CR_PASS_RUNT_FRM;
00299 
00300     /* A short delay after reset. */
00301     for (tout = 100; tout; tout--);
00302 
00303     /* Initialize MAC control registers. */
00304     LPC_EMAC->MAC1 = EMAC_MAC1_PASS_ALL;
00305     LPC_EMAC->MAC2 = EMAC_MAC2_CRC_EN | EMAC_MAC2_PAD_EN;
00306     LPC_EMAC->MAXF = EMAC_ETH_MAX_FLEN;
00307     /*
00308      * Find the clock that close to desired target clock
00309      */
00310     tmp = SystemCoreClock / EMAC_MCFG_MII_MAXCLK;
00311     for (tout = 0; tout < sizeof (EMAC_clkdiv); tout++){
00312         if (EMAC_clkdiv[tout] >= tmp) break;
00313     }
00314     tout++;
00315     // Write to MAC configuration register and reset
00316     LPC_EMAC->MCFG = EMAC_MCFG_CLK_SEL(tout) | EMAC_MCFG_RES_MII;
00317     // release reset
00318     LPC_EMAC->MCFG &= ~(EMAC_MCFG_RES_MII);
00319     LPC_EMAC->CLRT = EMAC_CLRT_DEF;
00320     LPC_EMAC->IPGR = EMAC_IPGR_P2_DEF;
00321 
00322     /* Enable Reduced MII interface. */
00323     LPC_EMAC->Command = EMAC_CR_RMII | EMAC_CR_PASS_RUNT_FRM;
00324 
00325     /* Reset Reduced MII Logic. */
00326     LPC_EMAC->SUPP = EMAC_SUPP_RES_RMII;
00327 
00328     for (tout = 100; tout; tout--);
00329     LPC_EMAC->SUPP = 0;
00330 
00331     /* Put the DP83848C in reset mode */
00332     write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_BMCR_RESET);
00333 
00334     /* Wait for hardware reset to end. */
00335     for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) {
00336         regv = read_PHY (EMAC_PHY_REG_BMCR);
00337         if (!(regv & (EMAC_PHY_BMCR_RESET | EMAC_PHY_BMCR_POWERDOWN))) {
00338             /* Reset complete, device not Power Down. */
00339             break;
00340         }
00341         if (tout == 0){
00342             // Time out, return ERROR
00343             return (ERROR);
00344         }
00345     }
00346 
00347     // Set PHY mode
00348     if (EMAC_SetPHYMode(EMAC_ConfigStruct->Mode) < 0){
00349         return (ERROR);
00350     }
00351 
00352     // Set EMAC address
00353     setEmacAddr(EMAC_ConfigStruct->pbEMAC_Addr);
00354 
00355     /* Initialize Tx and Rx DMA Descriptors */
00356     rx_descr_init ();
00357     tx_descr_init ();
00358 
00359     // Set Receive Filter register: enable broadcast and multicast
00360     LPC_EMAC->RxFilterCtrl = EMAC_RFC_MCAST_EN | EMAC_RFC_BCAST_EN | EMAC_RFC_PERFECT_EN;
00361 
00362     /* Enable Rx Done and Tx Done interrupt for EMAC */
00363     LPC_EMAC->IntEnable = EMAC_INT_RX_DONE/* | EMAC_INT_TX_DONE*/;
00364 
00365     /* Reset all interrupts */
00366     LPC_EMAC->IntClear  = 0xFFFF;
00367 
00368     /* Enable receive and transmit mode of MAC Ethernet core */
00369     LPC_EMAC->Command  |= (EMAC_CR_RX_EN | EMAC_CR_TX_EN);
00370     LPC_EMAC->MAC1     |= EMAC_MAC1_REC_EN;
00371 
00372     return SUCCESS;
00373 }
00374 
00375 
00376 /*********************************************************************//**
00377  * @brief       De-initializes the EMAC peripheral registers to their
00378 *                  default reset values.
00379  * @param[in]   None
00380  * @return      None
00381  **********************************************************************/
00382 void EMAC_DeInit(void)
00383 {
00384     // Disable all interrupt
00385     LPC_EMAC->IntEnable = 0x00;
00386     // Clear all pending interrupt
00387     LPC_EMAC->IntClear = (0xFF) | (EMAC_INT_SOFT_INT | EMAC_INT_WAKEUP);
00388 
00389     /* TurnOff clock and power for Ethernet module */
00390     CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCENET, DISABLE);
00391 }
00392 
00393 
00394 /*********************************************************************//**
00395  * @brief       Check specified PHY status in EMAC peripheral
00396  * @param[in]   ulPHYState  Specified PHY Status Type, should be:
00397  *                          - EMAC_PHY_STAT_LINK: Link Status
00398  *                          - EMAC_PHY_STAT_SPEED: Speed Status
00399  *                          - EMAC_PHY_STAT_DUP: Duplex Status
00400  * @return      Status of specified PHY status (0 or 1).
00401  *              (-1) if error.
00402  *
00403  * Note:
00404  * For EMAC_PHY_STAT_LINK, return value:
00405  * - 0: Link Down
00406  * - 1: Link Up
00407  * For EMAC_PHY_STAT_SPEED, return value:
00408  * - 0: 10Mbps
00409  * - 1: 100Mbps
00410  * For EMAC_PHY_STAT_DUP, return value:
00411  * - 0: Half-Duplex
00412  * - 1: Full-Duplex
00413  **********************************************************************/
00414 int32_t EMAC_CheckPHYStatus(uint32_t ulPHYState)
00415 {
00416     int32_t regv, tmp;
00417 #ifdef MCB_LPC_1768
00418     regv = read_PHY (EMAC_PHY_REG_STS);
00419     switch(ulPHYState){
00420     case EMAC_PHY_STAT_LINK:
00421         tmp = (regv & EMAC_PHY_SR_LINK) ? 1 : 0;
00422         break;
00423     case EMAC_PHY_STAT_SPEED:
00424         tmp = (regv & EMAC_PHY_SR_SPEED) ? 0 : 1;
00425         break;
00426     case EMAC_PHY_STAT_DUP:
00427         tmp = (regv & EMAC_PHY_SR_FULL_DUP) ? 1 : 0;
00428         break;
00429 #elif defined(IAR_LPC_1768)
00430     /* Use IAR_LPC_1768 board:
00431      * FSZ8721BL doesn't have Status Register
00432      * so we read Basic Mode Status Register (0x01h) instead
00433      */
00434     regv = read_PHY (EMAC_PHY_REG_BMSR);
00435     switch(ulPHYState){
00436     case EMAC_PHY_STAT_LINK:
00437         tmp = (regv & EMAC_PHY_BMSR_LINK_STATUS) ? 1 : 0;
00438         break;
00439     case EMAC_PHY_STAT_SPEED:
00440         tmp = (regv & EMAC_PHY_SR_100_SPEED) ? 1 : 0;
00441         break;
00442     case EMAC_PHY_STAT_DUP:
00443         tmp = (regv & EMAC_PHY_SR_FULL_DUP) ? 1 : 0;
00444         break;
00445 #endif
00446     default:
00447         tmp = -1;
00448         break;
00449     }
00450     return (tmp);
00451 }
00452 
00453 
00454 /*********************************************************************//**
00455  * @brief       Set specified PHY mode in EMAC peripheral
00456  * @param[in]   ulPHYMode   Specified PHY mode, should be:
00457  *                          - EMAC_MODE_AUTO
00458  *                          - EMAC_MODE_10M_FULL
00459  *                          - EMAC_MODE_10M_HALF
00460  *                          - EMAC_MODE_100M_FULL
00461  *                          - EMAC_MODE_100M_HALF
00462  * @return      Return (0) if no error, otherwise return (-1)
00463  **********************************************************************/
00464 int32_t EMAC_SetPHYMode(uint32_t ulPHYMode)
00465 {
00466     int32_t id1, id2, tout, regv;
00467 
00468     /* Check if this is a DP83848C PHY. */
00469     id1 = read_PHY (EMAC_PHY_REG_IDR1);
00470     id2 = read_PHY (EMAC_PHY_REG_IDR2);
00471 
00472 #ifdef MCB_LPC_1768
00473     if (((id1 << 16) | (id2 & 0xFFF0)) == EMAC_DP83848C_ID) {
00474         switch(ulPHYMode){
00475         case EMAC_MODE_AUTO:
00476             write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_AUTO_NEG);
00477 #elif defined(IAR_LPC_1768) /* Use IAR LPC1768 KickStart board */
00478     if (((id1 << 16) | id2) == EMAC_KSZ8721BL_ID) {
00479         /* Configure the PHY device */
00480         switch(ulPHYMode){
00481         case EMAC_MODE_AUTO:
00482             /* Use auto-negotiation about the link speed. */
00483             write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_AUTO_NEG);
00484 //          write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_BMCR_AN);
00485 #endif
00486             /* Wait to complete Auto_Negotiation */
00487             for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) {
00488                 regv = read_PHY (EMAC_PHY_REG_BMSR);
00489                 if (regv & EMAC_PHY_BMSR_AUTO_DONE) {
00490                     /* Auto-negotiation Complete. */
00491                     break;
00492                 }
00493                 if (tout == 0){
00494                     // Time out, return error
00495                     return (-1);
00496                 }
00497             }
00498             break;
00499         case EMAC_MODE_10M_FULL:
00500             /* Connect at 10MBit full-duplex */
00501             write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_FULLD_10M);
00502             break;
00503         case EMAC_MODE_10M_HALF:
00504             /* Connect at 10MBit half-duplex */
00505             write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_HALFD_10M);
00506             break;
00507         case EMAC_MODE_100M_FULL:
00508             /* Connect at 100MBit full-duplex */
00509             write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_FULLD_100M);
00510             break;
00511         case EMAC_MODE_100M_HALF:
00512             /* Connect at 100MBit half-duplex */
00513             write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_HALFD_100M);
00514             break;
00515         default:
00516             // un-supported
00517             return (-1);
00518         }
00519     }
00520     // It's not correct module ID
00521     else {
00522         return (-1);
00523     }
00524 
00525     // Update EMAC configuration with current PHY status
00526     if (EMAC_UpdatePHYStatus() < 0){
00527         return (-1);
00528     }
00529 
00530     // Complete
00531     return (0);
00532 }
00533 
00534 
00535 /*********************************************************************//**
00536  * @brief       Auto-Configures value for the EMAC configuration register to
00537  *              match with current PHY mode
00538  * @param[in]   None
00539  * @return      Return (0) if no error, otherwise return (-1)
00540  *
00541  * Note: The EMAC configuration will be auto-configured:
00542  *      - Speed mode.
00543  *      - Half/Full duplex mode
00544  **********************************************************************/
00545 int32_t EMAC_UpdatePHYStatus(void)
00546 {
00547     int32_t regv, tout;
00548 
00549     /* Check the link status. */
00550 #ifdef MCB_LPC_1768
00551     for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) {
00552         regv = read_PHY (EMAC_PHY_REG_STS);
00553         if (regv & EMAC_PHY_SR_LINK) {
00554             /* Link is on. */
00555             break;
00556         }
00557         if (tout == 0){
00558             // time out
00559             return (-1);
00560         }
00561     }
00562     /* Configure Full/Half Duplex mode. */
00563     if (regv & EMAC_PHY_SR_DUP) {
00564     /* Full duplex is enabled. */
00565             LPC_EMAC->MAC2    |= EMAC_MAC2_FULL_DUP;
00566             LPC_EMAC->Command |= EMAC_CR_FULL_DUP;
00567             LPC_EMAC->IPGT     = EMAC_IPGT_FULL_DUP;
00568     } else {
00569         /* Half duplex mode. */
00570         LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP;
00571     }
00572     if (regv & EMAC_PHY_SR_SPEED) {
00573     /* 10MBit mode. */
00574         LPC_EMAC->SUPP = 0;
00575     } else {
00576         /* 100MBit mode. */
00577         LPC_EMAC->SUPP = EMAC_SUPP_SPEED;
00578     }
00579 #elif defined(IAR_LPC_1768)
00580     for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) {
00581         regv = read_PHY (EMAC_PHY_REG_BMSR);
00582         if (regv & EMAC_PHY_BMSR_LINK_STATUS) {
00583             /* Link is on. */
00584             break;
00585         }
00586         if (tout == 0){
00587             // time out
00588             return (-1);
00589         }
00590     }
00591 
00592     /* Configure Full/Half Duplex mode. */
00593     if (regv & EMAC_PHY_SR_FULL_DUP) {
00594         /* Full duplex is enabled. */
00595         LPC_EMAC->MAC2    |= EMAC_MAC2_FULL_DUP;
00596         LPC_EMAC->Command |= EMAC_CR_FULL_DUP;
00597         LPC_EMAC->IPGT     = EMAC_IPGT_FULL_DUP;
00598     } else {
00599         /* Half duplex mode. */
00600         LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP;
00601     }
00602 
00603     /* Configure 100MBit/10MBit mode. */
00604     if (!(regv & EMAC_PHY_SR_100_SPEED)) {
00605         /* 10MBit mode. */
00606         LPC_EMAC->SUPP = 0;
00607     } else {
00608         /* 100MBit mode. */
00609         LPC_EMAC->SUPP = EMAC_SUPP_SPEED;
00610     }
00611 #endif
00612     // Complete
00613     return (0);
00614 }
00615 
00616 
00617 /*********************************************************************//**
00618  * @brief       Enable/Disable hash filter functionality for specified destination
00619  *              MAC address in EMAC module
00620  * @param[in]   dstMAC_addr     Pointer to the first MAC destination address, should
00621  *                              be 6-bytes length, in order LSB to the MSB
00622  * @param[in]   NewState        New State of this command, should be:
00623  *                                  - ENABLE.
00624  *                                  - DISABLE.
00625  * @return      None
00626  *
00627  * Note:
00628  * The standard Ethernet cyclic redundancy check (CRC) function is calculated from
00629  * the 6 byte destination address in the Ethernet frame (this CRC is calculated
00630  * anyway as part of calculating the CRC of the whole frame), then bits [28:23] out of
00631  * the 32 bits CRC result are taken to form the hash. The 6 bit hash is used to access
00632  * the hash table: it is used as an index in the 64 bit HashFilter register that has been
00633  * programmed with accept values. If the selected accept value is 1, the frame is
00634  * accepted.
00635  **********************************************************************/
00636 void EMAC_SetHashFilter(uint8_t dstMAC_addr[], FunctionalState NewState)
00637 {
00638     uint32_t *pReg;
00639     uint32_t tmp;
00640     int32_t crc;
00641 
00642     // Calculate the CRC from the destination MAC address
00643     crc = emac_CRCCalc(dstMAC_addr, 6);
00644     // Extract the value from CRC to get index value for hash filter table
00645     crc = (crc >> 23) & 0x3F;
00646 
00647     pReg = (crc > 31) ? ((uint32_t *)&LPC_EMAC->HashFilterH) \
00648                                 : ((uint32_t *)&LPC_EMAC->HashFilterL);
00649     tmp = (crc > 31) ? (crc - 32) : crc;
00650     if (NewState == ENABLE) {
00651         (*pReg) |= (1UL << tmp);
00652     } else {
00653         (*pReg) &= ~(1UL << tmp);
00654     }
00655     // Enable Rx Filter
00656     LPC_EMAC->Command &= ~EMAC_CR_PASS_RX_FILT;
00657 }
00658 
00659 /*********************************************************************//**
00660  * @brief       Enable/Disable Filter mode for each specified type EMAC peripheral
00661  * @param[in]   ulFilterMode    Filter mode, should be:
00662  *                              - EMAC_RFC_UCAST_EN: all frames of unicast types
00663  *                              will be accepted
00664  *                              - EMAC_RFC_BCAST_EN: broadcast frame will be
00665  *                              accepted
00666  *                              - EMAC_RFC_MCAST_EN: all frames of multicast
00667  *                              types will be accepted
00668  *                              - EMAC_RFC_UCAST_HASH_EN: The imperfect hash
00669  *                              filter will be applied to unicast addresses
00670  *                              - EMAC_RFC_MCAST_HASH_EN: The imperfect hash
00671  *                              filter will be applied to multicast addresses
00672  *                              - EMAC_RFC_PERFECT_EN: the destination address
00673  *                              will be compared with the 6 byte station address
00674  *                              programmed in the station address by the filter
00675  *                              - EMAC_RFC_MAGP_WOL_EN: the result of the magic
00676  *                              packet filter will generate a WoL interrupt when
00677  *                              there is a match
00678  *                              - EMAC_RFC_PFILT_WOL_EN: the result of the perfect address
00679  *                              matching filter and the imperfect hash filter will
00680  *                              generate a WoL interrupt when there is a match
00681  * @param[in]   NewState    New State of this command, should be:
00682  *                              - ENABLE
00683  *                              - DISABLE
00684  * @return      None
00685  **********************************************************************/
00686 void EMAC_SetFilterMode(uint32_t ulFilterMode, FunctionalState NewState)
00687 {
00688     if (NewState == ENABLE){
00689         LPC_EMAC->RxFilterCtrl |= ulFilterMode;
00690     } else {
00691         LPC_EMAC->RxFilterCtrl &= ~ulFilterMode;
00692     }
00693 }
00694 
00695 /*********************************************************************//**
00696  * @brief       Get status of Wake On LAN Filter for each specified
00697  *              type in EMAC peripheral, clear this status if it is set
00698  * @param[in]   ulWoLMode   WoL Filter mode, should be:
00699  *                              - EMAC_WOL_UCAST: unicast frames caused WoL
00700  *                              - EMAC_WOL_UCAST: broadcast frame caused WoL
00701  *                              - EMAC_WOL_MCAST: multicast frame caused WoL
00702  *                              - EMAC_WOL_UCAST_HASH: unicast frame that passes the
00703  *                              imperfect hash filter caused WoL
00704  *                              - EMAC_WOL_MCAST_HASH: multicast frame that passes the
00705  *                              imperfect hash filter caused WoL
00706  *                              - EMAC_WOL_PERFECT:perfect address matching filter
00707  *                              caused WoL
00708  *                              - EMAC_WOL_RX_FILTER: the receive filter caused WoL
00709  *                              - EMAC_WOL_MAG_PACKET: the magic packet filter caused WoL
00710  * @return      SET/RESET
00711  **********************************************************************/
00712 FlagStatus EMAC_GetWoLStatus(uint32_t ulWoLMode)
00713 {
00714     if (LPC_EMAC->RxFilterWoLStatus & ulWoLMode) {
00715         LPC_EMAC->RxFilterWoLClear = ulWoLMode;
00716         return SET;
00717     } else {
00718         return RESET;
00719     }
00720 }
00721 
00722 
00723 /*********************************************************************//**
00724  * @brief       Write data to Tx packet data buffer at current index due to
00725  *              TxProduceIndex
00726  * @param[in]   pDataStruct     Pointer to a EMAC_PACKETBUF_Type structure
00727  *                          data that contain specified information about
00728  *                          Packet data buffer.
00729  * @return      None
00730  **********************************************************************/
00731 void EMAC_WritePacketBuffer(EMAC_PACKETBUF_Type *pDataStruct)
00732 {
00733     uint32_t idx,len;
00734     uint32_t *sp,*dp;
00735 
00736     idx = LPC_EMAC->TxProduceIndex;
00737     sp  = (uint32_t *)pDataStruct->pbDataBuf;
00738     dp  = (uint32_t *)Tx_Desc[idx].Packet;
00739     /* Copy frame data to EMAC packet buffers. */
00740     for (len = (pDataStruct->ulDataLen + 3) >> 2; len; len--) {
00741         *dp++ = *sp++;
00742     }
00743     Tx_Desc[idx].Ctrl = (pDataStruct->ulDataLen - 1) | (EMAC_TCTRL_INT | EMAC_TCTRL_LAST);
00744 }
00745 
00746 /*********************************************************************//**
00747  * @brief       Read data from Rx packet data buffer at current index due
00748  *              to RxConsumeIndex
00749  * @param[in]   pDataStruct     Pointer to a EMAC_PACKETBUF_Type structure
00750  *                          data that contain specified information about
00751  *                          Packet data buffer.
00752  * @return      None
00753  **********************************************************************/
00754 void EMAC_ReadPacketBuffer(EMAC_PACKETBUF_Type *pDataStruct)
00755 {
00756     uint32_t idx, len;
00757     uint32_t *dp, *sp;
00758 
00759     idx = LPC_EMAC->RxConsumeIndex;
00760     dp = (uint32_t *)pDataStruct->pbDataBuf;
00761     sp = (uint32_t *)Rx_Desc[idx].Packet;
00762 
00763     if (pDataStruct->pbDataBuf != NULL) {
00764         for (len = (pDataStruct->ulDataLen + 3) >> 2; len; len--) {
00765             *dp++ = *sp++;
00766         }
00767     }
00768 }
00769 
00770 /*********************************************************************//**
00771  * @brief       Enable/Disable interrupt for each type in EMAC
00772  * @param[in]   ulIntType   Interrupt Type, should be:
00773  *                          - EMAC_INT_RX_OVERRUN: Receive Overrun
00774  *                          - EMAC_INT_RX_ERR: Receive Error
00775  *                          - EMAC_INT_RX_FIN: Receive Descriptor Finish
00776  *                          - EMAC_INT_RX_DONE: Receive Done
00777  *                          - EMAC_INT_TX_UNDERRUN: Transmit Under-run
00778  *                          - EMAC_INT_TX_ERR: Transmit Error
00779  *                          - EMAC_INT_TX_FIN: Transmit descriptor finish
00780  *                          - EMAC_INT_TX_DONE: Transmit Done
00781  *                          - EMAC_INT_SOFT_INT: Software interrupt
00782  *                          - EMAC_INT_WAKEUP: Wakeup interrupt
00783  * @param[in]   NewState    New State of this function, should be:
00784  *                          - ENABLE.
00785  *                          - DISABLE.
00786  * @return      None
00787  **********************************************************************/
00788 void EMAC_IntCmd(uint32_t ulIntType, FunctionalState NewState)
00789 {
00790     if (NewState == ENABLE) {
00791         LPC_EMAC->IntEnable |= ulIntType;
00792     } else {
00793         LPC_EMAC->IntEnable &= ~(ulIntType);
00794     }
00795 }
00796 
00797 /*********************************************************************//**
00798  * @brief       Check whether if specified interrupt flag is set or not
00799  *              for each interrupt type in EMAC and clear interrupt pending
00800  *              if it is set.
00801  * @param[in]   ulIntType   Interrupt Type, should be:
00802  *                          - EMAC_INT_RX_OVERRUN: Receive Overrun
00803  *                          - EMAC_INT_RX_ERR: Receive Error
00804  *                          - EMAC_INT_RX_FIN: Receive Descriptor Finish
00805  *                          - EMAC_INT_RX_DONE: Receive Done
00806  *                          - EMAC_INT_TX_UNDERRUN: Transmit Under-run
00807  *                          - EMAC_INT_TX_ERR: Transmit Error
00808  *                          - EMAC_INT_TX_FIN: Transmit descriptor finish
00809  *                          - EMAC_INT_TX_DONE: Transmit Done
00810  *                          - EMAC_INT_SOFT_INT: Software interrupt
00811  *                          - EMAC_INT_WAKEUP: Wakeup interrupt
00812  * @return      New state of specified interrupt (SET or RESET)
00813  **********************************************************************/
00814 IntStatus EMAC_IntGetStatus(uint32_t ulIntType)
00815 {
00816     if (LPC_EMAC->IntStatus & ulIntType) {
00817         LPC_EMAC->IntClear = ulIntType;
00818         return SET;
00819     } else {
00820         return RESET;
00821     }
00822 }
00823 
00824 
00825 /*********************************************************************//**
00826  * @brief       Check whether if the current RxConsumeIndex is not equal to the
00827  *              current RxProduceIndex.
00828  * @param[in]   None
00829  * @return      TRUE if they're not equal, otherwise return FALSE
00830  *
00831  * Note: In case the RxConsumeIndex is not equal to the RxProduceIndex,
00832  * it means there're available data has been received. They should be read
00833  * out and released the Receive Data Buffer by updating the RxConsumeIndex value.
00834  **********************************************************************/
00835 Bool EMAC_CheckReceiveIndex(void)
00836 {
00837     if (LPC_EMAC->RxConsumeIndex != LPC_EMAC->RxProduceIndex) {
00838         return TRUE;
00839     } else {
00840         return FALSE;
00841     }
00842 }
00843 
00844 
00845 /*********************************************************************//**
00846  * @brief       Check whether if the current TxProduceIndex is not equal to the
00847  *              current RxProduceIndex - 1.
00848  * @param[in]   None
00849  * @return      TRUE if they're not equal, otherwise return FALSE
00850  *
00851  * Note: In case the RxConsumeIndex is equal to the RxProduceIndex - 1,
00852  * it means the transmit buffer is available and data can be written to transmit
00853  * buffer to be sent.
00854  **********************************************************************/
00855 Bool EMAC_CheckTransmitIndex(void)
00856 {
00857     uint32_t tmp = LPC_EMAC->TxConsumeIndex -1;
00858     if (LPC_EMAC->TxProduceIndex == tmp) {
00859         return FALSE;
00860     } else {
00861         return TRUE;
00862     }
00863 }
00864 
00865 
00866 /*********************************************************************//**
00867  * @brief       Get current status value of receive data (due to RxConsumeIndex)
00868  * @param[in]   ulRxStatType    Received Status type, should be one of following:
00869  *                          - EMAC_RINFO_CTRL_FRAME: Control Frame
00870  *                          - EMAC_RINFO_VLAN: VLAN Frame
00871  *                          - EMAC_RINFO_FAIL_FILT: RX Filter Failed
00872  *                          - EMAC_RINFO_MCAST: Multicast Frame
00873  *                          - EMAC_RINFO_BCAST: Broadcast Frame
00874  *                          - EMAC_RINFO_CRC_ERR: CRC Error in Frame
00875  *                          - EMAC_RINFO_SYM_ERR: Symbol Error from PHY
00876  *                          - EMAC_RINFO_LEN_ERR: Length Error
00877  *                          - EMAC_RINFO_RANGE_ERR: Range error(exceeded max size)
00878  *                          - EMAC_RINFO_ALIGN_ERR: Alignment error
00879  *                          - EMAC_RINFO_OVERRUN: Receive overrun
00880  *                          - EMAC_RINFO_NO_DESCR: No new Descriptor available
00881  *                          - EMAC_RINFO_LAST_FLAG: last Fragment in Frame
00882  *                          - EMAC_RINFO_ERR: Error Occurred (OR of all error)
00883  * @return      Current value of receive data (due to RxConsumeIndex)
00884  **********************************************************************/
00885 FlagStatus EMAC_CheckReceiveDataStatus(uint32_t ulRxStatType)
00886 {
00887     uint32_t idx;
00888     idx = LPC_EMAC->RxConsumeIndex;
00889     return (((Rx_Stat[idx].Info) & ulRxStatType) ? SET : RESET);
00890 }
00891 
00892 
00893 /*********************************************************************//**
00894  * @brief       Get size of current Received data in received buffer (due to
00895  *              RxConsumeIndex)
00896  * @param[in]   None
00897  * @return      Size of received data
00898  **********************************************************************/
00899 uint32_t EMAC_GetReceiveDataSize(void)
00900 {
00901     uint32_t idx;
00902     idx =LPC_EMAC->RxConsumeIndex;
00903     return ((Rx_Stat[idx].Info) & EMAC_RINFO_SIZE);
00904 }
00905 
00906 /*********************************************************************//**
00907  * @brief       Increase the RxConsumeIndex (after reading the Receive buffer
00908  *              to release the Receive buffer) and wrap-around the index if
00909  *              it reaches the maximum Receive Number
00910  * @param[in]   None
00911  * @return      None
00912  **********************************************************************/
00913 void EMAC_UpdateRxConsumeIndex(void)
00914 {
00915     // Get current Rx consume index
00916     uint32_t idx = LPC_EMAC->RxConsumeIndex;
00917 
00918     /* Release frame from EMAC buffer */
00919     if (++idx == EMAC_NUM_RX_FRAG) idx = 0;
00920     LPC_EMAC->RxConsumeIndex = idx;
00921 }
00922 
00923 /*********************************************************************//**
00924  * @brief       Increase the TxProduceIndex (after writting to the Transmit buffer
00925  *              to enable the Transmit buffer) and wrap-around the index if
00926  *              it reaches the maximum Transmit Number
00927  * @param[in]   None
00928  * @return      None
00929  **********************************************************************/
00930 void EMAC_UpdateTxProduceIndex(void)
00931 {
00932     // Get current Tx produce index
00933     uint32_t idx = LPC_EMAC->TxProduceIndex;
00934 
00935     /* Start frame transmission */
00936     if (++idx == EMAC_NUM_TX_FRAG) idx = 0;
00937     LPC_EMAC->TxProduceIndex = idx;
00938 }
00939 
00940 
00941 /**
00942  * @}
00943  */
00944 
00945 #endif /* _EMAC */
00946 
00947 /**
00948  * @}
00949  */
00950 
00951 /* --------------------------------- End Of File ------------------------------ */
00952 /* @endcond */