diff options
Diffstat (limited to 'src/Hardware/SAME70/Ethernet/GmacInterface.cpp')
-rw-r--r-- | src/Hardware/SAME70/Ethernet/GmacInterface.cpp | 161 |
1 files changed, 82 insertions, 79 deletions
diff --git a/src/Hardware/SAME70/Ethernet/GmacInterface.cpp b/src/Hardware/SAME70/Ethernet/GmacInterface.cpp index 018bdad4..a0dad15e 100644 --- a/src/Hardware/SAME70/Ethernet/GmacInterface.cpp +++ b/src/Hardware/SAME70/Ethernet/GmacInterface.cpp @@ -56,6 +56,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; @@ -68,11 +70,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' @@ -89,7 +92,7 @@ unsigned int txBufferTooShortCount; /* configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY. */ /** The GMAC interrupts to enable */ -#define GMAC_INT_GROUP (GMAC_ISR_RCOMP | GMAC_ISR_ROVR | GMAC_ISR_HRESP | GMAC_ISR_TCOMP | GMAC_ISR_TUR | GMAC_ISR_TFC) +#define GMAC_INT_GROUP (GMAC_ISR_RCOMP | GMAC_ISR_ROVR) /** The GMAC TX errors to handle */ #define GMAC_TX_ERRORS (GMAC_TSR_TFC | GMAC_TSR_HRESP) @@ -160,9 +163,8 @@ uint32_t lwip_tx_rate = 0; uint32_t lwip_rx_rate = 0; #endif -/** - * \brief GMAC interrupt handler. - */ +// GMAC interrupt handler +// At present, we only use receive interrupts extern "C" void GMAC_Handler() noexcept { /* Get interrupt status. */ @@ -194,7 +196,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")); @@ -207,28 +209,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; @@ -292,9 +284,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); } /** @@ -323,7 +319,7 @@ static void gmac_low_level_init(struct netif *netif) noexcept netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP; /* Init MAC PHY driver. */ - if (ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, SystemCoreClock) != GMAC_OK) + if (ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, SystemCoreClockFreq/2) != GMAC_OK) // MCLK is half the core clock on the SAME70 { LWIP_DEBUGF(NETIF_DEBUG, ("gmac_low_level_init: PHY init ERROR!\n")); return; @@ -359,10 +355,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); } @@ -423,11 +416,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) { @@ -458,45 +451,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] - : nullptr; + 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; + p->tot_len = p->len = length; - 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; 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; @@ -538,38 +541,37 @@ 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)) { - case ETHTYPE_IP: - case ETHTYPE_ARP: + switch (lwip_htons(ethhdr->type)) + { + case ETHTYPE_IP: + case ETHTYPE_ARP: #if defined(PPPOE_SUPPORT) && PPPOE_SUPPORT - case ETHTYPE_PPPOEDISC: - case ETHTYPE_PPPOE: + case ETHTYPE_PPPOEDISC: + case ETHTYPE_PPPOE: #endif /* PPPOE_SUPPORT */ - /* Send packet to lwIP for processing. */ - if (netif->input(p, netif) != ERR_OK) { - LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); - /* Free buffer. */ - pbuf_free(p); - } - break; - - default: + /* Send packet to lwIP for processing. */ + if (netif->input(p, netif) != ERR_OK) + { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); /* Free buffer. */ pbuf_free(p); - break; + } + break; + + default: + /* Free buffer. */ + pbuf_free(p); + break; } return true; } @@ -654,6 +656,7 @@ 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->GMAC_NCFGR |= 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 @@ -712,7 +715,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) @@ -723,13 +726,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; } @@ -779,4 +775,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 |