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