964 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			964 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/**********************************************************************
 | 
						|
* $Id$      lpc17xx_emac.c              2010-05-21
 | 
						|
*//**
 | 
						|
* @file     lpc17xx_emac.c
 | 
						|
* @brief    Contains all functions support for Ethernet MAC firmware
 | 
						|
*           library on LPC17xx
 | 
						|
* @version  2.0
 | 
						|
* @date     21. May. 2010
 | 
						|
* @author   NXP MCU SW Application Team
 | 
						|
*
 | 
						|
* Copyright(C) 2010, NXP Semiconductor
 | 
						|
* All rights reserved.
 | 
						|
*
 | 
						|
***********************************************************************
 | 
						|
* Software that is described herein is for illustrative purposes only
 | 
						|
* which provides customers with programming information regarding the
 | 
						|
* products. This software is supplied "AS IS" without any warranties.
 | 
						|
* NXP Semiconductors assumes no responsibility or liability for the
 | 
						|
* use of the software, conveys no license or title under any patent,
 | 
						|
* copyright, or mask work right to the product. NXP Semiconductors
 | 
						|
* reserves the right to make changes in the software without
 | 
						|
* notification. NXP Semiconductors also make no representation or
 | 
						|
* warranty that such application will be suitable for the specified
 | 
						|
* use without further testing or modification.
 | 
						|
* Permission to use, copy, modify, and distribute this software and its
 | 
						|
* documentation is hereby granted, under NXP Semiconductors'
 | 
						|
* relevant copyright in the software, without fee, provided that it
 | 
						|
* is used in conjunction with NXP Semiconductors microcontrollers.  This
 | 
						|
* copyright, permission, and disclaimer notice must appear in all copies of
 | 
						|
* this code.
 | 
						|
**********************************************************************/
 | 
						|
 | 
						|
/* Peripheral group ----------------------------------------------------------- */
 | 
						|
/** @addtogroup EMAC
 | 
						|
 * @{
 | 
						|
 */
 | 
						|
 | 
						|
/* Includes ------------------------------------------------------------------- */
 | 
						|
#include "lpc17xx_emac.h"
 | 
						|
#include "lpc17xx_clkpwr.h"
 | 
						|
 | 
						|
/* If this source file built with example, the LPC17xx FW library configuration
 | 
						|
 * file in each example directory ("lpc17xx_libcfg.h") must be included,
 | 
						|
 * otherwise the default FW library configuration file must be included instead
 | 
						|
 */
 | 
						|
#ifdef __BUILD_WITH_EXAMPLE__
 | 
						|
#include "lpc17xx_libcfg.h"
 | 
						|
#else
 | 
						|
#include "lpc17xx_libcfg_default.h"
 | 
						|
#endif /* __BUILD_WITH_EXAMPLE__ */
 | 
						|
 | 
						|
 | 
						|
#ifdef _EMAC
 | 
						|
 | 
						|
/* Private Variables ---------------------------------------------------------- */
 | 
						|
/** @defgroup EMAC_Private_Variables EMAC Private Variables
 | 
						|
 * @{
 | 
						|
 */
 | 
						|
 | 
						|
/* MII Mgmt Configuration register - Clock divider setting */
 | 
						|
const uint8_t EMAC_clkdiv[] = { 4, 6, 8, 10, 14, 20, 28, 36, 40, 44, 48, 52, 56, 60, 64};
 | 
						|
 | 
						|
/* EMAC local DMA Descriptors */
 | 
						|
 | 
						|
/** Rx Descriptor data array */
 | 
						|
static RX_Desc Rx_Desc[EMAC_NUM_RX_FRAG];
 | 
						|
 | 
						|
/** Rx Status data array - Must be 8-Byte aligned */
 | 
						|
#if defined ( __CC_ARM   )
 | 
						|
static __align(8) RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG];
 | 
						|
#elif defined ( __ICCARM__ )
 | 
						|
#pragma data_alignment=8
 | 
						|
static RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG];
 | 
						|
#elif defined   (  __GNUC__  )
 | 
						|
static __attribute__ ((aligned (8))) RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG];
 | 
						|
#endif
 | 
						|
 | 
						|
/** Tx Descriptor data array */
 | 
						|
static TX_Desc Tx_Desc[EMAC_NUM_TX_FRAG];
 | 
						|
/** Tx Status data array */
 | 
						|
static TX_Stat Tx_Stat[EMAC_NUM_TX_FRAG];
 | 
						|
 | 
						|
/* EMAC local DMA buffers */
 | 
						|
/** Rx buffer data */
 | 
						|
static uint32_t rx_buf[EMAC_NUM_RX_FRAG][EMAC_ETH_MAX_FLEN>>2];
 | 
						|
/** Tx buffer data */
 | 
						|
static uint32_t tx_buf[EMAC_NUM_TX_FRAG][EMAC_ETH_MAX_FLEN>>2];
 | 
						|
 | 
						|
/**
 | 
						|
 * @}
 | 
						|
 */
 | 
						|
 | 
						|
/* Private Functions ---------------------------------------------------------- */
 | 
						|
static void rx_descr_init (void);
 | 
						|
static void tx_descr_init (void);
 | 
						|
static int32_t write_PHY (uint32_t PhyReg, uint16_t Value);
 | 
						|
static int32_t  read_PHY (uint32_t PhyReg);
 | 
						|
 | 
						|
static void setEmacAddr(uint8_t abStationAddr[]);
 | 
						|
static int32_t emac_CRCCalc(uint8_t frame_no_fcs[], int32_t frame_len);
 | 
						|
 | 
						|
 | 
						|
/*--------------------------- rx_descr_init ---------------------------------*/
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       Initializes RX Descriptor
 | 
						|
 * @param[in]   None
 | 
						|
 * @return      None
 | 
						|
 ***********************************************************************/
 | 
						|
static void rx_descr_init (void)
 | 
						|
{
 | 
						|
    /* Initialize Receive Descriptor and Status array. */
 | 
						|
    uint32_t i;
 | 
						|
 | 
						|
    for (i = 0; i < EMAC_NUM_RX_FRAG; i++) {
 | 
						|
        Rx_Desc[i].Packet  = (uint32_t)&rx_buf[i];
 | 
						|
        Rx_Desc[i].Ctrl    = EMAC_RCTRL_INT | (EMAC_ETH_MAX_FLEN - 1);
 | 
						|
        Rx_Stat[i].Info    = 0;
 | 
						|
        Rx_Stat[i].HashCRC = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Set EMAC Receive Descriptor Registers. */
 | 
						|
    LPC_EMAC->RxDescriptor       = (uint32_t)&Rx_Desc[0];
 | 
						|
    LPC_EMAC->RxStatus           = (uint32_t)&Rx_Stat[0];
 | 
						|
    LPC_EMAC->RxDescriptorNumber = EMAC_NUM_RX_FRAG - 1;
 | 
						|
 | 
						|
    /* Rx Descriptors Point to 0 */
 | 
						|
    LPC_EMAC->RxConsumeIndex  = 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*--------------------------- tx_descr_init ---- ----------------------------*/
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       Initializes TX Descriptor
 | 
						|
 * @param[in]   None
 | 
						|
 * @return      None
 | 
						|
 ***********************************************************************/
 | 
						|
static void tx_descr_init (void) {
 | 
						|
    /* Initialize Transmit Descriptor and Status array. */
 | 
						|
    uint32_t i;
 | 
						|
 | 
						|
    for (i = 0; i < EMAC_NUM_TX_FRAG; i++) {
 | 
						|
        Tx_Desc[i].Packet = (uint32_t)&tx_buf[i];
 | 
						|
        Tx_Desc[i].Ctrl   = 0;
 | 
						|
        Tx_Stat[i].Info   = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Set EMAC Transmit Descriptor Registers. */
 | 
						|
    LPC_EMAC->TxDescriptor       = (uint32_t)&Tx_Desc[0];
 | 
						|
    LPC_EMAC->TxStatus           = (uint32_t)&Tx_Stat[0];
 | 
						|
    LPC_EMAC->TxDescriptorNumber = EMAC_NUM_TX_FRAG - 1;
 | 
						|
 | 
						|
    /* Tx Descriptors Point to 0 */
 | 
						|
    LPC_EMAC->TxProduceIndex  = 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*--------------------------- write_PHY -------------------------------------*/
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       Write value to PHY device
 | 
						|
 * @param[in]   PhyReg: PHY Register address
 | 
						|
 * @param[in]   Value:  Value to write
 | 
						|
 * @return      0 - if success
 | 
						|
 *              1 - if fail
 | 
						|
 ***********************************************************************/
 | 
						|
static int32_t write_PHY (uint32_t PhyReg, uint16_t Value)
 | 
						|
{
 | 
						|
    /* Write a data 'Value' to PHY register 'PhyReg'. */
 | 
						|
    uint32_t tout;
 | 
						|
 | 
						|
    LPC_EMAC->MADR = EMAC_DEF_ADR | PhyReg;
 | 
						|
    LPC_EMAC->MWTD = Value;
 | 
						|
 | 
						|
    /* Wait until operation completed */
 | 
						|
    tout = 0;
 | 
						|
    for (tout = 0; tout < EMAC_MII_WR_TOUT; tout++) {
 | 
						|
        if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0) {
 | 
						|
            return (0);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    // Time out!
 | 
						|
    return (-1);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*--------------------------- read_PHY --------------------------------------*/
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       Read value from PHY device
 | 
						|
 * @param[in]   PhyReg: PHY Register address
 | 
						|
 * @return      0 - if success
 | 
						|
 *              1 - if fail
 | 
						|
 ***********************************************************************/
 | 
						|
static int32_t read_PHY (uint32_t PhyReg)
 | 
						|
{
 | 
						|
    /* Read a PHY register 'PhyReg'. */
 | 
						|
    uint32_t tout;
 | 
						|
 | 
						|
    LPC_EMAC->MADR = EMAC_DEF_ADR | PhyReg;
 | 
						|
    LPC_EMAC->MCMD = EMAC_MCMD_READ;
 | 
						|
 | 
						|
    /* Wait until operation completed */
 | 
						|
    tout = 0;
 | 
						|
    for (tout = 0; tout < EMAC_MII_RD_TOUT; tout++) {
 | 
						|
        if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0) {
 | 
						|
            LPC_EMAC->MCMD = 0;
 | 
						|
            return (LPC_EMAC->MRDD);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    // Time out!
 | 
						|
    return (-1);
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       Set Station MAC address for EMAC module
 | 
						|
 * @param[in]   abStationAddr Pointer to Station address that contains 6-bytes
 | 
						|
 *              of MAC address (should be in order from MAC Address 1 to MAC Address 6)
 | 
						|
 * @return      None
 | 
						|
 **********************************************************************/
 | 
						|
static void setEmacAddr(uint8_t abStationAddr[])
 | 
						|
{
 | 
						|
    /* Set the Ethernet MAC Address registers */
 | 
						|
    LPC_EMAC->SA0 = ((uint32_t)abStationAddr[5] << 8) | (uint32_t)abStationAddr[4];
 | 
						|
    LPC_EMAC->SA1 = ((uint32_t)abStationAddr[3] << 8) | (uint32_t)abStationAddr[2];
 | 
						|
    LPC_EMAC->SA2 = ((uint32_t)abStationAddr[1] << 8) | (uint32_t)abStationAddr[0];
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       Calculates CRC code for number of bytes in the frame
 | 
						|
 * @param[in]   frame_no_fcs    Pointer to the first byte of the frame
 | 
						|
 * @param[in]   frame_len       length of the frame without the FCS
 | 
						|
 * @return      the CRC as a 32 bit integer
 | 
						|
 **********************************************************************/
 | 
						|
static int32_t emac_CRCCalc(uint8_t frame_no_fcs[], int32_t frame_len)
 | 
						|
{
 | 
						|
    int i;      // iterator
 | 
						|
    int j;      // another iterator
 | 
						|
    char byte;  // current byte
 | 
						|
    int crc;    // CRC result
 | 
						|
    int q0, q1, q2, q3; // temporary variables
 | 
						|
    crc = 0xFFFFFFFF;
 | 
						|
    for (i = 0; i < frame_len; i++) {
 | 
						|
        byte = *frame_no_fcs++;
 | 
						|
        for (j = 0; j < 2; j++) {
 | 
						|
            if (((crc >> 28) ^ (byte >> 3)) & 0x00000001) {
 | 
						|
                q3 = 0x04C11DB7;
 | 
						|
            } else {
 | 
						|
                q3 = 0x00000000;
 | 
						|
            }
 | 
						|
            if (((crc >> 29) ^ (byte >> 2)) & 0x00000001) {
 | 
						|
                q2 = 0x09823B6E;
 | 
						|
            } else {
 | 
						|
                q2 = 0x00000000;
 | 
						|
            }
 | 
						|
            if (((crc >> 30) ^ (byte >> 1)) & 0x00000001) {
 | 
						|
                q1 = 0x130476DC;
 | 
						|
            } else {
 | 
						|
                q1 = 0x00000000;
 | 
						|
            }
 | 
						|
            if (((crc >> 31) ^ (byte >> 0)) & 0x00000001) {
 | 
						|
                q0 = 0x2608EDB8;
 | 
						|
            } else {
 | 
						|
                q0 = 0x00000000;
 | 
						|
            }
 | 
						|
            crc = (crc << 4) ^ q3 ^ q2 ^ q1 ^ q0;
 | 
						|
            byte >>= 4;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return crc;
 | 
						|
}
 | 
						|
/* End of Private Functions --------------------------------------------------- */
 | 
						|
 | 
						|
 | 
						|
/* Public Functions ----------------------------------------------------------- */
 | 
						|
/** @addtogroup EMAC_Public_Functions
 | 
						|
 * @{
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       Initializes the EMAC peripheral according to the specified
 | 
						|
*               parameters in the EMAC_ConfigStruct.
 | 
						|
 * @param[in]   EMAC_ConfigStruct Pointer to a EMAC_CFG_Type structure
 | 
						|
*                    that contains the configuration information for the
 | 
						|
*                    specified EMAC peripheral.
 | 
						|
 * @return      None
 | 
						|
 *
 | 
						|
 * Note: This function will initialize EMAC module according to procedure below:
 | 
						|
 *  - Remove the soft reset condition from the MAC
 | 
						|
 *  - Configure the PHY via the MIIM interface of the MAC
 | 
						|
 *  - Select RMII mode
 | 
						|
 *  - Configure the transmit and receive DMA engines, including the descriptor arrays
 | 
						|
 *  - Configure the host registers (MAC1,MAC2 etc.) in the MAC
 | 
						|
 *  - Enable the receive and transmit data paths
 | 
						|
 *  In default state after initializing, only Rx Done and Tx Done interrupt are enabled,
 | 
						|
 *  all remain interrupts are disabled
 | 
						|
 *  (Ref. from LPC17xx UM)
 | 
						|
 **********************************************************************/
 | 
						|
Status EMAC_Init(EMAC_CFG_Type *EMAC_ConfigStruct)
 | 
						|
{
 | 
						|
    /* Initialize the EMAC Ethernet controller. */
 | 
						|
    int32_t regv,tout, tmp;
 | 
						|
 | 
						|
    /* Set up clock and power for Ethernet module */
 | 
						|
    CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCENET, ENABLE);
 | 
						|
 | 
						|
    /* Reset all EMAC internal modules */
 | 
						|
    LPC_EMAC->MAC1    = EMAC_MAC1_RES_TX | EMAC_MAC1_RES_MCS_TX | EMAC_MAC1_RES_RX |
 | 
						|
                    EMAC_MAC1_RES_MCS_RX | EMAC_MAC1_SIM_RES | EMAC_MAC1_SOFT_RES;
 | 
						|
 | 
						|
    LPC_EMAC->Command = EMAC_CR_REG_RES | EMAC_CR_TX_RES | EMAC_CR_RX_RES | EMAC_CR_PASS_RUNT_FRM;
 | 
						|
 | 
						|
    /* A short delay after reset. */
 | 
						|
    for (tout = 100; tout; tout--);
 | 
						|
 | 
						|
    /* Initialize MAC control registers. */
 | 
						|
    LPC_EMAC->MAC1 = EMAC_MAC1_PASS_ALL;
 | 
						|
    LPC_EMAC->MAC2 = EMAC_MAC2_CRC_EN | EMAC_MAC2_PAD_EN;
 | 
						|
    LPC_EMAC->MAXF = EMAC_ETH_MAX_FLEN;
 | 
						|
    /*
 | 
						|
     * Find the clock that close to desired target clock
 | 
						|
     */
 | 
						|
    tmp = SystemCoreClock / EMAC_MCFG_MII_MAXCLK;
 | 
						|
    for (tout = 0; tout < sizeof (EMAC_clkdiv); tout++){
 | 
						|
        if (EMAC_clkdiv[tout] >= tmp) break;
 | 
						|
    }
 | 
						|
    tout++;
 | 
						|
    // Write to MAC configuration register and reset
 | 
						|
    LPC_EMAC->MCFG = EMAC_MCFG_CLK_SEL(tout) | EMAC_MCFG_RES_MII;
 | 
						|
    // release reset
 | 
						|
    LPC_EMAC->MCFG &= ~(EMAC_MCFG_RES_MII);
 | 
						|
    LPC_EMAC->CLRT = EMAC_CLRT_DEF;
 | 
						|
    LPC_EMAC->IPGR = EMAC_IPGR_P2_DEF;
 | 
						|
 | 
						|
    /* Enable Reduced MII interface. */
 | 
						|
    LPC_EMAC->Command = EMAC_CR_RMII | EMAC_CR_PASS_RUNT_FRM;
 | 
						|
 | 
						|
    /* Reset Reduced MII Logic. */
 | 
						|
//  LPC_EMAC->SUPP = EMAC_SUPP_RES_RMII;
 | 
						|
 | 
						|
    for (tout = 100; tout; tout--);
 | 
						|
    LPC_EMAC->SUPP = 0;
 | 
						|
 | 
						|
    /* Put the DP83848C in reset mode */
 | 
						|
    write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_BMCR_RESET);
 | 
						|
 | 
						|
    /* Wait for hardware reset to end. */
 | 
						|
    for (tout = EMAC_PHY_RESP_TOUT; tout>=0; tout--) {
 | 
						|
        regv = read_PHY (EMAC_PHY_REG_BMCR);
 | 
						|
        if (!(regv & (EMAC_PHY_BMCR_RESET | EMAC_PHY_BMCR_POWERDOWN))) {
 | 
						|
            /* Reset complete, device not Power Down. */
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        if (tout == 0){
 | 
						|
            // Time out, return ERROR
 | 
						|
            return (ERROR);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // Set PHY mode
 | 
						|
    if (EMAC_SetPHYMode(EMAC_ConfigStruct->Mode) < 0){
 | 
						|
        return (ERROR);
 | 
						|
    }
 | 
						|
 | 
						|
    // Set EMAC address
 | 
						|
    setEmacAddr(EMAC_ConfigStruct->pbEMAC_Addr);
 | 
						|
 | 
						|
    /* Initialize Tx and Rx DMA Descriptors */
 | 
						|
    rx_descr_init ();
 | 
						|
    tx_descr_init ();
 | 
						|
 | 
						|
    // Set Receive Filter register: enable broadcast and multicast
 | 
						|
    LPC_EMAC->RxFilterCtrl = EMAC_RFC_MCAST_EN | EMAC_RFC_BCAST_EN | EMAC_RFC_PERFECT_EN;
 | 
						|
 | 
						|
    /* Enable Rx Done and Tx Done interrupt for EMAC */
 | 
						|
    LPC_EMAC->IntEnable = EMAC_INT_RX_DONE | EMAC_INT_TX_DONE;
 | 
						|
 | 
						|
    /* Reset all interrupts */
 | 
						|
    LPC_EMAC->IntClear  = 0xFFFF;
 | 
						|
 | 
						|
    /* Enable receive and transmit mode of MAC Ethernet core */
 | 
						|
    LPC_EMAC->Command  |= (EMAC_CR_RX_EN | EMAC_CR_TX_EN);
 | 
						|
    LPC_EMAC->MAC1     |= EMAC_MAC1_REC_EN;
 | 
						|
 | 
						|
    return SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       De-initializes the EMAC peripheral registers to their
 | 
						|
*                  default reset values.
 | 
						|
 * @param[in]   None
 | 
						|
 * @return      None
 | 
						|
 **********************************************************************/
 | 
						|
void EMAC_DeInit(void)
 | 
						|
{
 | 
						|
    // Disable all interrupt
 | 
						|
    LPC_EMAC->IntEnable = 0x00;
 | 
						|
    // Clear all pending interrupt
 | 
						|
    LPC_EMAC->IntClear = (0xFF) | (EMAC_INT_SOFT_INT | EMAC_INT_WAKEUP);
 | 
						|
 | 
						|
    /* TurnOff clock and power for Ethernet module */
 | 
						|
    CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCENET, DISABLE);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       Check specified PHY status in EMAC peripheral
 | 
						|
 * @param[in]   ulPHYState  Specified PHY Status Type, should be:
 | 
						|
 *                          - EMAC_PHY_STAT_LINK: Link Status
 | 
						|
 *                          - EMAC_PHY_STAT_SPEED: Speed Status
 | 
						|
 *                          - EMAC_PHY_STAT_DUP: Duplex Status
 | 
						|
 * @return      Status of specified PHY status (0 or 1).
 | 
						|
 *              (-1) if error.
 | 
						|
 *
 | 
						|
 * Note:
 | 
						|
 * For EMAC_PHY_STAT_LINK, return value:
 | 
						|
 * - 0: Link Down
 | 
						|
 * - 1: Link Up
 | 
						|
 * For EMAC_PHY_STAT_SPEED, return value:
 | 
						|
 * - 0: 10Mbps
 | 
						|
 * - 1: 100Mbps
 | 
						|
 * For EMAC_PHY_STAT_DUP, return value:
 | 
						|
 * - 0: Half-Duplex
 | 
						|
 * - 1: Full-Duplex
 | 
						|
 **********************************************************************/
 | 
						|
int32_t EMAC_CheckPHYStatus(uint32_t ulPHYState)
 | 
						|
{
 | 
						|
    int32_t regv, tmp;
 | 
						|
#ifdef MCB_LPC_1768
 | 
						|
    regv = read_PHY (EMAC_PHY_REG_STS);
 | 
						|
    switch(ulPHYState){
 | 
						|
    case EMAC_PHY_STAT_LINK:
 | 
						|
        tmp = (regv & EMAC_PHY_SR_LINK) ? 1 : 0;
 | 
						|
        break;
 | 
						|
    case EMAC_PHY_STAT_SPEED:
 | 
						|
        tmp = (regv & EMAC_PHY_SR_SPEED) ? 0 : 1;
 | 
						|
        break;
 | 
						|
    case EMAC_PHY_STAT_DUP:
 | 
						|
        tmp = (regv & EMAC_PHY_SR_FULL_DUP) ? 1 : 0;
 | 
						|
        break;
 | 
						|
#elif defined(IAR_LPC_1768)
 | 
						|
    /* Use IAR_LPC_1768 board:
 | 
						|
     * FSZ8721BL doesn't have Status Register
 | 
						|
     * so we read Basic Mode Status Register (0x01h) instead
 | 
						|
     */
 | 
						|
    regv = read_PHY (EMAC_PHY_REG_BMSR);
 | 
						|
    switch(ulPHYState){
 | 
						|
    case EMAC_PHY_STAT_LINK:
 | 
						|
        tmp = (regv & EMAC_PHY_BMSR_LINK_STATUS) ? 1 : 0;
 | 
						|
        break;
 | 
						|
    case EMAC_PHY_STAT_SPEED:
 | 
						|
        tmp = (regv & EMAC_PHY_SR_100_SPEED) ? 1 : 0;
 | 
						|
        break;
 | 
						|
    case EMAC_PHY_STAT_DUP:
 | 
						|
        tmp = (regv & EMAC_PHY_SR_FULL_DUP) ? 1 : 0;
 | 
						|
        break;
 | 
						|
#endif
 | 
						|
    default:
 | 
						|
        tmp = -1;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return (tmp);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       Set specified PHY mode in EMAC peripheral
 | 
						|
 * @param[in]   ulPHYMode   Specified PHY mode, should be:
 | 
						|
 *                          - EMAC_MODE_AUTO
 | 
						|
 *                          - EMAC_MODE_10M_FULL
 | 
						|
 *                          - EMAC_MODE_10M_HALF
 | 
						|
 *                          - EMAC_MODE_100M_FULL
 | 
						|
 *                          - EMAC_MODE_100M_HALF
 | 
						|
 * @return      Return (0) if no error, otherwise return (-1)
 | 
						|
 **********************************************************************/
 | 
						|
int32_t EMAC_SetPHYMode(uint32_t ulPHYMode)
 | 
						|
{
 | 
						|
    int32_t id1, id2, tout;
 | 
						|
 | 
						|
    /* Check if this is a DP83848C PHY. */
 | 
						|
    id1 = read_PHY (EMAC_PHY_REG_IDR1);
 | 
						|
    id2 = read_PHY (EMAC_PHY_REG_IDR2);
 | 
						|
 | 
						|
#ifdef MCB_LPC_1768
 | 
						|
    if (((id1 << 16) | (id2 & 0xFFF0)) == EMAC_DP83848C_ID) {
 | 
						|
        switch(ulPHYMode){
 | 
						|
        case EMAC_MODE_AUTO:
 | 
						|
            write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_AUTO_NEG);
 | 
						|
#elif defined(IAR_LPC_1768) /* Use IAR LPC1768 KickStart board */
 | 
						|
    if (((id1 << 16) | id2) == EMAC_KSZ8721BL_ID) {
 | 
						|
        /* Configure the PHY device */
 | 
						|
        switch(ulPHYMode){
 | 
						|
        case EMAC_MODE_AUTO:
 | 
						|
            /* Use auto-negotiation about the link speed. */
 | 
						|
            write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_AUTO_NEG);
 | 
						|
//          write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_BMCR_AN);
 | 
						|
#endif
 | 
						|
            /* Wait to complete Auto_Negotiation */
 | 
						|
            for (tout = EMAC_PHY_RESP_TOUT; tout>=0; tout--) {
 | 
						|
                
 | 
						|
            }
 | 
						|
            break;
 | 
						|
        case EMAC_MODE_10M_FULL:
 | 
						|
            /* Connect at 10MBit full-duplex */
 | 
						|
            write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_FULLD_10M);
 | 
						|
            break;
 | 
						|
        case EMAC_MODE_10M_HALF:
 | 
						|
            /* Connect at 10MBit half-duplex */
 | 
						|
            write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_HALFD_10M);
 | 
						|
            break;
 | 
						|
        case EMAC_MODE_100M_FULL:
 | 
						|
            /* Connect at 100MBit full-duplex */
 | 
						|
            write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_FULLD_100M);
 | 
						|
            break;
 | 
						|
        case EMAC_MODE_100M_HALF:
 | 
						|
            /* Connect at 100MBit half-duplex */
 | 
						|
            write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_HALFD_100M);
 | 
						|
            break;
 | 
						|
        default:
 | 
						|
            // un-supported
 | 
						|
            return (-1);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    // It's not correct module ID
 | 
						|
    else {
 | 
						|
        return (-1);
 | 
						|
    }
 | 
						|
 | 
						|
    // Update EMAC configuration with current PHY status
 | 
						|
    if (EMAC_UpdatePHYStatus() < 0){
 | 
						|
        return (-1);
 | 
						|
    }
 | 
						|
 | 
						|
    // Complete
 | 
						|
    return (0);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       Auto-Configures value for the EMAC configuration register to
 | 
						|
 *              match with current PHY mode
 | 
						|
 * @param[in]   None
 | 
						|
 * @return      Return (0) if no error, otherwise return (-1)
 | 
						|
 *
 | 
						|
 * Note: The EMAC configuration will be auto-configured:
 | 
						|
 *      - Speed mode.
 | 
						|
 *      - Half/Full duplex mode
 | 
						|
 **********************************************************************/
 | 
						|
int32_t EMAC_UpdatePHYStatus(void)
 | 
						|
{
 | 
						|
    int32_t regv, tout;
 | 
						|
 | 
						|
    /* Check the link status. */
 | 
						|
#ifdef MCB_LPC_1768
 | 
						|
    for (tout = EMAC_PHY_RESP_TOUT; tout>=0; tout--) {
 | 
						|
        regv = read_PHY (EMAC_PHY_REG_STS);
 | 
						|
        if (regv & EMAC_PHY_SR_LINK) {
 | 
						|
            /* Link is on. */
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        if (tout == 0){
 | 
						|
            // time out
 | 
						|
            return (-1);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    /* Configure Full/Half Duplex mode. */
 | 
						|
    if (regv & EMAC_PHY_SR_DUP) {
 | 
						|
    /* Full duplex is enabled. */
 | 
						|
            LPC_EMAC->MAC2    |= EMAC_MAC2_FULL_DUP;
 | 
						|
            LPC_EMAC->Command |= EMAC_CR_FULL_DUP;
 | 
						|
            LPC_EMAC->IPGT     = EMAC_IPGT_FULL_DUP;
 | 
						|
    } else {
 | 
						|
        /* Half duplex mode. */
 | 
						|
        LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP;
 | 
						|
    }
 | 
						|
    if (regv & EMAC_PHY_SR_SPEED) {
 | 
						|
    /* 10MBit mode. */
 | 
						|
        LPC_EMAC->SUPP = 0;
 | 
						|
    } else {
 | 
						|
        /* 100MBit mode. */
 | 
						|
        LPC_EMAC->SUPP = EMAC_SUPP_SPEED;
 | 
						|
    }
 | 
						|
#elif defined(IAR_LPC_1768)
 | 
						|
    for (tout = EMAC_PHY_RESP_TOUT; tout>=0; tout--) {
 | 
						|
        regv = read_PHY (EMAC_PHY_REG_BMSR);
 | 
						|
        if (regv & EMAC_PHY_BMSR_LINK_STATUS) {
 | 
						|
            /* Link is on. */
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        if (tout == 0){
 | 
						|
            // time out
 | 
						|
            return (-1);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* Configure Full/Half Duplex mode. */
 | 
						|
    if (regv & EMAC_PHY_SR_FULL_DUP) {
 | 
						|
        /* Full duplex is enabled. */
 | 
						|
        LPC_EMAC->MAC2    |= EMAC_MAC2_FULL_DUP;
 | 
						|
        LPC_EMAC->Command |= EMAC_CR_FULL_DUP;
 | 
						|
        LPC_EMAC->IPGT     = EMAC_IPGT_FULL_DUP;
 | 
						|
    } else {
 | 
						|
        /* Half duplex mode. */
 | 
						|
        LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Configure 100MBit/10MBit mode. */
 | 
						|
    if (!(regv & EMAC_PHY_SR_100_SPEED)) {
 | 
						|
        /* 10MBit mode. */
 | 
						|
        LPC_EMAC->SUPP = 0;
 | 
						|
    } else {
 | 
						|
        /* 100MBit mode. */
 | 
						|
        LPC_EMAC->SUPP = EMAC_SUPP_SPEED;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
    // Complete
 | 
						|
    return (0);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       Enable/Disable hash filter functionality for specified destination
 | 
						|
 *              MAC address in EMAC module
 | 
						|
 * @param[in]   dstMAC_addr     Pointer to the first MAC destination address, should
 | 
						|
 *                              be 6-bytes length, in order LSB to the MSB
 | 
						|
 * @param[in]   NewState        New State of this command, should be:
 | 
						|
 *                                  - ENABLE.
 | 
						|
 *                                  - DISABLE.
 | 
						|
 * @return      None
 | 
						|
 *
 | 
						|
 * Note:
 | 
						|
 * The standard Ethernet cyclic redundancy check (CRC) function is calculated from
 | 
						|
 * the 6 byte destination address in the Ethernet frame (this CRC is calculated
 | 
						|
 * anyway as part of calculating the CRC of the whole frame), then bits [28:23] out of
 | 
						|
 * the 32 bits CRC result are taken to form the hash. The 6 bit hash is used to access
 | 
						|
 * the hash table: it is used as an index in the 64 bit HashFilter register that has been
 | 
						|
 * programmed with accept values. If the selected accept value is 1, the frame is
 | 
						|
 * accepted.
 | 
						|
 **********************************************************************/
 | 
						|
void EMAC_SetHashFilter(uint8_t dstMAC_addr[], FunctionalState NewState)
 | 
						|
{
 | 
						|
    uint32_t *pReg;
 | 
						|
    uint32_t tmp;
 | 
						|
    int32_t crc;
 | 
						|
 | 
						|
    // Calculate the CRC from the destination MAC address
 | 
						|
    crc = emac_CRCCalc(dstMAC_addr, 6);
 | 
						|
    // Extract the value from CRC to get index value for hash filter table
 | 
						|
    crc = (crc >> 23) & 0x3F;
 | 
						|
 | 
						|
    pReg = (crc > 31) ? ((uint32_t *)&LPC_EMAC->HashFilterH) \
 | 
						|
                                : ((uint32_t *)&LPC_EMAC->HashFilterL);
 | 
						|
    tmp = (crc > 31) ? (crc - 32) : crc;
 | 
						|
    if (NewState == ENABLE) {
 | 
						|
        (*pReg) |= (1UL << tmp);
 | 
						|
    } else {
 | 
						|
        (*pReg) &= ~(1UL << tmp);
 | 
						|
    }
 | 
						|
    // Enable Rx Filter
 | 
						|
    LPC_EMAC->Command &= ~EMAC_CR_PASS_RX_FILT;
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       Enable/Disable Filter mode for each specified type EMAC peripheral
 | 
						|
 * @param[in]   ulFilterMode    Filter mode, should be:
 | 
						|
 *                              - EMAC_RFC_UCAST_EN: all frames of unicast types
 | 
						|
 *                              will be accepted
 | 
						|
 *                              - EMAC_RFC_BCAST_EN: broadcast frame will be
 | 
						|
 *                              accepted
 | 
						|
 *                              - EMAC_RFC_MCAST_EN: all frames of multicast
 | 
						|
 *                              types will be accepted
 | 
						|
 *                              - EMAC_RFC_UCAST_HASH_EN: The imperfect hash
 | 
						|
 *                              filter will be applied to unicast addresses
 | 
						|
 *                              - EMAC_RFC_MCAST_HASH_EN: The imperfect hash
 | 
						|
 *                              filter will be applied to multicast addresses
 | 
						|
 *                              - EMAC_RFC_PERFECT_EN: the destination address
 | 
						|
 *                              will be compared with the 6 byte station address
 | 
						|
 *                              programmed in the station address by the filter
 | 
						|
 *                              - EMAC_RFC_MAGP_WOL_EN: the result of the magic
 | 
						|
 *                              packet filter will generate a WoL interrupt when
 | 
						|
 *                              there is a match
 | 
						|
 *                              - EMAC_RFC_PFILT_WOL_EN: the result of the perfect address
 | 
						|
 *                              matching filter and the imperfect hash filter will
 | 
						|
 *                              generate a WoL interrupt when there is a match
 | 
						|
 * @param[in]   NewState    New State of this command, should be:
 | 
						|
 *                              - ENABLE
 | 
						|
 *                              - DISABLE
 | 
						|
 * @return      None
 | 
						|
 **********************************************************************/
 | 
						|
void EMAC_SetFilterMode(uint32_t ulFilterMode, FunctionalState NewState)
 | 
						|
{
 | 
						|
    if (NewState == ENABLE){
 | 
						|
        LPC_EMAC->RxFilterCtrl |= ulFilterMode;
 | 
						|
    } else {
 | 
						|
        LPC_EMAC->RxFilterCtrl &= ~ulFilterMode;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       Get status of Wake On LAN Filter for each specified
 | 
						|
 *              type in EMAC peripheral, clear this status if it is set
 | 
						|
 * @param[in]   ulWoLMode   WoL Filter mode, should be:
 | 
						|
 *                              - EMAC_WOL_UCAST: unicast frames caused WoL
 | 
						|
 *                              - EMAC_WOL_UCAST: broadcast frame caused WoL
 | 
						|
 *                              - EMAC_WOL_MCAST: multicast frame caused WoL
 | 
						|
 *                              - EMAC_WOL_UCAST_HASH: unicast frame that passes the
 | 
						|
 *                              imperfect hash filter caused WoL
 | 
						|
 *                              - EMAC_WOL_MCAST_HASH: multicast frame that passes the
 | 
						|
 *                              imperfect hash filter caused WoL
 | 
						|
 *                              - EMAC_WOL_PERFECT:perfect address matching filter
 | 
						|
 *                              caused WoL
 | 
						|
 *                              - EMAC_WOL_RX_FILTER: the receive filter caused WoL
 | 
						|
 *                              - EMAC_WOL_MAG_PACKET: the magic packet filter caused WoL
 | 
						|
 * @return      SET/RESET
 | 
						|
 **********************************************************************/
 | 
						|
FlagStatus EMAC_GetWoLStatus(uint32_t ulWoLMode)
 | 
						|
{
 | 
						|
    if (LPC_EMAC->RxFilterWoLStatus & ulWoLMode) {
 | 
						|
        LPC_EMAC->RxFilterWoLClear = ulWoLMode;
 | 
						|
        return SET;
 | 
						|
    } else {
 | 
						|
        return RESET;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       Write data to Tx packet data buffer at current index due to
 | 
						|
 *              TxProduceIndex
 | 
						|
 * @param[in]   pDataStruct     Pointer to a EMAC_PACKETBUF_Type structure
 | 
						|
 *                          data that contain specified information about
 | 
						|
 *                          Packet data buffer.
 | 
						|
 * @return      None
 | 
						|
 **********************************************************************/
 | 
						|
void EMAC_WritePacketBuffer(EMAC_PACKETBUF_Type *pDataStruct)
 | 
						|
{
 | 
						|
    uint32_t idx,len;
 | 
						|
    uint32_t *sp,*dp;
 | 
						|
 | 
						|
    idx = LPC_EMAC->TxProduceIndex;
 | 
						|
    sp  = (uint32_t *)pDataStruct->pbDataBuf;
 | 
						|
    dp  = (uint32_t *)Tx_Desc[idx].Packet;
 | 
						|
    /* Copy frame data to EMAC packet buffers. */
 | 
						|
    for (len = (pDataStruct->ulDataLen + 3) >> 2; len; len--) {
 | 
						|
        *dp++ = *sp++;
 | 
						|
    }
 | 
						|
    Tx_Desc[idx].Ctrl = (pDataStruct->ulDataLen - 1) | (EMAC_TCTRL_INT | EMAC_TCTRL_LAST);
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       Read data from Rx packet data buffer at current index due
 | 
						|
 *              to RxConsumeIndex
 | 
						|
 * @param[in]   pDataStruct     Pointer to a EMAC_PACKETBUF_Type structure
 | 
						|
 *                          data that contain specified information about
 | 
						|
 *                          Packet data buffer.
 | 
						|
 * @return      None
 | 
						|
 **********************************************************************/
 | 
						|
void EMAC_ReadPacketBuffer(EMAC_PACKETBUF_Type *pDataStruct)
 | 
						|
{
 | 
						|
    uint32_t idx, len;
 | 
						|
    uint32_t *dp, *sp;
 | 
						|
 | 
						|
    idx = LPC_EMAC->RxConsumeIndex;
 | 
						|
    dp = (uint32_t *)pDataStruct->pbDataBuf;
 | 
						|
    sp = (uint32_t *)Rx_Desc[idx].Packet;
 | 
						|
 | 
						|
    if (pDataStruct->pbDataBuf != NULL) {
 | 
						|
        for (len = (pDataStruct->ulDataLen + 3) >> 2; len; len--) {
 | 
						|
            *dp++ = *sp++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       Enable/Disable interrupt for each type in EMAC
 | 
						|
 * @param[in]   ulIntType   Interrupt Type, should be:
 | 
						|
 *                          - EMAC_INT_RX_OVERRUN: Receive Overrun
 | 
						|
 *                          - EMAC_INT_RX_ERR: Receive Error
 | 
						|
 *                          - EMAC_INT_RX_FIN: Receive Descriptor Finish
 | 
						|
 *                          - EMAC_INT_RX_DONE: Receive Done
 | 
						|
 *                          - EMAC_INT_TX_UNDERRUN: Transmit Under-run
 | 
						|
 *                          - EMAC_INT_TX_ERR: Transmit Error
 | 
						|
 *                          - EMAC_INT_TX_FIN: Transmit descriptor finish
 | 
						|
 *                          - EMAC_INT_TX_DONE: Transmit Done
 | 
						|
 *                          - EMAC_INT_SOFT_INT: Software interrupt
 | 
						|
 *                          - EMAC_INT_WAKEUP: Wakeup interrupt
 | 
						|
 * @param[in]   NewState    New State of this function, should be:
 | 
						|
 *                          - ENABLE.
 | 
						|
 *                          - DISABLE.
 | 
						|
 * @return      None
 | 
						|
 **********************************************************************/
 | 
						|
void EMAC_IntCmd(uint32_t ulIntType, FunctionalState NewState)
 | 
						|
{
 | 
						|
    if (NewState == ENABLE) {
 | 
						|
        LPC_EMAC->IntEnable |= ulIntType;
 | 
						|
    } else {
 | 
						|
        LPC_EMAC->IntEnable &= ~(ulIntType);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       Check whether if specified interrupt flag is set or not
 | 
						|
 *              for each interrupt type in EMAC and clear interrupt pending
 | 
						|
 *              if it is set.
 | 
						|
 * @param[in]   ulIntType   Interrupt Type, should be:
 | 
						|
 *                          - EMAC_INT_RX_OVERRUN: Receive Overrun
 | 
						|
 *                          - EMAC_INT_RX_ERR: Receive Error
 | 
						|
 *                          - EMAC_INT_RX_FIN: Receive Descriptor Finish
 | 
						|
 *                          - EMAC_INT_RX_DONE: Receive Done
 | 
						|
 *                          - EMAC_INT_TX_UNDERRUN: Transmit Under-run
 | 
						|
 *                          - EMAC_INT_TX_ERR: Transmit Error
 | 
						|
 *                          - EMAC_INT_TX_FIN: Transmit descriptor finish
 | 
						|
 *                          - EMAC_INT_TX_DONE: Transmit Done
 | 
						|
 *                          - EMAC_INT_SOFT_INT: Software interrupt
 | 
						|
 *                          - EMAC_INT_WAKEUP: Wakeup interrupt
 | 
						|
 * @return      New state of specified interrupt (SET or RESET)
 | 
						|
 **********************************************************************/
 | 
						|
IntStatus EMAC_IntGetStatus(uint32_t ulIntType)
 | 
						|
{
 | 
						|
    if (LPC_EMAC->IntStatus & ulIntType) {
 | 
						|
        LPC_EMAC->IntClear = ulIntType;
 | 
						|
        return SET;
 | 
						|
    } else {
 | 
						|
        return RESET;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       Check whether if the current RxConsumeIndex is not equal to the
 | 
						|
 *              current RxProduceIndex.
 | 
						|
 * @param[in]   None
 | 
						|
 * @return      TRUE if they're not equal, otherwise return FALSE
 | 
						|
 *
 | 
						|
 * Note: In case the RxConsumeIndex is not equal to the RxProduceIndex,
 | 
						|
 * it means there're available data has been received. They should be read
 | 
						|
 * out and released the Receive Data Buffer by updating the RxConsumeIndex value.
 | 
						|
 **********************************************************************/
 | 
						|
Bool EMAC_CheckReceiveIndex(void)
 | 
						|
{
 | 
						|
    if (LPC_EMAC->RxConsumeIndex != LPC_EMAC->RxProduceIndex) {
 | 
						|
        return TRUE;
 | 
						|
    } else {
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       Check whether if the current TxProduceIndex is not equal to the
 | 
						|
 *              current RxProduceIndex - 1.
 | 
						|
 * @param[in]   None
 | 
						|
 * @return      TRUE if they're not equal, otherwise return FALSE
 | 
						|
 *
 | 
						|
 * Note: In case the RxConsumeIndex is equal to the RxProduceIndex - 1,
 | 
						|
 * it means the transmit buffer is available and data can be written to transmit
 | 
						|
 * buffer to be sent.
 | 
						|
 **********************************************************************/
 | 
						|
Bool EMAC_CheckTransmitIndex(void)
 | 
						|
{
 | 
						|
    uint32_t tmp = LPC_EMAC->TxConsumeIndex;
 | 
						|
    if (LPC_EMAC->TxProduceIndex == ( tmp - 1 ))
 | 
						|
    {
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
    else if( ( tmp == 0 ) && ( LPC_EMAC->TxProduceIndex == ( EMAC_NUM_TX_FRAG - 1 ) ) )
 | 
						|
    {
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        return TRUE;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       Get current status value of receive data (due to RxConsumeIndex)
 | 
						|
 * @param[in]   ulRxStatType    Received Status type, should be one of following:
 | 
						|
 *                          - EMAC_RINFO_CTRL_FRAME: Control Frame
 | 
						|
 *                          - EMAC_RINFO_VLAN: VLAN Frame
 | 
						|
 *                          - EMAC_RINFO_FAIL_FILT: RX Filter Failed
 | 
						|
 *                          - EMAC_RINFO_MCAST: Multicast Frame
 | 
						|
 *                          - EMAC_RINFO_BCAST: Broadcast Frame
 | 
						|
 *                          - EMAC_RINFO_CRC_ERR: CRC Error in Frame
 | 
						|
 *                          - EMAC_RINFO_SYM_ERR: Symbol Error from PHY
 | 
						|
 *                          - EMAC_RINFO_LEN_ERR: Length Error
 | 
						|
 *                          - EMAC_RINFO_RANGE_ERR: Range error(exceeded max size)
 | 
						|
 *                          - EMAC_RINFO_ALIGN_ERR: Alignment error
 | 
						|
 *                          - EMAC_RINFO_OVERRUN: Receive overrun
 | 
						|
 *                          - EMAC_RINFO_NO_DESCR: No new Descriptor available
 | 
						|
 *                          - EMAC_RINFO_LAST_FLAG: last Fragment in Frame
 | 
						|
 *                          - EMAC_RINFO_ERR: Error Occurred (OR of all error)
 | 
						|
 * @return      Current value of receive data (due to RxConsumeIndex)
 | 
						|
 **********************************************************************/
 | 
						|
FlagStatus EMAC_CheckReceiveDataStatus(uint32_t ulRxStatType)
 | 
						|
{
 | 
						|
    uint32_t idx;
 | 
						|
    idx = LPC_EMAC->RxConsumeIndex;
 | 
						|
    return (((Rx_Stat[idx].Info) & ulRxStatType) ? SET : RESET);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       Get size of current Received data in received buffer (due to
 | 
						|
 *              RxConsumeIndex)
 | 
						|
 * @param[in]   None
 | 
						|
 * @return      Size of received data
 | 
						|
 **********************************************************************/
 | 
						|
uint32_t EMAC_GetReceiveDataSize(void)
 | 
						|
{
 | 
						|
    uint32_t idx;
 | 
						|
    idx =LPC_EMAC->RxConsumeIndex;
 | 
						|
    return ((Rx_Stat[idx].Info) & EMAC_RINFO_SIZE);
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       Increase the RxConsumeIndex (after reading the Receive buffer
 | 
						|
 *              to release the Receive buffer) and wrap-around the index if
 | 
						|
 *              it reaches the maximum Receive Number
 | 
						|
 * @param[in]   None
 | 
						|
 * @return      None
 | 
						|
 **********************************************************************/
 | 
						|
void EMAC_UpdateRxConsumeIndex(void)
 | 
						|
{
 | 
						|
    // Get current Rx consume index
 | 
						|
    uint32_t idx = LPC_EMAC->RxConsumeIndex;
 | 
						|
 | 
						|
    /* Release frame from EMAC buffer */
 | 
						|
    if (++idx == EMAC_NUM_RX_FRAG) idx = 0;
 | 
						|
    LPC_EMAC->RxConsumeIndex = idx;
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
 * @brief       Increase the TxProduceIndex (after writting to the Transmit buffer
 | 
						|
 *              to enable the Transmit buffer) and wrap-around the index if
 | 
						|
 *              it reaches the maximum Transmit Number
 | 
						|
 * @param[in]   None
 | 
						|
 * @return      None
 | 
						|
 **********************************************************************/
 | 
						|
void EMAC_UpdateTxProduceIndex(void)
 | 
						|
{
 | 
						|
    // Get current Tx produce index
 | 
						|
    uint32_t idx = LPC_EMAC->TxProduceIndex;
 | 
						|
 | 
						|
    /* Start frame transmission */
 | 
						|
    if (++idx == EMAC_NUM_TX_FRAG) idx = 0;
 | 
						|
    LPC_EMAC->TxProduceIndex = idx;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * @}
 | 
						|
 */
 | 
						|
 | 
						|
#endif /* _EMAC */
 | 
						|
 | 
						|
/**
 | 
						|
 * @}
 | 
						|
 */
 | 
						|
 | 
						|
/* --------------------------------- End Of File ------------------------------ */
 |