diff options
Diffstat (limited to 'src/Hardware/SAME5x/Ethernet/GmacInterface.cpp')
-rw-r--r-- | src/Hardware/SAME5x/Ethernet/GmacInterface.cpp | 137 |
1 files changed, 67 insertions, 70 deletions
diff --git a/src/Hardware/SAME5x/Ethernet/GmacInterface.cpp b/src/Hardware/SAME5x/Ethernet/GmacInterface.cpp index 2f6a5988..b2c4ebc3 100644 --- a/src/Hardware/SAME5x/Ethernet/GmacInterface.cpp +++ b/src/Hardware/SAME5x/Ethernet/GmacInterface.cpp @@ -27,6 +27,8 @@ extern "C" { #include <RepRapFirmware.h> #include <RTOSIface/RTOSIface.h> #include <Platform/TaskPriorities.h> +#include <Platform/RepRap.h> +#include <Platform/Platform.h> extern Mutex lwipMutex; @@ -39,11 +41,12 @@ constexpr size_t EthernetTaskStackWords = 300; static Task<EthernetTaskStackWords> ethernetTask; // Error counters -unsigned int rxErrorCount; -unsigned int rxBuffersNotFullyPopulatedCount; -unsigned int txErrorCount; -unsigned int txBufferNotFreeCount; -unsigned int txBufferTooShortCount; +static unsigned int rxErrorCount = 0; +static unsigned int rxBuffersNotFullyPopulatedCount = 0; +static unsigned int rxBufferNotAvailableCount = 0; +static unsigned int txErrorCount = 0; +static unsigned int txBufferNotFreeCount = 0; +static unsigned int txBufferTooShortCount = 0; /** Network interface identifier. */ #define IFNAME0 'e' @@ -160,7 +163,7 @@ static void gmac_rx_populate_queue(struct gmac_device *p_gmac_dev, uint32_t star if (p_gmac_dev->rx_pbuf[ul_index] == nullptr) { /* Allocate a new pbuf with the maximum size. */ - pbuf * const p = pbuf_alloc(PBUF_RAW, (u16_t) GMAC_FRAME_LENTGH_MAX, PBUF_POOL); + pbuf * const p = pbuf_alloc(PBUF_RAW, (u16_t) GMAC_FRAME_LENGTH_MAX, PBUF_POOL); if (p == nullptr) { LWIP_DEBUGF(NETIF_DEBUG, ("gmac_rx_populate_queue: pbuf allocation failure\n")); @@ -173,28 +176,18 @@ static void gmac_rx_populate_queue(struct gmac_device *p_gmac_dev, uint32_t star LWIP_ASSERT("gmac_rx_populate_queue: pbuf size too small!", pbuf_clen(p) <= 1); /* Make sure that the payload buffer is properly aligned. */ - LWIP_ASSERT("gmac_rx_populate_queue: unaligned p->payload buffer address", - (((uint32_t)p->payload & 0xFFFFFFFC) == (uint32_t)p->payload)); - - // dc42 do this first to avoid a race condition with DMA, because writing addr.val transfers ownership back to the GMAC, so it should be the last thing we do - /* Reset status value. */ - p_gmac_dev->rx_desc[ul_index].status.val = 0; + LWIP_ASSERT("gmac_rx_populate_queue: unaligned p->payload buffer address", (((uint32_t)p->payload & 0xFFFFFFFC) == (uint32_t)p->payload)); /* Save pbuf pointer to be sent to lwIP upper layer. */ p_gmac_dev->rx_pbuf[ul_index] = p; - if (ul_index == GMAC_RX_BUFFERS - 1) - { - p_gmac_dev->rx_desc[ul_index].addr.val = (u32_t) p->payload | GMAC_RXD_WRAP; - } - else - { - p_gmac_dev->rx_desc[ul_index].addr.val = (u32_t) p->payload; - } + // dc42 do this first to avoid a race condition with DMA, because writing addr.val transfers ownership back to the GMAC, so it should be the last thing we do + p_gmac_dev->rx_desc[ul_index].status.val = 0; // reset status value + + __DSB(); + p_gmac_dev->rx_desc[ul_index].addr.val = (ul_index == GMAC_RX_BUFFERS - 1) ? (u32_t) p->payload | GMAC_RXD_WRAP : (u32_t) p->payload; Cache::FlushBeforeDMASend(&p_gmac_dev->rx_desc[ul_index], sizeof(p_gmac_dev->rx_desc[ul_index])); - LWIP_DEBUGF(NETIF_DEBUG, - ("gmac_rx_populate_queue: new pbuf allocated: %p [idx=%u]\n", - p, (unsigned int)ul_index)); + LWIP_DEBUGF(NETIF_DEBUG, ("gmac_rx_populate_queue: new pbuf allocated: %p [idx=%u]\n", p, (unsigned int)ul_index)); } ++ul_index; @@ -258,9 +251,13 @@ static void gmac_tx_init(struct gmac_device *ps_gmac_dev) noexcept ps_gmac_dev->tx_desc[ul_index].status.val = GMAC_TXD_USED | GMAC_TXD_LAST; } ps_gmac_dev->tx_desc[ul_index - 1].status.val |= GMAC_TXD_WRAP; + Cache::FlushBeforeDMASend(ps_gmac_dev->tx_desc, sizeof(ps_gmac_dev->tx_desc)); /* Set transmit buffer queue base address pointer. */ gmac_set_tx_queue(GMAC, (uint32_t) &ps_gmac_dev->tx_desc[0]); + + /* Clear error status. */ + gmac_clear_tx_status(GMAC, GMAC_TX_ERRORS); } /** @@ -308,16 +305,8 @@ static void gmac_low_level_init(struct netif *netif) noexcept * an err_t value if the packet couldn't be sent. */ -#include <General/Portability.h> static err_t gmac_low_level_output(netif *p_netif, struct pbuf *p) noexcept { -#if 0 - debugPrintf("%u %u %" PRIu32 "\n", - LoadBE16((const uint8_t*)p->payload + 0x24), // destination port - LoadBE16((const uint8_t*)p->payload + 0x10), // length - LoadBE32((const uint8_t*)p->payload + 0x26) // sequence number - ); -#endif gmac_device *const ps_gmac_dev = static_cast<gmac_device *>(p_netif->state); while (true) @@ -334,10 +323,7 @@ static err_t gmac_low_level_output(netif *p_netif, struct pbuf *p) noexcept LINK_STATS_INC(link.drop); /* Reinit TX descriptors. */ - gmac_tx_init(ps_gmac_dev); - - /* Clear error status. */ - gmac_clear_tx_status(GMAC, GMAC_TX_ERRORS); + gmac_tx_init(ps_gmac_dev); // this also clears the Tx errors gmac_enable_transmit(GMAC, true); } @@ -397,11 +383,11 @@ static err_t gmac_low_level_output(netif *p_netif, struct pbuf *p) noexcept * \param netif the lwIP network interface structure for this ethernetif. * * \return a pbuf filled with the received packet (including MAC header). - * 0 on memory error. + * nullptr if no received packet available. */ static pbuf *gmac_low_level_input(struct netif *netif) noexcept { - gmac_device *ps_gmac_dev = static_cast<gmac_device *>(netif->state); + gmac_device *const ps_gmac_dev = static_cast<gmac_device *>(netif->state); if (gmac_get_rx_status(GMAC) & GMAC_RX_ERRORS) { @@ -432,44 +418,55 @@ static pbuf *gmac_low_level_input(struct netif *netif) noexcept return nullptr; } - volatile gmac_rx_descriptor_t * const p_rx = &ps_gmac_dev->rx_desc[ps_gmac_dev->us_rx_idx]; + if (gmac_get_rx_status(GMAC) & GMAC_RSR_BNA) + { + ++rxBufferNotAvailableCount; + gmac_clear_rx_status(GMAC, GMAC_RSR_BNA); + } + + /* Check if a packet has been received and processed by GMAC. */ + uint32_t rxIdx = ps_gmac_dev->us_rx_idx; + volatile gmac_rx_descriptor_t * const p_rx = &ps_gmac_dev->rx_desc[rxIdx]; Cache::InvalidateAfterDMAReceive(p_rx, sizeof(gmac_rx_descriptor_t)); - pbuf * const p = ((p_rx->addr.val & GMAC_RXD_OWNERSHIP) == GMAC_RXD_OWNERSHIP) - ? ps_gmac_dev->rx_pbuf[ps_gmac_dev->us_rx_idx] + pbuf * p = ((p_rx->addr.val & GMAC_RXD_OWNERSHIP) != 0) + ? ps_gmac_dev->rx_pbuf[rxIdx] : nullptr; /* Check if a packet has been received and processed by GMAC. */ if (p != nullptr) { - /* Packet is a SOF since packet size is set to maximum. */ - const uint32_t length = p_rx->status.val & GMAC_RXD_LEN_MASK; + const uint32_t status = p_rx->status.val; + const uint32_t length = status & GMAC_RXD_LEN_MASK; /* Fetch pre-allocated pbuf. */ Cache::InvalidateAfterDMAReceive(p->payload, length); - p->len = length; /* Remove this pbuf from its descriptor. */ - ps_gmac_dev->rx_pbuf[ps_gmac_dev->us_rx_idx] = nullptr; + ps_gmac_dev->rx_pbuf[rxIdx] = nullptr; ps_gmac_dev->rxPbufsFullyPopulated = false; - LWIP_DEBUGF(NETIF_DEBUG, - ("gmac_low_level_input: DMA buffer %p received, size=%u [idx=%u]\n", - p, (unsigned int)length, (unsigned int)ps_gmac_dev->us_rx_idx)); - /* Set pbuf total packet size. */ - p->tot_len = length; + p->tot_len = p->len = length; LINK_STATS_INC(link.recv); - ps_gmac_dev->us_rx_idx = (ps_gmac_dev->us_rx_idx + 1) % GMAC_RX_BUFFERS; + ps_gmac_dev->us_rx_idx = rxIdx = (rxIdx + 1) % GMAC_RX_BUFFERS; + if ((status & (GMAC_RXD_SOF | GMAC_RXD_EOF)) == (GMAC_RXD_SOF | GMAC_RXD_EOF)) + { #if LWIP_STATS - lwip_rx_count += length; + lwip_rx_count += length; #endif + } + else + { + pbuf_free(p); + p = nullptr; + } } /* Fill empty descriptors with new pbufs. */ if (!ps_gmac_dev->rxPbufsFullyPopulated) { - gmac_rx_populate_queue(ps_gmac_dev, ps_gmac_dev->us_rx_idx); + gmac_rx_populate_queue(ps_gmac_dev, rxIdx); } return p; @@ -511,20 +508,18 @@ extern "C" [[noreturn]] void gmac_task(void *pvParameters) noexcept */ bool ethernetif_input(struct netif *netif) noexcept { - struct eth_hdr *ethhdr; - struct pbuf *p; - /* Move received packet into a new pbuf. */ - p = gmac_low_level_input(netif); + pbuf *const p = gmac_low_level_input(netif); if (p == nullptr) { return false; } /* Points to packet payload, which starts with an Ethernet header. */ - ethhdr = static_cast<struct eth_hdr*>(p->payload); + const eth_hdr *ethhdr = static_cast<struct eth_hdr*>(p->payload); - switch (lwip_htons(ethhdr->type)) { + switch (lwip_htons(ethhdr->type)) + { case ETHTYPE_IP: case ETHTYPE_ARP: #if defined(PPPOE_SUPPORT) && PPPOE_SUPPORT @@ -532,7 +527,8 @@ bool ethernetif_input(struct netif *netif) noexcept case ETHTYPE_PPPOE: #endif /* PPPOE_SUPPORT */ /* Send packet to lwIP for processing. */ - if (netif->input(p, netif) != ERR_OK) { + if (netif->input(p, netif) != ERR_OK) + { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); /* Free buffer. */ pbuf_free(p); @@ -723,12 +719,13 @@ void ethernetif_hardware_init() noexcept /* Enable the copy of data into the buffers ignore broadcasts, and not copy FCS. */ gmac_enable_copy_all(GMAC, false); gmac_disable_broadcast(GMAC, false); + GMAC->NCR.reg |= GMAC_NCFGR_RXCOEN; // check IP, UDP and TCP checksums so that we don't need to do it in lwip #if SUPPORT_MULTICAST_DISCOVERY // Without this code, we don't receive any multicast packets - GMAC->GMAC_NCFGR |= GMAC_NCFGR_MTIHEN; // enable multicast hash reception - GMAC->GMAC_HRB = 0xFFFFFFFF; // enable reception of all multicast frames - GMAC->GMAC_HRT = 0xFFFFFFFF; + GMAC->NCR.reg |= GMAC_NCFGR_MTIHEN; // enable multicast hash reception + GMAC->HRB.reg = 0xFFFFFFFF; // enable reception of all multicast frames + GMAC->HRT.reg = 0xFFFFFFFF; #endif /* Set RX buffer size to 1536. */ @@ -758,7 +755,7 @@ void ethernetif_hardware_init() noexcept bool ethernetif_establish_link() noexcept { /* Auto Negotiate, work in RMII mode. */ - uint8_t result = ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR); + const uint8_t result = ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR); if (result != GMAC_OK) { if (result != GMAC_TIMEOUT) @@ -769,13 +766,6 @@ bool ethernetif_establish_link() noexcept return false; } - /* Establish ethernet link. */ - if (ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1) != GMAC_OK) - { - LWIP_DEBUGF(NETIF_DEBUG, ("gmac_low_level_init: set link ERROR!\n")); - return false; - } - return true; } @@ -825,4 +815,11 @@ extern "C" uint32_t sys_now() noexcept return millis(); } +void ethernetif_diagnostics(MessageType mtype) noexcept +{ + reprap.GetPlatform().MessageF(mtype, "Error counts: %u %u %u %u %u %u\nSocket states:", + rxErrorCount, rxBuffersNotFullyPopulatedCount, rxBufferNotAvailableCount, txErrorCount, txBufferNotFreeCount, txBufferTooShortCount); + rxErrorCount = rxBuffersNotFullyPopulatedCount = rxBufferNotAvailableCount = txErrorCount = txBufferNotFreeCount = txBufferTooShortCount = 0; +} + // End |