123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963 |
- /**********************************************************************
- * $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 ------------------------------ */
|