Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Crocker <dcrocker@eschertech.com>2022-08-06 17:55:54 +0300
committerDavid Crocker <dcrocker@eschertech.com>2022-08-06 17:55:54 +0300
commitbd288d3cf6d102bd922543516222693582a46dc9 (patch)
tree26e968c8889068aaa1b46a6310c4017ae82759e0
parent1b560f82f6382a0f02ebbbdfb34651ef92f9d544 (diff)
Fixed bug causing jerky uploads on Duet 3 and 3 Mini Ethernet
-rw-r--r--src/Hardware/SAME5x/Ethernet/GmacInterface.cpp137
-rw-r--r--src/Hardware/SAME5x/Ethernet/GmacInterface.h16
-rw-r--r--src/Hardware/SAME5x/Ethernet/conf_eth.h2
-rw-r--r--src/Hardware/SAME5x/Ethernet/gmac.h2
-rw-r--r--src/Hardware/SAME5x/Ethernet/ksz8081rna/ethernet_phy.c99
-rw-r--r--src/Hardware/SAME5x/Ethernet/ksz8081rna/ethernet_phy.h4
-rw-r--r--src/Hardware/SAME70/Ethernet/GmacInterface.cpp161
-rw-r--r--src/Hardware/SAME70/Ethernet/GmacInterface.h16
-rw-r--r--src/Hardware/SAME70/Ethernet/ksz8081rna/ethernet_phy.c136
-rw-r--r--src/Hardware/SAME70/Ethernet/ksz8081rna/ethernet_phy.h2
-rw-r--r--src/Networking/HttpResponder.cpp29
-rw-r--r--src/Networking/LwipEthernet/Lwip/lwipopts.h17
-rw-r--r--src/Networking/LwipEthernet/Lwip/src/core/tcp_in.c2
-rw-r--r--src/Networking/LwipEthernet/LwipEthernetInterface.cpp19
-rw-r--r--src/Networking/LwipEthernet/LwipSocket.cpp86
-rw-r--r--src/Networking/LwipEthernet/LwipSocket.h3
-rw-r--r--src/Networking/Network.cpp6
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