diff options
author | David Crocker <dcrocker@eschertech.com> | 2022-08-06 17:55:54 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2022-08-06 17:55:54 +0300 |
commit | bd288d3cf6d102bd922543516222693582a46dc9 (patch) | |
tree | 26e968c8889068aaa1b46a6310c4017ae82759e0 | |
parent | 1b560f82f6382a0f02ebbbdfb34651ef92f9d544 (diff) |
Fixed bug causing jerky uploads on Duet 3 and 3 Mini Ethernet
-rw-r--r-- | src/Hardware/SAME5x/Ethernet/GmacInterface.cpp | 137 | ||||
-rw-r--r-- | src/Hardware/SAME5x/Ethernet/GmacInterface.h | 16 | ||||
-rw-r--r-- | src/Hardware/SAME5x/Ethernet/conf_eth.h | 2 | ||||
-rw-r--r-- | src/Hardware/SAME5x/Ethernet/gmac.h | 2 | ||||
-rw-r--r-- | src/Hardware/SAME5x/Ethernet/ksz8081rna/ethernet_phy.c | 99 | ||||
-rw-r--r-- | src/Hardware/SAME5x/Ethernet/ksz8081rna/ethernet_phy.h | 4 | ||||
-rw-r--r-- | src/Hardware/SAME70/Ethernet/GmacInterface.cpp | 161 | ||||
-rw-r--r-- | src/Hardware/SAME70/Ethernet/GmacInterface.h | 16 | ||||
-rw-r--r-- | src/Hardware/SAME70/Ethernet/ksz8081rna/ethernet_phy.c | 136 | ||||
-rw-r--r-- | src/Hardware/SAME70/Ethernet/ksz8081rna/ethernet_phy.h | 2 | ||||
-rw-r--r-- | src/Networking/HttpResponder.cpp | 29 | ||||
-rw-r--r-- | src/Networking/LwipEthernet/Lwip/lwipopts.h | 17 | ||||
-rw-r--r-- | src/Networking/LwipEthernet/Lwip/src/core/tcp_in.c | 2 | ||||
-rw-r--r-- | src/Networking/LwipEthernet/LwipEthernetInterface.cpp | 19 | ||||
-rw-r--r-- | src/Networking/LwipEthernet/LwipSocket.cpp | 86 | ||||
-rw-r--r-- | src/Networking/LwipEthernet/LwipSocket.h | 3 | ||||
-rw-r--r-- | src/Networking/Network.cpp | 6 |
17 files changed, 263 insertions, 474 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 diff --git a/src/Hardware/SAME5x/Ethernet/GmacInterface.h b/src/Hardware/SAME5x/Ethernet/GmacInterface.h index 0ef1f1e7..51026d5a 100644 --- a/src/Hardware/SAME5x/Ethernet/GmacInterface.h +++ b/src/Hardware/SAME5x/Ethernet/GmacInterface.h @@ -8,18 +8,15 @@ #ifndef SRC_HARDWARE_SAME5X_ETHERNET_GMACINTERFACE_H_ #define SRC_HARDWARE_SAME5X_ETHERNET_GMACINTERFACE_H_ -#ifdef __cplusplus extern "C" { -#endif - #include "lwip/err.h" #include "lwip/ip_addr.h" #include "lwip/netif.h" #include "netif/etharp.h" - -#ifdef __cplusplus } +#include <Platform/MessageType.h> + err_t ethernetif_init(struct netif *netif) noexcept; // called by LwIP to initialise the interface void ethernetif_terminate() noexcept; // called when we shut down @@ -34,13 +31,6 @@ bool ethernetif_link_established() noexcept; // asks the PHY if the link is s void ethernetif_set_mac_address(const uint8_t macAddress[]) noexcept; -#endif - -// Error counters -extern unsigned int rxErrorCount; -extern unsigned int rxBuffersNotFullyPopulatedCount; -extern unsigned int txErrorCount; -extern unsigned int txBufferNotFreeCount; -extern unsigned int txBufferTooShortCount; +void ethernetif_diagnostics(MessageType mtype) noexcept; #endif /* SRC_HARDWARE_SAME5X_ETHERNET_GMACINTERFACE_H_ */ diff --git a/src/Hardware/SAME5x/Ethernet/conf_eth.h b/src/Hardware/SAME5x/Ethernet/conf_eth.h index ebfd3161..6fd6ce95 100644 --- a/src/Hardware/SAME5x/Ethernet/conf_eth.h +++ b/src/Hardware/SAME5x/Ethernet/conf_eth.h @@ -21,7 +21,7 @@ #define GMAC_TX_BUFFERS 4 /** The MAC can support frame lengths up to 1536 bytes */ -#define GMAC_FRAME_LENTGH_MAX 1536 +#define GMAC_FRAME_LENGTH_MAX 1536 /** MAC PHY operation max retry count */ #define MAC_PHY_RETRY_MAX 1000000 diff --git a/src/Hardware/SAME5x/Ethernet/gmac.h b/src/Hardware/SAME5x/Ethernet/gmac.h index c4eeafcb..1bdf6232 100644 --- a/src/Hardware/SAME5x/Ethernet/gmac.h +++ b/src/Hardware/SAME5x/Ethernet/gmac.h @@ -85,7 +85,7 @@ extern "C" { #define GMAC_TXD_LEN_MASK (0x1FFF) /**< Length of buffer */ /** The MAC can support frame lengths up to 1536 bytes */ -#define GMAC_FRAME_LENTGH_MAX 1536 +#define GMAC_FRAME_LENGTH_MAX 1536 #define GMAC_TX_UNITSIZE (1518 + 2) /**< Size for ETH frame length, rounded up to a multiple of 4 (may make the DMA more efficient) */ diff --git a/src/Hardware/SAME5x/Ethernet/ksz8081rna/ethernet_phy.c b/src/Hardware/SAME5x/Ethernet/ksz8081rna/ethernet_phy.c index 81438cf0..271954c7 100644 --- a/src/Hardware/SAME5x/Ethernet/ksz8081rna/ethernet_phy.c +++ b/src/Hardware/SAME5x/Ethernet/ksz8081rna/ethernet_phy.c @@ -45,11 +45,6 @@ */ #include "ethernet_phy.h" - -#if 0 //dc42 -#include "pio/pio.h" -#endif - #include "../gmac.h" // ASF3 gmac driver #include "conf_eth.h" @@ -80,6 +75,8 @@ extern "C" { /* Ethernet PHY operation timeout */ #define ETH_PHY_TIMEOUT 10 +extern void debugPrintf(const char *fmt, ...) noexcept; + /** * \brief Find a valid PHY Address ( from addrStart to 31 ). * @@ -89,8 +86,7 @@ extern "C" { * * \return 0xFF when no valid PHY address is found. */ -static uint8_t ethernet_phy_find_valid(Gmac *p_gmac, uint8_t uc_phy_addr, - uint8_t uc_start_addr) +static uint8_t ethernet_phy_find_valid(Gmac *p_gmac, uint8_t uc_phy_addr, uint8_t uc_start_addr) { uint32_t ul_value = 0; uint8_t uc_rc = 0; @@ -167,92 +163,6 @@ uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t mck) /** - * \brief Get the Link & speed settings, and automatically set up the GMAC with the - * settings. - * - * \param p_gmac Pointer to the GMAC instance. - * \param uc_phy_addr PHY address. - * \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply. - * - * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout. - */ -uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr, - uint8_t uc_apply_setting_flag) -{ - uint32_t ul_stat1; - uint32_t ul_stat2; - uint8_t uc_phy_address, uc_speed, uc_fd; - uint8_t uc_rc; - - gmac_enable_management(p_gmac, true); - - uc_phy_address = uc_phy_addr; - - uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_stat1); - if (uc_rc != GMAC_OK) { - /* Disable PHY management and start the GMAC transfer */ - gmac_enable_management(p_gmac, false); - - return uc_rc; - } - - if ((ul_stat1 & GMII_LINK_STATUS) == 0) { - /* Disable PHY management and start the GMAC transfer */ - gmac_enable_management(p_gmac, false); - - return GMAC_INVALID; - } - - if (uc_apply_setting_flag == 0) { - /* Disable PHY management and start the GMAC transfer */ - gmac_enable_management(p_gmac, false); - - return uc_rc; - } - - /* Read advertisement */ - uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_PCR1, &ul_stat2); - if (uc_rc != GMAC_OK) { - /* Disable PHY management and start the GMAC transfer */ - gmac_enable_management(p_gmac, false); - - return uc_rc; - } - - if ((ul_stat1 & GMII_100BASE_TX_FD) && (ul_stat2 & GMII_OMI_100BASE_TX_FD)) { - /* Set GMAC for 100BaseTX and Full Duplex */ - uc_speed = true; - uc_fd = true; - } - - if ((ul_stat1 & GMII_10BASE_T_FD) && (ul_stat2 & GMII_OMI_10BASE_T_FD)) { - /* Set MII for 10BaseT and Full Duplex */ - uc_speed = false; - uc_fd = true; - } - - if ((ul_stat1 & GMII_100BASE_TX_HD) && (ul_stat2 & GMII_OMI_100BASE_TX_HD)) { - /* Set MII for 100BaseTX and Half Duplex */ - uc_speed = true; - uc_fd = false; - } - - if ((ul_stat1 & GMII_10BASE_T_HD) && (ul_stat2 & GMII_OMI_10BASE_T_HD)) { - /* Set MII for 10BaseT and Half Duplex */ - uc_speed = false; - uc_fd = false; - } - - gmac_set_speed(p_gmac, uc_speed); - gmac_enable_full_duplex(p_gmac, uc_fd); - - /* Start the GMAC transfers */ - gmac_enable_management(p_gmac, false); - return uc_rc; -} - - -/** * \brief Issue an auto negotiation of the PHY. * * \param p_gmac Pointer to the GMAC instance. @@ -295,8 +205,7 @@ uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr) * MII advertising for Next page. * 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3. */ - ul_phy_anar = GMII_100TX_FDX | GMII_100TX_HDX | GMII_10_FDX | GMII_10_HDX | - GMII_AN_IEEE_802_3; + ul_phy_anar = GMII_100TX_FDX | GMII_100TX_HDX | GMII_10_FDX | GMII_10_HDX | GMII_AN_IEEE_802_3; uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_ANAR, ul_phy_anar); if (uc_rc != GMAC_OK) { gmac_enable_management(p_gmac, false); diff --git a/src/Hardware/SAME5x/Ethernet/ksz8081rna/ethernet_phy.h b/src/Hardware/SAME5x/Ethernet/ksz8081rna/ethernet_phy.h index 42098f13..ab5740b8 100644 --- a/src/Hardware/SAME5x/Ethernet/ksz8081rna/ethernet_phy.h +++ b/src/Hardware/SAME5x/Ethernet/ksz8081rna/ethernet_phy.h @@ -52,8 +52,8 @@ // IEEE defined Registers #define GMII_BMCR 0x00 // Basic Control #define GMII_BMSR 0x01 // Basic Status -#define GMII_PHYID1 0x02 // PHY Idendifier 1 -#define GMII_PHYID2 0x03 // PHY Idendifier 2 +#define GMII_PHYID1 0x02 // PHY Identifier 1 +#define GMII_PHYID2 0x03 // PHY Identifier 2 #define GMII_ANAR 0x04 // Auto_Negotiation Advertisement #define GMII_ANLPAR 0x05 // Auto_negotiation Link Partner Ability #define GMII_ANER 0x06 // Auto-negotiation Expansion 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 diff --git a/src/Hardware/SAME70/Ethernet/GmacInterface.h b/src/Hardware/SAME70/Ethernet/GmacInterface.h index 1cbe7ad9..86b490fb 100644 --- a/src/Hardware/SAME70/Ethernet/GmacInterface.h +++ b/src/Hardware/SAME70/Ethernet/GmacInterface.h @@ -45,18 +45,15 @@ #ifndef SAME70_ETHERNET_GMACINTERFACE_H_INCLUDED #define SAME70_ETHERNET_GMACINTERFACE_H_INCLUDED -#ifdef __cplusplus extern "C" { -#endif - #include "lwip/err.h" #include "lwip/ip_addr.h" #include "lwip/netif.h" #include "netif/etharp.h" - -#ifdef __cplusplus } +#include <Platform/MessageType.h> + err_t ethernetif_init(struct netif *netif) noexcept; // called by LwIP to initialise the interface void ethernetif_terminate() noexcept; // called when we shut down @@ -71,13 +68,6 @@ bool ethernetif_link_established() noexcept; // asks the PHY if the link is s void ethernetif_set_mac_address(const uint8_t macAddress[]) noexcept; -#endif - -// Error counters -extern unsigned int rxErrorCount; -extern unsigned int rxBuffersNotFullyPopulatedCount; -extern unsigned int txErrorCount; -extern unsigned int txBufferNotFreeCount; -extern unsigned int txBufferTooShortCount; +void ethernetif_diagnostics(MessageType mtype) noexcept; #endif /* SAME70_ETHERNET_GMACINTERFACE_H_INCLUDED */ diff --git a/src/Hardware/SAME70/Ethernet/ksz8081rna/ethernet_phy.c b/src/Hardware/SAME70/Ethernet/ksz8081rna/ethernet_phy.c index c185c1aa..3b8c2a86 100644 --- a/src/Hardware/SAME70/Ethernet/ksz8081rna/ethernet_phy.c +++ b/src/Hardware/SAME70/Ethernet/ksz8081rna/ethernet_phy.c @@ -46,10 +46,6 @@ #include "ethernet_phy.h" -#if 0 //dc42 -#include "pio/pio.h" -#endif - #include <gmac/gmac.h> // ASF3 gmac driver #include "conf_eth.h" @@ -77,14 +73,11 @@ extern "C" { /* Max PHY number */ #define ETH_PHY_MAX_ADDR 31 -#if 0 // chrishamm -/* Ethernet PHY operation max retry count */ -#define ETH_PHY_RETRY_MAX 1000000 -#endif - /* Ethernet PHY operation timeout */ #define ETH_PHY_TIMEOUT 10 +extern void debugPrintf(const char *fmt, ...) noexcept; + /** * \brief Find a valid PHY Address ( from addrStart to 31 ). * @@ -94,8 +87,7 @@ extern "C" { * * \return 0xFF when no valid PHY address is found. */ -static uint8_t ethernet_phy_find_valid(Gmac *p_gmac, uint8_t uc_phy_addr, - uint8_t uc_start_addr) +static uint8_t ethernet_phy_find_valid(Gmac *p_gmac, uint8_t uc_phy_addr, uint8_t uc_start_addr) { uint32_t ul_value = 0; uint8_t uc_rc = 0; @@ -150,12 +142,6 @@ uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t mck) uint8_t uc_rc; uint8_t uc_phy; -#if 0 // chrishamm - pio_set_output(PIN_GMAC_RESET_PIO, PIN_GMAC_RESET_MASK, 1, false, true); - pio_set_input(PIN_GMAC_INT_PIO, PIN_GMAC_INT_MASK, PIO_PULLUP); - pio_set_peripheral(PIN_GMAC_PIO, PIN_GMAC_PERIPH, PIN_GMAC_MASK); -#endif - ethernet_phy_reset(GMAC,uc_phy_addr); /* Configure GMAC runtime clock */ @@ -178,92 +164,6 @@ uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t mck) /** - * \brief Get the Link & speed settings, and automatically set up the GMAC with the - * settings. - * - * \param p_gmac Pointer to the GMAC instance. - * \param uc_phy_addr PHY address. - * \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply. - * - * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout. - */ -uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr, - uint8_t uc_apply_setting_flag) -{ - uint32_t ul_stat1; - uint32_t ul_stat2; - uint8_t uc_phy_address, uc_speed, uc_fd; - uint8_t uc_rc; - - gmac_enable_management(p_gmac, true); - - uc_phy_address = uc_phy_addr; - - uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_stat1); - if (uc_rc != GMAC_OK) { - /* Disable PHY management and start the GMAC transfer */ - gmac_enable_management(p_gmac, false); - - return uc_rc; - } - - if ((ul_stat1 & GMII_LINK_STATUS) == 0) { - /* Disable PHY management and start the GMAC transfer */ - gmac_enable_management(p_gmac, false); - - return GMAC_INVALID; - } - - if (uc_apply_setting_flag == 0) { - /* Disable PHY management and start the GMAC transfer */ - gmac_enable_management(p_gmac, false); - - return uc_rc; - } - - /* Read advertisement */ - uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_PCR1, &ul_stat2); - if (uc_rc != GMAC_OK) { - /* Disable PHY management and start the GMAC transfer */ - gmac_enable_management(p_gmac, false); - - return uc_rc; - } - - if ((ul_stat1 & GMII_100BASE_TX_FD) && (ul_stat2 & GMII_OMI_100BASE_TX_FD)) { - /* Set GMAC for 100BaseTX and Full Duplex */ - uc_speed = true; - uc_fd = true; - } - - if ((ul_stat1 & GMII_10BASE_T_FD) && (ul_stat2 & GMII_OMI_10BASE_T_FD)) { - /* Set MII for 10BaseT and Full Duplex */ - uc_speed = false; - uc_fd = true; - } - - if ((ul_stat1 & GMII_100BASE_TX_HD) && (ul_stat2 & GMII_OMI_100BASE_TX_HD)) { - /* Set MII for 100BaseTX and Half Duplex */ - uc_speed = true; - uc_fd = false; - } - - if ((ul_stat1 & GMII_10BASE_T_HD) && (ul_stat2 & GMII_OMI_10BASE_T_HD)) { - /* Set MII for 10BaseT and Half Duplex */ - uc_speed = false; - uc_fd = false; - } - - gmac_set_speed(p_gmac, uc_speed); - gmac_enable_full_duplex(p_gmac, uc_fd); - - /* Start the GMAC transfers */ - gmac_enable_management(p_gmac, false); - return uc_rc; -} - - -/** * \brief Issue an auto negotiation of the PHY. * * \param p_gmac Pointer to the GMAC instance. @@ -274,10 +174,6 @@ uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr, static bool phyInitialized = false; uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr) { -#if 0 // chrishamm - uint32_t ul_retry_max = ETH_PHY_RETRY_MAX; - uint32_t ul_retry_count = 0; -#endif uint32_t ul_value; uint32_t ul_phy_anar; uint32_t ul_phy_analpar; @@ -310,8 +206,7 @@ uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr) * MII advertising for Next page. * 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3. */ - ul_phy_anar = GMII_100TX_FDX | GMII_100TX_HDX | GMII_10_FDX | GMII_10_HDX | - GMII_AN_IEEE_802_3; + ul_phy_anar = GMII_100TX_FDX | GMII_100TX_HDX | GMII_10_FDX | GMII_10_HDX | GMII_AN_IEEE_802_3; uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_ANAR, ul_phy_anar); if (uc_rc != GMAC_OK) { gmac_enable_management(p_gmac, false); @@ -345,7 +240,6 @@ uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr) } /* Check if auto negotiation is completed */ -#if 1 // chrishamm uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMSR, &ul_value); if (uc_rc != GMAC_OK) { @@ -358,27 +252,6 @@ uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr) gmac_enable_management(p_gmac, false); return GMAC_TIMEOUT; } -#else - while (1) { - uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMSR, &ul_value); - if (uc_rc != GMAC_OK) { - gmac_enable_management(p_gmac, false); - return uc_rc; - } - /* Done successfully */ - if (ul_value & GMII_AUTONEG_COMP) { - break; - } - - /* Timeout check */ - if (ul_retry_max) { - if (++ul_retry_count >= ul_retry_max) { - gmac_enable_management(p_gmac, false); - return GMAC_TIMEOUT; - } - } - } -#endif /* Get the auto negotiate link partner base page */ uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_ANLPAR, &ul_phy_analpar); @@ -387,7 +260,6 @@ uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr) return uc_rc; } - /* Set up the GMAC link speed */ if ((ul_phy_anar & ul_phy_analpar) & GMII_100TX_FDX) { /* Set MII for 100BaseTX and Full Duplex */ diff --git a/src/Hardware/SAME70/Ethernet/ksz8081rna/ethernet_phy.h b/src/Hardware/SAME70/Ethernet/ksz8081rna/ethernet_phy.h index 85e93438..ab5740b8 100644 --- a/src/Hardware/SAME70/Ethernet/ksz8081rna/ethernet_phy.h +++ b/src/Hardware/SAME70/Ethernet/ksz8081rna/ethernet_phy.h @@ -47,7 +47,7 @@ #ifndef ETHERNET_PHY_H_INCLUDED #define ETHERNET_PHY_H_INCLUDED -#include "compiler.h" +#include <Core.h> // IEEE defined Registers #define GMII_BMCR 0x00 // Basic Control diff --git a/src/Networking/HttpResponder.cpp b/src/Networking/HttpResponder.cpp index d910ef9f..6b75b418 100644 --- a/src/Networking/HttpResponder.cpp +++ b/src/Networking/HttpResponder.cpp @@ -1296,21 +1296,24 @@ void HttpResponder::DoUpload() noexcept size_t len; if (skt->ReadBuffer(buffer, len)) { - (void)CheckAuthenticated(); // uploading may take a long time, so make sure the requester IP is not timed out - timer = millis(); // reset the timer + do + { + (void)CheckAuthenticated(); // uploading may take a long time, so make sure the requester IP is not timed out + timer = millis(); // reset the timer - const bool ok = dummyUpload || fileBeingUploaded.Write(buffer, len); - skt->Taken(len); - uploadedBytes += len; + const bool ok = dummyUpload || fileBeingUploaded.Write(buffer, len); + skt->Taken(len); + uploadedBytes += len; - if (!ok) - { - uploadError = true; - GetPlatform().Message(ErrorMessage, "HTTP: could not write upload data\n"); - CancelUpload(); - SendJsonResponse("upload"); - return; - } + if (!ok) + { + uploadError = true; + GetPlatform().Message(ErrorMessage, "HTTP: could not write upload data\n"); + CancelUpload(); + SendJsonResponse("upload"); + return; + } + } while (skt->ReadBuffer(buffer, len)); } else if (!skt->CanRead() || millis() - timer >= HttpSessionTimeout) { diff --git a/src/Networking/LwipEthernet/Lwip/lwipopts.h b/src/Networking/LwipEthernet/Lwip/lwipopts.h index e67dcc6c..559aea5c 100644 --- a/src/Networking/LwipEthernet/Lwip/lwipopts.h +++ b/src/Networking/LwipEthernet/Lwip/lwipopts.h @@ -63,7 +63,7 @@ /** * LWIP_NETIF_STATUS_CALLBACK==1: Support a callback function whenever an interface - * changes its up/down status (i.e., due to DHCP IP acquistion) + * changes its up/down status (i.e., due to DHCP IP acquisition) */ #define LWIP_NETIF_STATUS_CALLBACK 1 @@ -89,9 +89,14 @@ #define LWIP_CHKSUM_ALGORITHM 3 // use fastest checksum algorithm (does 8 bytes at a time) +#define CHECKSUM_CHECK_IP 0 // use hardware checking of incoming IP checksums +#define CHECKSUM_CHECK_UDP 0 // use hardware checking of incoming UDP checksums +#define CHECKSUM_CHECK_TCP 0 // use hardware checking of incoming TCP checksums + #define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS 1 -#define lwip_htons(_x) __builtin_bswap16(_x) -#define lwip_htonl(_x) __builtin_bswap32(_x) +#define lwip_htons(_x) __builtin_bswap16(_x) +#define lwip_htonl(_x) __builtin_bswap32(_x) +#define SWAP_BYTES_IN_WORD(_x) __builtin_bswap16(_x) /* ------------------------------------ @@ -120,7 +125,7 @@ #define MEMP_NUM_UDP_PCB 3 /** - * MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections. + * MEMP_NUM_TCP_PCB: the number of simultaneously active TCP connections. * (requires the LWIP_TCP option) */ #define MEMP_NUM_TCP_PCB 8 @@ -179,7 +184,7 @@ /** * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */ -#define PBUF_POOL_BUFSIZE GMAC_FRAME_LENTGH_MAX +#define PBUF_POOL_BUFSIZE GMAC_FRAME_LENGTH_MAX /* ---------------------------------- @@ -240,7 +245,7 @@ extern uint32_t random32(void) noexcept; * TCP_WND: The size of a TCP window. This must be at least * (2 * TCP_MSS) for things to work well */ -#define TCP_WND (2 * TCP_MSS) +#define TCP_WND (4 * TCP_MSS) /** * TCP_SND_BUF: TCP sender buffer space (bytes). diff --git a/src/Networking/LwipEthernet/Lwip/src/core/tcp_in.c b/src/Networking/LwipEthernet/Lwip/src/core/tcp_in.c index 428a6f48..e198fd13 100644 --- a/src/Networking/LwipEthernet/Lwip/src/core/tcp_in.c +++ b/src/Networking/LwipEthernet/Lwip/src/core/tcp_in.c @@ -1645,6 +1645,7 @@ tcp_receive(struct tcp_pcb *pcb) /* We get here if the incoming segment is out-of-sequence. */ #if TCP_QUEUE_OOSEQ + //debugPrintf("OOS! have %" PRIu32 ", expected %" PRIu32 " to %" PRIu32 "\n", seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd - 1); /* We queue the segment on the ->ooseq queue. */ if (pcb->ooseq == NULL) { pcb->ooseq = tcp_seg_copy(&inseg); @@ -1873,6 +1874,7 @@ tcp_receive(struct tcp_pcb *pcb) } } else { /* The incoming segment is not within the window. */ + //debugPrintf("Not in window: %" PRIu32 ", expected %" PRIu32 " to %" PRIu32 "\n", seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd - 1); tcp_send_empty_ack(pcb); } } else { diff --git a/src/Networking/LwipEthernet/LwipEthernetInterface.cpp b/src/Networking/LwipEthernet/LwipEthernetInterface.cpp index 443a09f7..0430a81c 100644 --- a/src/Networking/LwipEthernet/LwipEthernetInterface.cpp +++ b/src/Networking/LwipEthernet/LwipEthernetInterface.cpp @@ -70,15 +70,9 @@ Mutex lwipMutex; extern "C" { - // Task function to keep the GMAC and LwIP running - void DoEthernetTask() - { - ethernet_task(); - } - // Callback functions for LWIP (may be called from ISR) // This occasionally seems to get called with a null pcb argument, so check for that here - static err_t conn_accept(void *arg, tcp_pcb *pcb, err_t err) + static err_t conn_accept(void *arg, tcp_pcb *pcb, err_t err) noexcept { LWIP_UNUSED_ARG(arg); LWIP_UNUSED_ARG(err); @@ -450,7 +444,7 @@ void LwipEthernetInterface::Spin() noexcept if (ethernet_link_established()) { // Check for incoming packets - DoEthernetTask(); + ethernet_task(); // Have we obtained an IP address yet? ethernet_get_ipaddress(ipAddress, netmask, gateway); @@ -483,7 +477,7 @@ void LwipEthernetInterface::Spin() noexcept if (ethernet_link_established()) { // Check for incoming packets - DoEthernetTask(); + ethernet_task(); // Poll the next TCP socket sockets[nextSocketToPoll]->Poll(); @@ -513,10 +507,9 @@ void LwipEthernetInterface::Spin() noexcept void LwipEthernetInterface::Diagnostics(MessageType mtype) noexcept { - platform.MessageF(mtype, "- Ethernet -\nState: %s\n", GetStateName()); - platform.MessageF(mtype, "Error counts: %u %u %u %u %u\nSocket states:", - rxErrorCount, rxBuffersNotFullyPopulatedCount, txErrorCount, txBufferNotFreeCount, txBufferTooShortCount); - for (LwipSocket *s : sockets) + platform.MessageF(mtype, "= Ethernet =\nState: %s\n", GetStateName()); + ethernetif_diagnostics(mtype); + for (const LwipSocket *s : sockets) { platform.MessageF(mtype, " %d", s->GetState()); } diff --git a/src/Networking/LwipEthernet/LwipSocket.cpp b/src/Networking/LwipEthernet/LwipSocket.cpp index fc015ba2..30fb787c 100644 --- a/src/Networking/LwipEthernet/LwipSocket.cpp +++ b/src/Networking/LwipEthernet/LwipSocket.cpp @@ -112,13 +112,14 @@ void LwipSocket::DataReceived(pbuf *data) noexcept if (state != SocketState::closing) { // Store it for the NetworkResponder - if (receivedData == nullptr) + pbuf *const rdata = receivedData; + if (rdata == nullptr) { receivedData = data; } else { - pbuf_cat(receivedData, data); + pbuf_cat(rdata, data); } } else @@ -256,30 +257,47 @@ bool LwipSocket::CanSend() const noexcept return (state == SocketState::connected); } +// Get the next received pbuf, skipping any empty ones (we can get empty ones from lwip) +pbuf *LwipSocket::GetNextReceivedPbuf() noexcept +{ + pbuf *rdata; + while ((rdata = receivedData) != nullptr && rdata->len == 0) + { + debugPrintf("Discarding empty pbuf\n"); + MutexLocker lock(lwipMutex); + receivedData = rdata->next; + rdata->next = nullptr; + pbuf_free(rdata); + readIndex = 0; + } + return rdata; +} + // Read 1 character from the receive buffers, returning true if successful bool LwipSocket::ReadChar(char& c) noexcept { - if (receivedData != nullptr) + pbuf *const rdata = GetNextReceivedPbuf(); + if (rdata != nullptr) { - const char * const data = (const char *)receivedData->payload; + const char * const data = (const char *)rdata->payload; c = data[readIndex++]; - if (readIndex >= receivedData->len) + const uint16_t rlen = rdata->len; + if (readIndex >= rlen) { - // We've processed one more pbuf + // Free the buffer. Grab the mutex first to prevent lwip appending more data to it. MutexLocker lock(lwipMutex); + receivedData = rdata->next; + rdata->next = nullptr; + pbuf_free(rdata); + readIndex = 0; + + // Tell lwip we have taken this data if (connectionPcb != nullptr) { - tcp_recved(connectionPcb, receivedData->len); + tcp_recved(connectionPcb, rlen); } - - // Free the first item of the pbuf chain and move on to the next one - pbuf *currentBlock = receivedData; - receivedData = receivedData->next; - currentBlock->next = nullptr; - pbuf_free(currentBlock); - readIndex = 0; } return true; @@ -292,11 +310,12 @@ bool LwipSocket::ReadChar(char& c) noexcept // Return a pointer to data in a buffer and a length available bool LwipSocket::ReadBuffer(const uint8_t *&buffer, size_t &len) noexcept { - if (receivedData != nullptr) + pbuf *const rdata = GetNextReceivedPbuf(); + if (rdata != nullptr) { - const uint8_t * const data = (const uint8_t *)receivedData->payload; + const uint8_t * const data = (const uint8_t *)rdata->payload; buffer = &data[readIndex]; - len = receivedData->len - readIndex; + len = rdata->len - readIndex; return true; } @@ -306,25 +325,27 @@ bool LwipSocket::ReadBuffer(const uint8_t *&buffer, size_t &len) noexcept // Flag some data as taken from the receive buffers. We never take data from more than one buffer at a time. void LwipSocket::Taken(size_t len) noexcept { - if (receivedData != nullptr) + pbuf *const rdata = receivedData; + if (rdata != nullptr) // should always be true { readIndex += len; - if (readIndex >= receivedData->len) + const uint16_t rlen = rdata->len; + if (readIndex >= rlen) { - // Notify LwIP + // Free the buffer. Grab the mutex first to prevent lwip appending more data to it. MutexLocker lock(lwipMutex); + // Free the first item of the pbuf chain if the number of taken bytes exceeds its size + receivedData = rdata->next; + rdata->next = nullptr; + pbuf_free(rdata); + readIndex = 0; + + // Notify LwIP if (connectionPcb != nullptr) { - tcp_recved(connectionPcb, receivedData->len); + tcp_recved(connectionPcb, rlen); } - - // Free the first item of the pbuf chain if the number of taken bytes exceeds its size - pbuf *currentBlock = receivedData; - receivedData = receivedData->next; - currentBlock->next = nullptr; - pbuf_free(currentBlock); - readIndex = 0; } } } @@ -346,8 +367,6 @@ void LwipSocket::Poll() noexcept break; case SocketState::connected: - // A connection has been established, but no responder has been found yet - // See if we can assign this socket if (responderFound) { // Are we still waiting for data to be written? @@ -415,13 +434,14 @@ void LwipSocket::Poll() noexcept } } -// Discard any received data for this transaction +// Discard any received data for this transaction. Acquire the lwip mutex before calling this. void LwipSocket::DiscardReceivedData() noexcept { - if (receivedData != nullptr) + pbuf *const rdata = receivedData; + if (rdata != nullptr) { - pbuf_free(receivedData); receivedData = nullptr; + pbuf_free(rdata); } readIndex = 0; } diff --git a/src/Networking/LwipEthernet/LwipSocket.h b/src/Networking/LwipEthernet/LwipSocket.h index ddedf5d8..c51e250c 100644 --- a/src/Networking/LwipEthernet/LwipSocket.h +++ b/src/Networking/LwipEthernet/LwipSocket.h @@ -63,6 +63,7 @@ private: void ReInit() noexcept; void DiscardReceivedData() noexcept; + pbuf *GetNextReceivedPbuf() noexcept; uint32_t whenConnected; uint32_t whenWritten; @@ -70,7 +71,7 @@ private: bool responderFound; tcp_pcb *connectionPcb; - pbuf *receivedData; + pbuf *volatile receivedData; size_t readIndex; SocketState state; diff --git a/src/Networking/Network.cpp b/src/Networking/Network.cpp index c8fd283a..cf012cc0 100644 --- a/src/Networking/Network.cpp +++ b/src/Networking/Network.cpp @@ -555,7 +555,11 @@ void Network::Spin() noexcept { slowLoop = dt; } - RTOSIface::Yield(); + + if (!doneSomething) + { + RTOSIface::Yield(); + } } } #endif |