Beispiel #1
0
/* Low level init of the MAC and PHY */
STATIC err_t low_level_init(struct netif *netif)
{
	lpc_enetdata_t *lpc_enetif = netif->state;
	err_t err = ERR_OK;

#if defined(USE_RMII)
	Chip_ENET_Init(LPC_ETHERNET, true);

#else
	Chip_ENET_Init(LPC_ETHERNET, false);
#endif

	/* Initialize the PHY */
	Chip_ENET_SetupMII(LPC_ETHERNET, Chip_ENET_FindMIIDiv(LPC_ETHERNET, 2500000), LPC_PHYDEF_PHYADDR);
#if defined(USE_RMII)
	if (lpc_phy_init(true, msDelay) != SUCCESS) {
		return ERROR;
	}
#else
	if (lpc_phy_init(false, msDelay) != SUCCESS) {
		return ERROR;
	}
#endif

	/* Save station address */
	Chip_ENET_SetADDR(LPC_ETHERNET, netif->hwaddr);

	/* Setup transmit and receive descriptors */
	if (lpc_tx_setup(lpc_enetif) != ERR_OK) {
		return ERR_BUF;
	}
	if (lpc_rx_setup(lpc_enetif) != ERR_OK) {
		return ERR_BUF;
	}

	/* Enable packet reception */
#if IP_SOF_BROADCAST_RECV
	Chip_ENET_EnableRXFilter(LPC_ETHERNET, ENET_RXFILTERCTRL_APE | ENET_RXFILTERCTRL_ABE);
#else
	Chip_ENET_EnableRXFilter(ENET_RXFILTERCTRL_APE);
#endif

	/* Clear and enable rx/tx interrupts */
	Chip_ENET_EnableInt(LPC_ETHERNET, RXINTGROUP | TXINTGROUP);

	/* Enable RX and TX */
	Chip_ENET_TXEnable(LPC_ETHERNET);
	Chip_ENET_RXEnable(LPC_ETHERNET);

	return err;
}
Beispiel #2
0
/** \brief  Low level init of the MAC and PHY.
 *
 *  \param[in]      netif  Pointer to LWIP netif structure
 */
static err_t low_level_init(struct netif *netif)
{
	struct lpc_enetdata *lpc_enetif = netif->state;
	err_t err = ERR_OK;

	LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
    				("Enable PCONP_PCENET\r\n"));
	/* Enable MII clocking */
	LPC_SC->PCONP |= CLKPWR_PCONP_PCENET;

#if defined(TARGET_LPC1768)
	LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
    				("enable P1 ethernet pins\r\n"));
	LPC_PINCON->PINSEL2 = 0x50150105;                  /* Enable P1 Ethernet Pins. */
	LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & ~0x0000000F) | 0x00000005;
#elif defined(TARGET_LPC4088)
  LPC_IOCON->P1_0  &= ~0x07;    /*  ENET I/O config */
  LPC_IOCON->P1_0  |= 0x01;     /* ENET_TXD0 */
  LPC_IOCON->P1_1  &= ~0x07;
  LPC_IOCON->P1_1  |= 0x01;     /* ENET_TXD1 */
  LPC_IOCON->P1_4  &= ~0x07;
  LPC_IOCON->P1_4  |= 0x01;     /* ENET_TXEN */
  LPC_IOCON->P1_8  &= ~0x07;
  LPC_IOCON->P1_8  |= 0x01;     /* ENET_CRS */
  LPC_IOCON->P1_9  &= ~0x07;
  LPC_IOCON->P1_9  |= 0x01;     /* ENET_RXD0 */
  LPC_IOCON->P1_10 &= ~0x07;
  LPC_IOCON->P1_10 |= 0x01;     /* ENET_RXD1 */
  LPC_IOCON->P1_14 &= ~0x07;
  LPC_IOCON->P1_14 |= 0x01;     /* ENET_RX_ER */
  LPC_IOCON->P1_15 &= ~0x07;
  LPC_IOCON->P1_15 |= 0x01;     /* ENET_REF_CLK */
  LPC_IOCON->P1_16 &= ~0x07;    /* ENET/PHY I/O config */
  LPC_IOCON->P1_16 |= 0x01;     /* ENET_MDC */
  LPC_IOCON->P1_17 &= ~0x07;
  LPC_IOCON->P1_17 |= 0x01;     /* ENET_MDIO */
#endif
	
	LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
    				("reset all MAC logic\r\n"));
	/* Reset all MAC logic */
	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;
	osDelay(10);

	LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
    				("MAC initialization\r\n"));
	/* Initial MAC initialization */
	LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
    				("MAC initialization:PASS_ALL\r\n"));
	LPC_EMAC->MAC1 = EMAC_MAC1_PASS_ALL;
	LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
    				("MAC initialization:CRC EN\r\n"));		
	LPC_EMAC->MAC2 = EMAC_MAC2_CRC_EN | EMAC_MAC2_PAD_EN |
		EMAC_MAC2_VLAN_PAD_EN;
	LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
    				("MAC initialization:MAXF\r\n"));		
	LPC_EMAC->MAXF = EMAC_ETH_MAX_FLEN;
	
	LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
    				("RMII set to lowest clock rate\r\n"));
	/* Set RMII management clock rate to lowest speed */
	LPC_EMAC->MCFG = EMAC_MCFG_CLK_SEL(11) | EMAC_MCFG_RES_MII;
	LPC_EMAC->MCFG &= ~EMAC_MCFG_RES_MII;

	LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
    				("maximum number of retries set\r\n"));
	/* Maximum number of retries, 0x37 collision window, gap */
	LPC_EMAC->CLRT = EMAC_CLRT_DEF;
	LPC_EMAC->IPGR = EMAC_IPGR_P1_DEF | EMAC_IPGR_P2_DEF;

#if LPC_EMAC_RMII
	LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
    				("RMII Setup\r\n"));
	/* RMII setup */
	LPC_EMAC->Command = EMAC_CR_PASS_RUNT_FRM | EMAC_CR_RMII;
#else
	/* MII setup */
	LPC_EMAC->CR = EMAC_CR_PASS_RUNT_FRM;
#endif

	/* Initialize the PHY and reset */
	LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
    				("initialize the phy and reset\r\n"));
    err = lpc_phy_init(netif, LPC_EMAC_RMII);
	if (err != ERR_OK) {
 		LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
    				("error in lpc_phy_init %d\r\n", err));
 		return err;
 	}

	LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
    				("saving station address\r\n"));
	/* Save station address */
	LPC_EMAC->SA2 = (u32_t) netif->hwaddr[0] |
		(((u32_t) netif->hwaddr[1]) << 8);
	LPC_EMAC->SA1 = (u32_t) netif->hwaddr[2] |
		(((u32_t) netif->hwaddr[3]) << 8);
	LPC_EMAC->SA0 = (u32_t) netif->hwaddr[4] |
		(((u32_t) netif->hwaddr[5]) << 8);

	LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
    				("setup tx and rx descriptors\r\n"));
	/* Setup transmit and receive descriptors */
	if (lpc_tx_setup(lpc_enetif) != ERR_OK) {
		LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
    				("error on tx setup\r\n"));
		return ERR_BUF;
	}
	if (lpc_rx_setup(lpc_enetif) != ERR_OK) {
		LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
    				("error on rx setup\r\n"));
		return ERR_BUF;
	}

	/* Enable packet reception */
#if IP_SOF_BROADCAST_RECV
	LPC_EMAC->RxFilterCtrl = EMAC_RFC_PERFECT_EN | EMAC_RFC_BCAST_EN | EMAC_RFC_MCAST_EN;
#else
	LPC_EMAC->RxFilterCtrl = EMAC_RFC_PERFECT_EN;
#endif
	LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
    				("enable tx/rx interrupts\r\n"));
	/* Clear and enable rx/tx interrupts */
	LPC_EMAC->IntClear = 0xFFFF;
	LPC_EMAC->IntEnable = RXINTGROUP | TXINTGROUP;

	LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
    				("Enable tx/rx\r\n"));
	/* Enable RX and TX */
	LPC_EMAC->Command |= EMAC_CR_RX_EN | EMAC_CR_TX_EN;
	LPC_EMAC->MAC1 |= EMAC_MAC1_REC_EN;

	LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
    				("return from low_level_init error:%d\r\n", err));
	return err;
}
Beispiel #3
0
/** \brief  Allocates a pbuf and returns the data from the incoming packet.
 *
 *  \param[in] netif the lwip network interface structure for this lpc_enetif
 *  \return a pbuf filled with the received packet (including MAC header)
 *         NULL on memory error
 */
static struct pbuf *lpc_low_level_input(struct netif *netif)
{
	struct lpc_enetdata *lpc_enetif = netif->state;
	struct pbuf *p = NULL;
	u32_t idx, length;
	u16_t origLength;

#ifdef LOCK_RX_THREAD
#if NO_SYS == 0
	/* Get exclusive access */
	sys_mutex_lock(&lpc_enetif->TXLockMutex);
#endif
#endif

	/* Monitor RX overrun status. This should never happen unless
	   (possibly) the internal bus is behing held up by something.
	   Unless your system is running at a very low clock speed or
	   there are possibilities that the internal buses may be held
	   up for a long time, this can probably safely be removed. */
	if (LPC_EMAC->IntStatus & EMAC_INT_RX_OVERRUN) {
		LINK_STATS_INC(link.err);
		LINK_STATS_INC(link.drop);

		/* Temporarily disable RX */
		LPC_EMAC->MAC1 &= ~EMAC_MAC1_REC_EN;

		/* Reset the RX side */
		LPC_EMAC->MAC1 |= EMAC_MAC1_RES_RX;
		LPC_EMAC->IntClear = EMAC_INT_RX_OVERRUN;

		/* De-allocate all queued RX pbufs */
		for (idx = 0; idx < LPC_NUM_BUFF_RXDESCS; idx++) {
			if (lpc_enetif->rxb[idx] != NULL) {
				pbuf_free(lpc_enetif->rxb[idx]);
				lpc_enetif->rxb[idx] = NULL;
			}
		}

		/* Start RX side again */
		lpc_rx_setup(lpc_enetif);

		/* Re-enable RX */
		LPC_EMAC->MAC1 |= EMAC_MAC1_REC_EN;

#ifdef LOCK_RX_THREAD
#if NO_SYS == 0
		sys_mutex_unlock(&lpc_enetif->TXLockMutex);
#endif
#endif

		return NULL;
	}

	/* Determine if a frame has been received */
	length = 0;
	idx = LPC_EMAC->RxConsumeIndex;
	if (LPC_EMAC->RxProduceIndex != idx) {
		/* Handle errors */
		if (lpc_enetif->prxs[idx].statusinfo & (EMAC_RINFO_CRC_ERR |
			EMAC_RINFO_SYM_ERR | EMAC_RINFO_ALIGN_ERR | EMAC_RINFO_LEN_ERR)) {
#if LINK_STATS
			if (lpc_enetif->prxs[idx].statusinfo & (EMAC_RINFO_CRC_ERR |
				EMAC_RINFO_SYM_ERR | EMAC_RINFO_ALIGN_ERR))
				LINK_STATS_INC(link.chkerr);
			if (lpc_enetif->prxs[idx].statusinfo & EMAC_RINFO_LEN_ERR)
				LINK_STATS_INC(link.lenerr);
#endif

			/* Drop the frame */
			LINK_STATS_INC(link.drop);

			/* Re-queue the pbuf for receive */
			lpc_enetif->rx_free_descs++;
			p = lpc_enetif->rxb[idx];
			lpc_enetif->rxb[idx] = NULL;
			lpc_rxqueue_pbuf(lpc_enetif, p);

			LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
				("lpc_low_level_input: Packet dropped with errors (0x%x)\r\n",
				lpc_enetif->prxs[idx].statusinfo));

			p = NULL;
		} else {
			/* A packet is waiting, get length */
			length = (lpc_enetif->prxs[idx].statusinfo & 0x7FF) + 1;

			/* Zero-copy */
			p = lpc_enetif->rxb[idx];
			origLength = p->len;
			p->len = (u16_t) length;

			/* Free pbuf from descriptor */
			lpc_enetif->rxb[idx] = NULL;
			lpc_enetif->rx_free_descs++;

			/* Attempt to queue new buffer(s) */
			if (lpc_rx_queue(lpc_enetif->netif) == 0) {
    			/* Drop the frame due to OOM. */
    			LINK_STATS_INC(link.drop);

    			/* Re-queue the pbuf for receive */
    			p->len = origLength;
    			lpc_rxqueue_pbuf(lpc_enetif, p);

    			LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
    				("lpc_low_level_input: Packet index %d dropped for OOM\r\n",
    				idx));
			
#ifdef LOCK_RX_THREAD
#if NO_SYS == 0
        		sys_mutex_unlock(&lpc_enetif->TXLockMutex);
#endif
#endif

		        return NULL;
			}

			LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
				("lpc_low_level_input: Packet received: %p, size %d (index=%d)\r\n",
				p, length, idx));

			/* Save size */
			p->tot_len = (u16_t) length;
			LINK_STATS_INC(link.recv);
		}
	}

#ifdef LOCK_RX_THREAD
#if NO_SYS == 0
	sys_mutex_unlock(&lpc_enetif->TXLockMutex);
#endif
#endif

	return p;
}
/* Low level init of the MAC and PHY */
static err_t low_level_init(struct netif *netif)
{
	struct lpc_enetdata *lpc_netifdata = netif->state;

	/* Initialize via Chip ENET function */
	Chip_ENET_Init(LPC_ETHERNET);

	/* Save MAC address */
	Chip_ENET_SetADDR(LPC_ETHERNET, netif->hwaddr);

	/* Initial MAC configuration for checksum offload, full duplex,
	   100Mbps, disable receive own in half duplex, inter-frame gap
	   of 64-bits */
	LPC_ETHERNET->MAC_CONFIG = MAC_CFG_BL(0) | MAC_CFG_IPC | MAC_CFG_DM |
							   MAC_CFG_DO | MAC_CFG_FES | MAC_CFG_PS | MAC_CFG_IFG(3);

	/* Setup filter */
#if IP_SOF_BROADCAST_RECV
	LPC_ETHERNET->MAC_FRAME_FILTER = MAC_FF_PR | MAC_FF_RA;
#else
	LPC_ETHERNET->MAC_FRAME_FILTER = 0;	/* Only matching MAC address */
#endif

	/* Initialize the PHY */
#if defined(USE_RMII)
	if (lpc_phy_init(true, msDelay) != SUCCESS) {
		return ERROR;
	}

	intMask = RDES_CE | RDES_DE | RDES_RE | RDES_RWT | RDES_LC | RDES_OE |
			  RDES_SAF | RDES_AFM;
#else
	if (lpc_phy_init(false, msDelay) != SUCCESS) {
		return ERROR;
	}

	intMask = RDES_CE | RDES_RE | RDES_RWT | RDES_LC | RDES_OE | RDES_SAF |
			  RDES_AFM;
#endif

	/* Setup transmit and receive descriptors */
	if (lpc_tx_setup(lpc_netifdata) != ERR_OK) {
		return ERR_BUF;
	}
	if (lpc_rx_setup(lpc_netifdata) != ERR_OK) {
		return ERR_BUF;
	}

	/* Flush transmit FIFO */
	LPC_ETHERNET->DMA_OP_MODE = DMA_OM_FTF;

	/* Setup DMA to flush receive FIFOs at 32 bytes, service TX FIFOs at
	   64 bytes */
	LPC_ETHERNET->DMA_OP_MODE |= DMA_OM_RTC(1) | DMA_OM_TTC(0);

	/* Clear all MAC interrupts */
	LPC_ETHERNET->DMA_STAT = DMA_ST_ALL;

	/* Enable MAC interrupts */
	LPC_ETHERNET->DMA_INT_EN =
#if NO_SYS == 1
		0;
#else
		DMA_IE_TIE | DMA_IE_OVE | DMA_IE_UNE | DMA_IE_RIE | DMA_IE_NIE |
		DMA_IE_AIE | DMA_IE_TUE | DMA_IE_RUE;
#endif

	/* Enable receive and transmit DMA processes */
	LPC_ETHERNET->DMA_OP_MODE |= DMA_OM_ST | DMA_OM_SR;

	/* Enable packet reception */
	LPC_ETHERNET->MAC_CONFIG |= MAC_CFG_RE | MAC_CFG_TE;

	/* Start receive polling */
	LPC_ETHERNET->DMA_REC_POLL_DEMAND = 1;

	return ERR_OK;
}
Beispiel #5
0
/** \brief  Low level init of the MAC and PHY.
 *
 *  \param[in]       netif  Pointer to LWIP netif structure
 *  \return          ERR_OK or error code
 */
static err_t low_level_init(struct netif *netif)
{
	struct lpc_enetdata *lpc_netifdata = netif->state;
	err_t err;
	s32_t timeout;

	/* Enable MAC clocking from same source as CPU */
	CGU_EntityConnect(CGU_CLKSRC_PLL1, CGU_PERIPHERAL_ETHERNET);

	/* Slightly different clocking for RMII and MII modes */
	CGU_EntityConnect(CGU_CLKSRC_ENET_TX_CLK, CGU_BASE_PHY_TX);
#if LPC_EMAC_RMII == 1
	/* RMII mode gets PHY RX clock from ENET_REF_CLK (same pin as
	   ENET_TX_CLK on the chip) */
	CGU_EntityConnect(CGU_CLKSRC_ENET_TX_CLK, CGU_BASE_PHY_RX);
#else
	/* MII mode gets PHY RX clock from ENET_RX_CLK */
	CGU_EntityConnect(CGU_CLKSRC_ENET_RX_CLK, CGU_BASE_PHY_RX);
#endif

	/* Reset ethernet via RGU. This should be 1 clock, but we wait
	   anyways. If the while loop really stalls, something else
	   is wrong. */
	LPC_RGU->RESET_CTRL0 = (1 << 22);
	timeout = 10;
	while (!(LPC_RGU->RESET_ACTIVE_STATUS0 & (1 << 22))) {
		msDelay(1);
		timeout--;
		if (timeout == 0)
			return ERR_TIMEOUT;
	}

	/* Reset MAC Subsystem internal registers and logic */
	LPC_ETHERNET->DMA_BUS_MODE |= DMA_BM_SWR;
	timeout = 3;
	while (LPC_ETHERNET->DMA_BUS_MODE & DMA_BM_SWR) {
		msDelay(1);
		timeout--;
		if (timeout == 0)
			return ERR_TIMEOUT;
	}
	LPC_ETHERNET->DMA_BUS_MODE = DMA_BM_ATDS | DMA_BM_PBL(1) | DMA_BM_RPBL(1);

	/* Save MAC address */
	LPC_ETHERNET->MAC_ADDR0_LOW = ((u32_t) netif->hwaddr[3] << 24) |
		((u32_t) netif->hwaddr[2] << 16) | ((u32_t) netif->hwaddr[1] << 8) |
		(u32_t) netif->hwaddr[0];
	LPC_ETHERNET->MAC_ADDR0_HIGH = ((u32_t) netif->hwaddr[5] << 8) |
		(u32_t) netif->hwaddr[4];

	/* Initial MAC configuration for checksum offload, full duplex,
	   100Mbps, disable receive own in half duplex, inter-frame gap
	   of 64-bits */
	LPC_ETHERNET->MAC_CONFIG = MAC_CFG_BL(0) | MAC_CFG_IPC | MAC_CFG_DM |
		MAC_CFG_DO | MAC_CFG_FES | MAC_CFG_PS | MAC_CFG_IFG(3);

	/* Setup filter */
#if IP_SOF_BROADCAST_RECV
	LPC_ETHERNET->MAC_FRAME_FILTER = MAC_FF_PR | MAC_FF_RA;
#else
	LPC_ETHERNET->MAC_FRAME_FILTER = 0; /* Only matching MAC address */
#endif

	/* Initialize the PHY */
	err = lpc_phy_init(netif, LPC_EMAC_RMII);
	if (err != ERR_OK)
 		return err;

	/* Setup transmit and receive descriptors */
	if (lpc_tx_setup(lpc_netifdata) != ERR_OK)
		return ERR_BUF;
	if (lpc_rx_setup(lpc_netifdata) != ERR_OK)
		return ERR_BUF;

	/* Flush transmit FIFO */
	LPC_ETHERNET->DMA_OP_MODE = DMA_OM_FTF;

	/* Setup DMA to flush receive FIFOs at 32 bytes, service TX FIFOs at
	   64 bytes */
	LPC_ETHERNET->DMA_OP_MODE |= DMA_OM_RTC(1) | DMA_OM_TTC(0);

	/* Clear all MAC interrupts */
	LPC_ETHERNET->DMA_STAT = DMA_ST_ALL;

	/* Enable MAC interrupts */
	LPC_ETHERNET->DMA_INT_EN =
#if NO_SYS == 1
		0;
#else
		DMA_IE_TIE | DMA_IE_OVE | DMA_IE_UNE | DMA_IE_RIE | DMA_IE_NIE |
			DMA_IE_AIE | DMA_IE_TUE | DMA_IE_RUE;
#endif

	/* Enable receive and transmit DMA processes */
	LPC_ETHERNET->DMA_OP_MODE |= DMA_OM_ST | DMA_OM_SR;

	/* Enable packet reception */
	LPC_ETHERNET->MAC_CONFIG |= MAC_CFG_RE | MAC_CFG_TE; 

	/* Start receive polling */
	LPC_ETHERNET->DMA_REC_POLL_DEMAND = 1;

	return ERR_OK;
}
/* Allocates a pbuf and returns the data from the incoming packet */
STATIC struct pbuf *lpc_low_level_input(struct netif *netif) {
    lpc_enetdata_t *lpc_enetif = netif->state;
    struct pbuf *p = NULL;
    u32_t idx, length;

#ifdef LOCK_RX_THREAD
#if NO_SYS == 0
    /* Get exclusive access */
    sys_mutex_lock(&lpc_enetif->rx_lock_mutex);
#endif
#endif

    /* Monitor RX overrun status. This should never happen unless
       (possibly) the internal bus is behing held up by something.
       Unless your system is running at a very low clock speed or
       there are possibilities that the internal buses may be held
       up for a long time, this can probably safely be removed. */
    if (Chip_ENET_GetIntStatus(LPC_ETHERNET) & ENET_INT_RXOVERRUN) {
        LINK_STATS_INC(link.err);
        LINK_STATS_INC(link.drop);

        /* Temporarily disable RX */
        Chip_ENET_RXDisable(LPC_ETHERNET);

        /* Reset the RX side */
        Chip_ENET_ResetRXLogic(LPC_ETHERNET);
        Chip_ENET_ClearIntStatus(LPC_ETHERNET, ENET_INT_RXOVERRUN);

        /* De-allocate all queued RX pbufs */
        for (idx = 0; idx < LPC_NUM_BUFF_RXDESCS; idx++) {
            if (lpc_enetif->rxb[idx] != NULL) {
                pbuf_free(lpc_enetif->rxb[idx]);
                lpc_enetif->rxb[idx] = NULL;
            }
        }

        /* Start RX side again */
        lpc_rx_setup(lpc_enetif);

        /* Re-enable RX */
        Chip_ENET_RXEnable(LPC_ETHERNET);

#ifdef LOCK_RX_THREAD
#if NO_SYS == 0
        sys_mutex_unlock(&lpc_enetif->rx_lock_mutex);
#endif
#endif

        return NULL;
    }

    /* Determine if a frame has been received */
    length = 0;
    idx = Chip_ENET_GetRXConsumeIndex(LPC_ETHERNET);
    if (!Chip_ENET_IsRxEmpty(LPC_ETHERNET)) {
        /* Handle errors */
        if (lpc_enetif->prxs[idx].StatusInfo & (ENET_RINFO_CRC_ERR |
                                                ENET_RINFO_SYM_ERR | ENET_RINFO_ALIGN_ERR | ENET_RINFO_LEN_ERR)) {
#if LINK_STATS
            if (lpc_enetif->prxs[idx].StatusInfo & (ENET_RINFO_CRC_ERR |
                                                    ENET_RINFO_SYM_ERR | ENET_RINFO_ALIGN_ERR)) {
                LINK_STATS_INC(link.chkerr);
            }
            if (lpc_enetif->prxs[idx].StatusInfo & ENET_RINFO_LEN_ERR) {
                LINK_STATS_INC(link.lenerr);
            }
#endif

            /* Drop the frame */
            LINK_STATS_INC(link.drop);

            /* Re-queue the pbuf for receive */
            lpc_enetif->rx_free_descs++;
            p = lpc_enetif->rxb[idx];
            lpc_enetif->rxb[idx] = NULL;
            lpc_rxqueue_pbuf(lpc_enetif, p);

            LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE,
                        ("lpc_low_level_input: Packet dropped with errors (0x%x)\n",
                         lpc_enetif->prxs[idx].StatusInfo));

            p = NULL;
        }
        else {
            /* A packet is waiting, get length */
            length = ENET_RINFO_SIZE(lpc_enetif->prxs[idx].StatusInfo) - 4;	/* Remove FCS */

            /* Zero-copy */
            p = lpc_enetif->rxb[idx];
            p->len = (u16_t) length;

            /* Free pbuf from desriptor */
            lpc_enetif->rxb[idx] = NULL;
            lpc_enetif->rx_free_descs++;

            /* Queue new buffer(s) */
            if (lpc_rx_queue(lpc_enetif->pnetif) == 0) {

                /* Re-queue the pbuf for receive */
                lpc_rxqueue_pbuf(lpc_enetif, p);

                /* Drop the frame */
                LINK_STATS_INC(link.drop);

                LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE,
                            ("lpc_low_level_input: Packet dropped since it could not allocate Rx Buffer\n"));

                p = NULL;
            }
            else {

                LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE,
                            ("lpc_low_level_input: Packet received: %p, size %d (index=%d)\n",
                             p, length, idx));

                /* Save size */
                p->tot_len = (u16_t) length;
                LINK_STATS_INC(link.recv);
            }
        }

        /* Update Consume index */
        Chip_ENET_IncRXConsumeIndex(LPC_ETHERNET);
    }

#ifdef LOCK_RX_THREAD
#if NO_SYS == 0
    sys_mutex_unlock(&lpc_enetif->rx_lock_mutex);
#endif
#endif

    return p;
}