/* 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; }
/** \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; }
/** \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; }
/** \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; }