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:
-rw-r--r--.cproject8
-rw-r--r--src/Endstops/SwitchEndstop.h2
-rw-r--r--src/Hardware/IoPorts.cpp15
-rw-r--r--src/Networking/ESP8266WiFi/WiFiInterface.cpp146
-rw-r--r--src/Networking/ESP8266WiFi/WiFiInterface.h2
-rw-r--r--src/Networking/ESP8266WiFi/WiFiSocket.cpp4
-rw-r--r--src/Networking/ESP8266WiFi/WiFiSocket.h2
-rw-r--r--src/Networking/LwipEthernet/GMAC/ethernet_sam.cpp4
-rw-r--r--src/Networking/LwipEthernet/GMAC/ethernet_sam.h3
-rw-r--r--src/Networking/LwipEthernet/GMAC/same70_gmac.cpp263
-rw-r--r--src/Networking/LwipEthernet/GMAC/same70_gmac.h9
-rw-r--r--src/Networking/LwipEthernet/Lwip/lwipopts.h11
-rw-r--r--src/Networking/LwipEthernet/LwipEthernetInterface.cpp190
-rw-r--r--src/Networking/LwipEthernet/LwipEthernetInterface.h2
-rw-r--r--src/Networking/LwipEthernet/LwipSocket.cpp101
-rw-r--r--src/Networking/LwipEthernet/LwipSocket.h2
-rw-r--r--src/Networking/Network.cpp29
-rw-r--r--src/Networking/Network.h2
-rw-r--r--src/Networking/NetworkInterface.h2
-rw-r--r--src/Networking/Socket.h2
-rw-r--r--src/Networking/W5500Ethernet/W5500Interface.cpp31
-rw-r--r--src/Networking/W5500Ethernet/W5500Interface.h2
-rw-r--r--src/Networking/W5500Ethernet/W5500Socket.cpp4
-rw-r--r--src/Networking/W5500Ethernet/W5500Socket.h2
-rw-r--r--src/Platform.cpp9
-rw-r--r--src/RepRap.cpp4
-rw-r--r--src/RepRapFirmware.cpp7
-rw-r--r--src/RepRapFirmware.h4
-rw-r--r--src/Storage/CRC32.cpp30
-rw-r--r--src/Tasks.cpp3
-rw-r--r--src/Version.h2
31 files changed, 505 insertions, 392 deletions
diff --git a/.cproject b/.cproject
index 7ffb7685..f1470df2 100644
--- a/.cproject
+++ b/.cproject
@@ -1352,7 +1352,7 @@
<listOptionValue builtIn="false" value="__SAME70Q20B__"/>
<listOptionValue builtIn="false" value="RTOS"/>
<listOptionValue builtIn="false" value="DUET3_V06"/>
- <listOptionValue builtIn="false" value="LWIP_GMAC_TASK=0"/>
+ <listOptionValue builtIn="false" value="LWIP_GMAC_TASK=1"/>
</option>
<option id="gnu.c.compiler.option.dialect.std.1738681846" name="Language standard" superClass="gnu.c.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.c.compiler.dialect.default" valueType="enumerated"/>
<option id="gnu.c.compiler.option.dialect.flags.1952106689" name="Other dialect flags" superClass="gnu.c.compiler.option.dialect.flags" useByScannerDiscovery="true" value="-std=gnu99" valueType="string"/>
@@ -1419,7 +1419,7 @@
<listOptionValue builtIn="false" value="__SAME70Q20B__"/>
<listOptionValue builtIn="false" value="RTOS"/>
<listOptionValue builtIn="false" value="DUET3_V06"/>
- <listOptionValue builtIn="false" value="LWIP_GMAC_TASK=0"/>
+ <listOptionValue builtIn="false" value="LWIP_GMAC_TASK=1"/>
<listOptionValue builtIn="false" value="_XOPEN_SOURCE"/>
</option>
<option id="gnu.cpp.compiler.option.dialect.std.1240779290" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.default" valueType="enumerated"/>
@@ -1532,6 +1532,8 @@
<listOptionValue builtIn="false" value="__SAME70Q20B__"/>
<listOptionValue builtIn="false" value="RTOS"/>
<listOptionValue builtIn="false" value="DUET3_V06"/>
+ <listOptionValue builtIn="false" value="LWIP_GMAC_TASK=1"/>
+ <listOptionValue builtIn="false" value="DEBUG"/>
</option>
<option id="gnu.c.compiler.option.dialect.std.1475182191" name="Language standard" superClass="gnu.c.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.c.compiler.dialect.default" valueType="enumerated"/>
<option id="gnu.c.compiler.option.dialect.flags.879019933" name="Other dialect flags" superClass="gnu.c.compiler.option.dialect.flags" useByScannerDiscovery="true" value="-std=gnu99" valueType="string"/>
@@ -1599,6 +1601,8 @@
<listOptionValue builtIn="false" value="RTOS"/>
<listOptionValue builtIn="false" value="DUET3_V06"/>
<listOptionValue builtIn="false" value="_XOPEN_SOURCE"/>
+ <listOptionValue builtIn="false" value="LWIP_GMAC_TASK=1"/>
+ <listOptionValue builtIn="false" value="DEBUG"/>
</option>
<option id="gnu.cpp.compiler.option.dialect.std.1952551090" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.default" valueType="enumerated"/>
<option id="gnu.cpp.compiler.option.dialect.flags.832664520" name="Other dialect flags" superClass="gnu.cpp.compiler.option.dialect.flags" useByScannerDiscovery="true" value="-std=gnu++17" valueType="string"/>
diff --git a/src/Endstops/SwitchEndstop.h b/src/Endstops/SwitchEndstop.h
index cd4492be..5fb2f623 100644
--- a/src/Endstops/SwitchEndstop.h
+++ b/src/Endstops/SwitchEndstop.h
@@ -46,7 +46,7 @@ private:
inline bool IsTriggered(size_t index) const
{
#if SUPPORT_CAN_EXPANSION
- return (boardNumbers[index] == CanId::MasterAddress) ? ports[index].Read() : states[index] != activeLow;
+ return (boardNumbers[index] == CanId::MasterAddress) ? ports[index].Read() != activeLow : states[index] != activeLow;
#else
return ports[index].Read();
#endif
diff --git a/src/Hardware/IoPorts.cpp b/src/Hardware/IoPorts.cpp
index 7672356d..daf1c54f 100644
--- a/src/Hardware/IoPorts.cpp
+++ b/src/Hardware/IoPorts.cpp
@@ -197,23 +197,20 @@ bool IoPort::Allocate(const char *pn, const StringRef& reply, PinUsedBy neededFo
const char *const fullPinName = pn; // the full pin name less the inversion and pullup flags
#if defined(DUET3)
- uint32_t expansionNumber;
if (isdigit(*pn))
{
- expansionNumber = SafeStrtoul(pn, &pn);
+ const uint32_t expansionNumber = SafeStrtoul(pn, &pn);
if (*pn != '.')
{
reply.printf("Bad pin name '%s'", fullPinName);
return false;
}
+ if (expansionNumber != 0)
+ {
+ reply.printf("Pin '%s': only main board pins allowed here", fullPinName);
+ return false;
+ }
}
- else
- {
- expansionNumber = 0;
- }
-
- //TODO use expansionNumber as part of the logical pin number
- (void)expansionNumber;
#endif
LogicalPin lp;
diff --git a/src/Networking/ESP8266WiFi/WiFiInterface.cpp b/src/Networking/ESP8266WiFi/WiFiInterface.cpp
index 95ff18eb..d1024a9e 100644
--- a/src/Networking/ESP8266WiFi/WiFiInterface.cpp
+++ b/src/Networking/ESP8266WiFi/WiFiInterface.cpp
@@ -469,13 +469,12 @@ void WiFiInterface::Stop()
}
}
-void WiFiInterface::Spin(bool full)
+void WiFiInterface::Spin()
{
// Main state machine.
switch (state)
{
case NetworkState::starting1:
- if (full)
{
// The ESP toggles CS before it has finished starting up, so don't look at the CS signal too soon
const uint32_t now = millis();
@@ -488,7 +487,6 @@ void WiFiInterface::Spin(bool full)
break;
case NetworkState::starting2:
- if (full)
{
// See if the ESP8266 has kept its pins at their stable values for long enough
const uint32_t now = millis();
@@ -533,93 +531,90 @@ void WiFiInterface::Spin(bool full)
break;
case NetworkState::disabled:
- if (full && uploader != nullptr)
+ if (uploader != nullptr)
{
uploader->Spin();
}
break;
case NetworkState::active:
- if (full)
+ if (espStatusChanged && digitalRead(EspDataReadyPin))
{
- if (espStatusChanged && digitalRead(EspDataReadyPin))
+ if (reprap.Debug(moduleNetwork))
{
- if (reprap.Debug(moduleNetwork))
- {
- debugPrintf("ESP reported status change\n");
- }
- GetNewStatus();
+ debugPrintf("ESP reported status change\n");
}
- else if ( currentMode != requestedMode
- && currentMode != WiFiState::connecting
- && currentMode != WiFiState::reconnecting
- && currentMode != WiFiState::autoReconnecting
- )
+ GetNewStatus();
+ }
+ else if ( currentMode != requestedMode
+ && currentMode != WiFiState::connecting
+ && currentMode != WiFiState::reconnecting
+ && currentMode != WiFiState::autoReconnecting
+ )
+ {
+ // Tell the wifi module to change mode
+ int32_t rslt = ResponseUnknownError;
+ if (currentMode != WiFiState::idle)
{
- // Tell the wifi module to change mode
- int32_t rslt = ResponseUnknownError;
- if (currentMode != WiFiState::idle)
- {
- // We must set WiFi module back to idle before changing to the new state
- rslt = SendCommand(NetworkCommand::networkStop, 0, 0, nullptr, 0, nullptr, 0);
- }
- else if (requestedMode == WiFiState::connected)
- {
- rslt = SendCommand(NetworkCommand::networkStartClient, 0, 0, requestedSsid, SsidLength, nullptr, 0);
- }
- else if (requestedMode == WiFiState::runningAsAccessPoint)
- {
- rslt = SendCommand(NetworkCommand::networkStartAccessPoint, 0, 0, nullptr, 0, nullptr, 0);
- }
+ // We must set WiFi module back to idle before changing to the new state
+ rslt = SendCommand(NetworkCommand::networkStop, 0, 0, nullptr, 0, nullptr, 0);
+ }
+ else if (requestedMode == WiFiState::connected)
+ {
+ rslt = SendCommand(NetworkCommand::networkStartClient, 0, 0, requestedSsid, SsidLength, nullptr, 0);
+ }
+ else if (requestedMode == WiFiState::runningAsAccessPoint)
+ {
+ rslt = SendCommand(NetworkCommand::networkStartAccessPoint, 0, 0, nullptr, 0, nullptr, 0);
+ }
- if (rslt >= 0)
- {
- state = NetworkState::changingMode;
- }
- else
- {
- Stop();
- platform.MessageF(NetworkInfoMessage, "Failed to change WiFi mode (code %" PRIi32 ")\n", rslt);
- }
+ if (rslt >= 0)
+ {
+ state = NetworkState::changingMode;
}
- else if (currentMode == WiFiState::connected || currentMode == WiFiState::runningAsAccessPoint)
+ else
+ {
+ Stop();
+ platform.MessageF(NetworkInfoMessage, "Failed to change WiFi mode (code %" PRIi32 ")\n", rslt);
+ }
+ }
+ else if (currentMode == WiFiState::connected || currentMode == WiFiState::runningAsAccessPoint)
+ {
+ // Find the next socket to poll
+ const size_t startingSocket = currentSocket;
+ do
{
- // Find the next socket to poll
- const size_t startingSocket = currentSocket;
- do
+ if (sockets[currentSocket]->NeedsPolling())
{
- if (sockets[currentSocket]->NeedsPolling())
- {
- break;
- }
- ++currentSocket;
- if (currentSocket == NumWiFiTcpSockets)
- {
- currentSocket = 0;
- }
- } while (currentSocket != startingSocket);
-
- // Either the current socket needs polling, or no sockets do but we must still poll one of them to get notified of any new connections
- sockets[currentSocket]->Poll(full);
+ break;
+ }
++currentSocket;
if (currentSocket == NumWiFiTcpSockets)
{
currentSocket = 0;
}
+ } while (currentSocket != startingSocket);
+
+ // Either the current socket needs polling, or no sockets do but we must still poll one of them to get notified of any new connections
+ sockets[currentSocket]->Poll();
+ ++currentSocket;
+ if (currentSocket == NumWiFiTcpSockets)
+ {
+ currentSocket = 0;
+ }
- // Check if the data port needs to be closed
- if (closeDataPort)
+ // Check if the data port needs to be closed
+ if (closeDataPort)
+ {
+ for (WiFiSocket *s : sockets)
{
- for (WiFiSocket *s : sockets)
+ if (s->GetProtocol() == FtpDataProtocol)
{
- if (s->GetProtocol() == FtpDataProtocol)
+ if (!s->IsClosing())
{
- if (!s->IsClosing())
- {
- TerminateDataPort();
- }
- break;
+ TerminateDataPort();
}
+ break;
}
}
}
@@ -628,7 +623,7 @@ void WiFiInterface::Spin(bool full)
case NetworkState::changingMode:
// Here when we have asked the ESP to change mode. Don't leave this state until we have a new status report from the ESP.
- if (full && espStatusChanged && digitalRead(EspDataReadyPin))
+ if (espStatusChanged && digitalRead(EspDataReadyPin))
{
GetNewStatus();
switch (currentMode)
@@ -695,19 +690,16 @@ void WiFiInterface::Spin(bool full)
}
}
- if (full)
+ // Check for debug info received from the WiFi module
+ if (debugPrintPending)
{
- // Check for debug info received from the WiFi module
- if (debugPrintPending)
+ if (reprap.Debug(moduleWiFi))
{
- if (reprap.Debug(moduleWiFi))
- {
- debugMessageBuffer[debugMessageChars] = 0;
- debugPrintf("WiFi: %s\n", debugMessageBuffer);
- }
- debugMessageChars = 0;
- debugPrintPending = false;
+ debugMessageBuffer[debugMessageChars] = 0;
+ debugPrintf("WiFi: %s\n", debugMessageBuffer);
}
+ debugMessageChars = 0;
+ debugPrintPending = false;
}
}
diff --git a/src/Networking/ESP8266WiFi/WiFiInterface.h b/src/Networking/ESP8266WiFi/WiFiInterface.h
index 6656967a..7b7bbc72 100644
--- a/src/Networking/ESP8266WiFi/WiFiInterface.h
+++ b/src/Networking/ESP8266WiFi/WiFiInterface.h
@@ -42,7 +42,7 @@ public:
void Init() override;
void Activate() override;
void Exit() override;
- void Spin(bool full) override;
+ void Spin() override;
void Diagnostics(MessageType mtype) override;
void Start();
void Stop();
diff --git a/src/Networking/ESP8266WiFi/WiFiSocket.cpp b/src/Networking/ESP8266WiFi/WiFiSocket.cpp
index 5fbe6d45..16cfb26b 100644
--- a/src/Networking/ESP8266WiFi/WiFiSocket.cpp
+++ b/src/Networking/ESP8266WiFi/WiFiSocket.cpp
@@ -114,7 +114,7 @@ void WiFiSocket::Taken(size_t len)
}
// Poll a socket to see if it needs to be serviced
-void WiFiSocket::Poll(bool full)
+void WiFiSocket::Poll()
{
// Get the socket status
Receiver<ConnStatusResponse> resp;
@@ -161,7 +161,7 @@ void WiFiSocket::Poll(bool full)
// no break
case ConnState::connected:
- if (full && state != SocketState::connected)
+ if (state != SocketState::connected)
{
// It's a new connection
if (reprap.Debug(moduleNetwork))
diff --git a/src/Networking/ESP8266WiFi/WiFiSocket.h b/src/Networking/ESP8266WiFi/WiFiSocket.h
index 02b87948..d9fb953c 100644
--- a/src/Networking/ESP8266WiFi/WiFiSocket.h
+++ b/src/Networking/ESP8266WiFi/WiFiSocket.h
@@ -21,7 +21,7 @@ public:
WiFiSocket(NetworkInterface *iface);
void Init(SocketNumber n);
int State() const { return (int)state; } // used only for reporting debug info, hence the 'int' return
- void Poll(bool full);
+ void Poll();
void Close();
bool IsClosing() const { return (state == SocketState::closing); }
void Terminate();
diff --git a/src/Networking/LwipEthernet/GMAC/ethernet_sam.cpp b/src/Networking/LwipEthernet/GMAC/ethernet_sam.cpp
index a1ac7db8..e706a153 100644
--- a/src/Networking/LwipEthernet/GMAC/ethernet_sam.cpp
+++ b/src/Networking/LwipEthernet/GMAC/ethernet_sam.cpp
@@ -59,8 +59,6 @@ extern "C" {
#include "lwip/stats.h"
#include "lwip/sys.h"
#include "lwip/tcp.h"
-#include "lwip/tcp.h"
-#include "lwip/tcpip.h"
#include "netif/etharp.h"
/* Global variable containing MAC Config (hw addr, IP, GW, ...) */
@@ -223,6 +221,7 @@ void ethernet_task(void)
ethernet_timers_update();
}
+#if !LWIP_GMAC_TASK
/*
* \brief Sets the EMAC RX callback. It will be called when a new packet
* can be processed and should be called with a NULL parameter inside
@@ -234,6 +233,7 @@ void ethernet_set_rx_callback(gmac_dev_tx_cb_t callback)
{
ethernetif_set_rx_callback(callback);
}
+#endif
/*
* \brief Returns the current IP address
diff --git a/src/Networking/LwipEthernet/GMAC/ethernet_sam.h b/src/Networking/LwipEthernet/GMAC/ethernet_sam.h
index 0532dc88..23266cf3 100644
--- a/src/Networking/LwipEthernet/GMAC/ethernet_sam.h
+++ b/src/Networking/LwipEthernet/GMAC/ethernet_sam.h
@@ -72,11 +72,12 @@ void ethernet_timers_update(void);
// Reads all stored network packets and processes them
void ethernet_task(void);
+#if !LWIP_GMAC_TASK
// Set the RX callback for incoming network packets
void ethernet_set_rx_callback(gmac_dev_tx_cb_t callback);
+#endif
// Returns the network interface's current IPv4 address
void ethernet_get_ipaddress(IPAddress& ipAddress, IPAddress& netMask, IPAddress& gateWay);
-
#endif /* ETHERNET_SAM_H_INCLUDED */
diff --git a/src/Networking/LwipEthernet/GMAC/same70_gmac.cpp b/src/Networking/LwipEthernet/GMAC/same70_gmac.cpp
index 12f070c8..895f7d22 100644
--- a/src/Networking/LwipEthernet/GMAC/same70_gmac.cpp
+++ b/src/Networking/LwipEthernet/GMAC/same70_gmac.cpp
@@ -3,39 +3,29 @@
*
* \brief GMAC (Gigabit MAC) driver for lwIP.
*
- * Copyright (c) 2015-2016 Atmel Corporation. All rights reserved.
+ * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
*
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 3. The name of Atmel may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * 4. This software may only be redistributed and used in connection with an
- * Atmel microcontroller product.
- *
- * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
- * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
@@ -48,29 +38,40 @@
extern "C" {
#include "ethernet_phy.h"
+#include "lwip/opt.h"
+#include "lwip/sys.h"
#include "lwip/def.h"
#include "lwip/mem.h"
-#include "lwip/opt.h"
#include "lwip/pbuf.h"
-#include "lwip/snmp.h"
#include "lwip/stats.h"
-#include "lwip/sys.h"
+#include "lwip/snmp.h"
#include "netif/etharp.h"
}
#define __nocache __attribute__((section(".ram_nocache")))
+extern void delay(uint32_t ms);
+
#if LWIP_GMAC_TASK
// We can't #include RepRapFirmware.h here because that leads to a duplicate definition of ERR_TIMEOUT
#include <RTOSIface/RTOSIface.h>
#include <TaskPriorities.h>
-constexpr size_t EthernetTaskStackWords = 200;
+extern Mutex lwipMutex;
+
+constexpr size_t EthernetTaskStackWords = 250;
static Task<EthernetTaskStackWords> ethernetTask;
#endif
+// Error counters
+unsigned int rxErrorCount;
+unsigned int rxBuffersNotFullyPopulatedCount;
+unsigned int txErrorCount;
+unsigned int txBufferNotFreeCount;
+unsigned int txBufferTooShortCount;
+
/** Network interface identifier. */
#define IFNAME0 'e'
#define IFNAME1 'n'
@@ -123,9 +124,9 @@ struct gmac_device {
* of the address shall be set to 0.
*/
/** Pointer to Rx descriptor list (must be 8-byte aligned). */
- gmac_rx_descriptor_t rx_desc[GMAC_RX_BUFFERS];
+ volatile gmac_rx_descriptor_t rx_desc[GMAC_RX_BUFFERS];
/** Pointer to Tx descriptor list (must be 8-byte aligned). */
- gmac_tx_descriptor_t tx_desc[GMAC_TX_BUFFERS];
+ volatile gmac_tx_descriptor_t tx_desc[GMAC_TX_BUFFERS];
/** RX pbuf pointer list. */
struct pbuf *rx_pbuf[GMAC_RX_BUFFERS];
/** TX buffers. */
@@ -158,6 +159,8 @@ static uint8_t gs_uc_mac_address[] =
ETHERNET_CONF_ETHADDR5
};
+static bool rxPbufsFullyPopulated = false;
+
#if LWIP_STATS
/** Used to compute lwIP bandwidth. */
uint32_t lwip_tx_count = 0;
@@ -166,7 +169,9 @@ uint32_t lwip_tx_rate = 0;
uint32_t lwip_rx_rate = 0;
#endif
-static gmac_dev_tx_cb_t gmac_rx_cb = NULL;
+#if !LWIP_GMAC_TASK
+static gmac_dev_tx_cb_t gmac_rx_cb = nullptr;
+#endif
/**
* \brief GMAC interrupt handler.
@@ -190,7 +195,7 @@ void GMAC_Handler(void)
ul_isr = gmac_get_interrupt_status(GMAC);
/* RX interrupts. */
- if ((ul_isr & GMAC_INT_GROUP) != 0 && gmac_rx_cb != NULL)
+ if ((ul_isr & GMAC_INT_GROUP) != 0 && gmac_rx_cb != nullptr)
{
gmac_rx_cb(ul_isr);
}
@@ -207,21 +212,25 @@ void GMAC_Handler(void)
* (since the lsb are used as status bits by GMAC).
*
* \param p_gmac_dev Pointer to driver data structure.
+ * \param startAt The index to start populating from
*/
-static void gmac_rx_populate_queue(struct gmac_device *p_gmac_dev)
+static void gmac_rx_populate_queue(struct gmac_device *p_gmac_dev, uint32_t startAt)
{
- uint32_t ul_index = 0;
- struct pbuf *p = 0;
+ uint32_t ul_index = startAt;
/* Set up the RX descriptors. */
- for (ul_index = 0; ul_index < GMAC_RX_BUFFERS; ul_index++) {
- if (p_gmac_dev->rx_pbuf[ul_index] == 0) {
-
+ do
+ {
+ if (p_gmac_dev->rx_pbuf[ul_index] == nullptr)
+ {
/* Allocate a new pbuf with the maximum size. */
- p = pbuf_alloc(PBUF_RAW, (u16_t) GMAC_FRAME_LENTGH_MAX, PBUF_POOL);
- if (p == NULL) {
+ pbuf * const p = pbuf_alloc(PBUF_RAW, (u16_t) GMAC_FRAME_LENTGH_MAX, PBUF_POOL);
+ if (p == nullptr)
+ {
LWIP_DEBUGF(NETIF_DEBUG, ("gmac_rx_populate_queue: pbuf allocation failure\n"));
- break;
+ rxPbufsFullyPopulated = false;
+ ++rxBuffersNotFullyPopulatedCount;
+ return;
}
/* Make sure lwIP is well configured so one pbuf can contain the maximum packet size. */
@@ -231,22 +240,35 @@ static void gmac_rx_populate_queue(struct gmac_device *p_gmac_dev)
LWIP_ASSERT("gmac_rx_populate_queue: unaligned p->payload buffer address",
(((uint32_t)p->payload & 0xFFFFFFFC) == (uint32_t)p->payload));
- 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
/* Reset status value. */
p_gmac_dev->rx_desc[ul_index].status.val = 0;
/* 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;
+ }
+
LWIP_DEBUGF(NETIF_DEBUG,
("gmac_rx_populate_queue: new pbuf allocated: %p [idx=%u]\n",
p, ul_index));
}
- }
+
+ ++ul_index;
+ if (ul_index == GMAC_RX_BUFFERS)
+ {
+ ul_index = 0;
+ }
+ } while (ul_index != startAt);
+
+ rxPbufsFullyPopulated = true;
}
/**
@@ -264,15 +286,16 @@ static void gmac_rx_init(struct gmac_device *ps_gmac_dev)
ps_gmac_dev->us_rx_idx = 0;
/* Set up the RX descriptors. */
- for (ul_index = 0; ul_index < GMAC_RX_BUFFERS; ul_index++) {
- ps_gmac_dev->rx_pbuf[ul_index] = 0;
- ps_gmac_dev->rx_desc[ul_index].addr.val = 0;
+ for (ul_index = 0; ul_index < GMAC_RX_BUFFERS; ul_index++)
+ {
+ ps_gmac_dev->rx_pbuf[ul_index] = nullptr;
+ ps_gmac_dev->rx_desc[ul_index].addr.val = GMAC_RXD_OWNERSHIP; // mark it as not free for hardware to use, until we have allocated the pbuf
ps_gmac_dev->rx_desc[ul_index].status.val = 0;
}
ps_gmac_dev->rx_desc[ul_index - 1].addr.val |= GMAC_RXD_WRAP;
/* Build RX buffer and descriptors. */
- gmac_rx_populate_queue(ps_gmac_dev);
+ gmac_rx_populate_queue(ps_gmac_dev, 0);
/* Set receive buffer queue base address pointer. */
gmac_set_rx_queue(GMAC, (uint32_t) &ps_gmac_dev->rx_desc[0]);
@@ -293,8 +316,9 @@ static void gmac_tx_init(struct gmac_device *ps_gmac_dev)
ps_gmac_dev->us_tx_idx = 0;
/* Set up the TX descriptors. */
- for (ul_index = 0; ul_index < GMAC_TX_BUFFERS; ul_index++) {
- ps_gmac_dev->tx_desc[ul_index].addr = (uint32_t)&ps_gmac_dev->tx_buf[ul_index][0];
+ for (ul_index = 0; ul_index < GMAC_TX_BUFFERS; ul_index++)
+ {
+ ps_gmac_dev->tx_desc[ul_index].addr = reinterpret_cast<uint32_t>(&ps_gmac_dev->tx_buf[ul_index][0]);
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;
@@ -378,14 +402,14 @@ static void gmac_low_level_init(struct netif *netif)
* \return ERR_OK if the packet could be sent.
* an err_t value if the packet couldn't be sent.
*/
-static err_t gmac_low_level_output(struct netif *netif, struct pbuf *p)
+static err_t gmac_low_level_output(netif *p_netif, struct pbuf *p)
{
- struct gmac_device *ps_gmac_dev = static_cast<gmac_device *>(netif->state);
- struct pbuf *q = NULL;
- uint8_t *buffer = 0;
+ gmac_device *const ps_gmac_dev = static_cast<gmac_device *>(p_netif->state);
/* Handle GMAC underrun or AHB errors. */
- if (gmac_get_tx_status(GMAC) & GMAC_TX_ERRORS) {
+ if (gmac_get_tx_status(GMAC) & GMAC_TX_ERRORS)
+ {
+ ++txErrorCount;
LWIP_DEBUGF(NETIF_DEBUG, ("gmac_low_level_output: GMAC ERROR, reinit TX...\n"));
gmac_enable_transmit(GMAC, false);
@@ -402,20 +426,36 @@ static err_t gmac_low_level_output(struct netif *netif, struct pbuf *p)
gmac_enable_transmit(GMAC, true);
}
- //TODO check buffer is free!!!
- //TODO what if message is too long?
-
- buffer = (uint8_t*)ps_gmac_dev->tx_desc[ps_gmac_dev->us_tx_idx].addr;
+ while ((ps_gmac_dev->tx_desc[ps_gmac_dev->us_tx_idx].status.val & GMAC_TXD_USED) == 0)
+ {
+ ++txBufferNotFreeCount;
+ delay(1);
+ }
- /* Copy pbuf chain into TX buffer. */
- for (q = p; q != NULL; q = q->next) {
- memcpy(buffer, q->payload, q->len);
- buffer += q->len;
+ // Copy pbuf chain into TX buffer
+ {
+ uint8_t *buffer = reinterpret_cast<uint8_t*>(ps_gmac_dev->tx_desc[ps_gmac_dev->us_tx_idx].addr);
+ size_t totalLength = 0;
+ for (const pbuf *q = p; q != NULL; q = q->next)
+ {
+ totalLength += q->len;
+ if (totalLength > GMAC_TX_UNITSIZE)
+ {
+ ++txBufferTooShortCount;
+ return ERR_BUF;
+ }
+ memcpy(buffer, q->payload, q->len);
+ buffer += q->len;
+ }
}
- /* Set len and mark the buffer to be sent by GMAC. */
- ps_gmac_dev->tx_desc[ps_gmac_dev->us_tx_idx].status.bm.b_len = p->tot_len;
- ps_gmac_dev->tx_desc[ps_gmac_dev->us_tx_idx].status.bm.b_used = 0;
+ // Set length and mark the buffer to be sent by GMAC
+ uint32_t txStat = p->tot_len | GMAC_TXD_LAST;
+ if (ps_gmac_dev->us_tx_idx == GMAC_TX_BUFFERS - 1)
+ {
+ txStat |= GMAC_TXD_WRAP;
+ }
+ ps_gmac_dev->tx_desc[ps_gmac_dev->us_tx_idx].status.val = txStat;
LWIP_DEBUGF(NETIF_DEBUG,
("gmac_low_level_output: DMA buffer sent, size=%d [idx=%u]\n",
@@ -442,50 +482,56 @@ static err_t gmac_low_level_output(struct netif *netif, struct pbuf *p)
* \return a pbuf filled with the received packet (including MAC header).
* 0 on memory error.
*/
-static struct pbuf *gmac_low_level_input(struct netif *netif)
+static pbuf *gmac_low_level_input(struct netif *netif)
{
- struct gmac_device *ps_gmac_dev = static_cast<gmac_device *>(netif->state);
- struct pbuf *p = 0;
- uint32_t length = 0;
- uint32_t ul_index = 0;
- gmac_rx_descriptor_t *p_rx = &ps_gmac_dev->rx_desc[ps_gmac_dev->us_rx_idx];
-
- /* Handle GMAC overrun or AHB errors. */
- if (gmac_get_rx_status(GMAC) & GMAC_RX_ERRORS) {
+ gmac_device *ps_gmac_dev = static_cast<gmac_device *>(netif->state);
+ if (gmac_get_rx_status(GMAC) & GMAC_RX_ERRORS)
+ {
+ // Handle GMAC overrun or AHB errors
+ ++rxErrorCount;
gmac_enable_receive(GMAC, false);
LINK_STATS_INC(link.err);
LINK_STATS_INC(link.drop);
/* Free all RX pbufs. */
- for (ul_index = 0; ul_index < GMAC_RX_BUFFERS; ul_index++) {
- if (ps_gmac_dev->rx_pbuf[ul_index] != 0) {
+ for (uint32_t ul_index = 0; ul_index < GMAC_RX_BUFFERS; ul_index++)
+ {
+ if (ps_gmac_dev->rx_pbuf[ul_index] != 0)
+ {
pbuf_free(ps_gmac_dev->rx_pbuf[ul_index]);
- ps_gmac_dev->rx_pbuf[ul_index] = 0;
+ ps_gmac_dev->rx_pbuf[ul_index] = nullptr;
}
}
- /* Reinit TX descriptors. */
+ /* Reinit RX descriptors. */
gmac_rx_init(ps_gmac_dev);
/* Clear error status. */
gmac_clear_rx_status(GMAC, GMAC_RX_ERRORS);
gmac_enable_receive(GMAC, true);
+ return nullptr;
}
- /* Check that a packet has been received and processed by GMAC. */
- if ((p_rx->addr.val & GMAC_RXD_OWNERSHIP) == GMAC_RXD_OWNERSHIP) {
+ volatile gmac_rx_descriptor_t * const p_rx = &ps_gmac_dev->rx_desc[ps_gmac_dev->us_rx_idx];
+ 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;
+
+ /* 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. */
- length = p_rx->status.val & GMAC_RXD_LEN_MASK;
+ const uint32_t length = p_rx->status.val & GMAC_RXD_LEN_MASK;
/* Fetch pre-allocated pbuf. */
- p = ps_gmac_dev->rx_pbuf[ps_gmac_dev->us_rx_idx];
p->len = length;
- /* Remove this pbuf from its desriptor. */
- ps_gmac_dev->rx_pbuf[ps_gmac_dev->us_rx_idx] = 0;
+ /* Remove this pbuf from its descriptor. */
+ ps_gmac_dev->rx_pbuf[ps_gmac_dev->us_rx_idx] = nullptr;
+ rxPbufsFullyPopulated = false;
LWIP_DEBUGF(NETIF_DEBUG,
("gmac_low_level_input: DMA buffer %p received, size=%u [idx=%u]\n",
@@ -495,12 +541,6 @@ static struct pbuf *gmac_low_level_input(struct netif *netif)
p->tot_len = length;
LINK_STATS_INC(link.recv);
- /* Fill empty descriptors with new pbufs. */
- gmac_rx_populate_queue(ps_gmac_dev);
-
- /* Mark the descriptor ready for transfer. */
- p_rx->addr.val &= ~(GMAC_RXD_OWNERSHIP);
-
ps_gmac_dev->us_rx_idx = (ps_gmac_dev->us_rx_idx + 1) % GMAC_RX_BUFFERS;
#if LWIP_STATS
@@ -508,6 +548,12 @@ static struct pbuf *gmac_low_level_input(struct netif *netif)
#endif
}
+ /* Fill empty descriptors with new pbufs. */
+ if (!rxPbufsFullyPopulated)
+ {
+ gmac_rx_populate_queue(ps_gmac_dev, ps_gmac_dev->us_rx_idx);
+ }
+
return p;
}
@@ -519,16 +565,21 @@ static struct pbuf *gmac_low_level_input(struct netif *netif)
*
* \param pvParameters A pointer to the gmac_device instance.
*/
-extern "C" void gmac_task(void *pvParameters)
+extern "C" [[noreturn]] void gmac_task(void *pvParameters)
{
gmac_device * const ps_gmac_dev = static_cast<gmac_device*>(pvParameters);
+ netif * const p_netif = ps_gmac_dev->netif;
- while (1) {
- /* Process the incoming packets */
- while (ethernetif_input(ps_gmac_dev->netif)) { }
+ while (1)
+ {
+ // Process the incoming packets
+ {
+ MutexLocker lock(lwipMutex);
+ while (ethernetif_input(p_netif)) { }
+ }
- /* Wait for the RX notification from the ISR */
- TaskBase::Take();
+ // Wait for the RX notification from the ISR
+ TaskBase::Take((rxPbufsFullyPopulated) ? 1000 : 20);
}
}
#endif
@@ -549,7 +600,7 @@ bool ethernetif_input(struct netif *netif)
/* Move received packet into a new pbuf. */
p = gmac_low_level_input(netif);
- if (p == NULL)
+ if (p == nullptr)
{
return false;
}
@@ -760,10 +811,12 @@ bool ethernetif_link_established(void)
return true;
}
+#if !LWIP_GMAC_TASK
void ethernetif_set_rx_callback(gmac_dev_tx_cb_t callback)
{
gmac_rx_cb = callback;
}
+#endif
void ethernetif_set_mac_address(const uint8_t macAddress[])
{
@@ -777,7 +830,7 @@ void ethernetif_set_mac_address(const uint8_t macAddress[])
extern "C" u32_t millis();
-u32_t sys_now(void)
+extern "C" u32_t sys_now(void)
{
return millis();
}
diff --git a/src/Networking/LwipEthernet/GMAC/same70_gmac.h b/src/Networking/LwipEthernet/GMAC/same70_gmac.h
index fe263623..7c676ff7 100644
--- a/src/Networking/LwipEthernet/GMAC/same70_gmac.h
+++ b/src/Networking/LwipEthernet/GMAC/same70_gmac.h
@@ -67,8 +67,10 @@ bool ethernetif_establish_link(void); // attempts to establish link and retu
bool ethernetif_link_established(void); // asks the PHY if the link is still up
+#if !LWIP_GMAC_TASK
typedef void (*gmac_dev_tx_cb_t) (uint32_t ul_status); // copied from gmac_raw.h
void ethernetif_set_rx_callback(gmac_dev_tx_cb_t callback);
+#endif
void ethernetif_set_mac_address(const uint8_t macAddress[]);
@@ -78,4 +80,11 @@ void ethernetif_set_mac_address(const uint8_t macAddress[]);
}
#endif
+// Error counters
+extern unsigned int rxErrorCount;
+extern unsigned int rxBuffersNotFullyPopulatedCount;
+extern unsigned int txErrorCount;
+extern unsigned int txBufferNotFreeCount;
+extern unsigned int txBufferTooShortCount;
+
#endif /* ETHERNETIF_H_INCLUDED */
diff --git a/src/Networking/LwipEthernet/Lwip/lwipopts.h b/src/Networking/LwipEthernet/Lwip/lwipopts.h
index 367f37c8..c2c683c6 100644
--- a/src/Networking/LwipEthernet/Lwip/lwipopts.h
+++ b/src/Networking/LwipEthernet/Lwip/lwipopts.h
@@ -56,11 +56,8 @@
* use lwIP facilities.
* Uses Raw API only.
*/
-#ifndef LWIP_GMAC_TASK
-# error LWIP_GMAC_TASK must be defined in compiler settings
-#endif
-#define NO_SYS (!LWIP_GMAC_TASK)
+#define NO_SYS 1
/**
* LWIP_NETIF_STATUS_CALLBACK==1: Support a callback function whenever an interface
@@ -136,7 +133,7 @@
* MEMP_NUM_REASSDATA: the number of IP packets simultaneously queued for
* reassembly (whole packets, not fragments!)
*/
-#define MEMP_NUM_REASSDATA 2
+#define MEMP_NUM_REASSDATA 5
/**
* MEMP_NUM_FRAG_PBUF: the number of IP fragments simultaneously sent
@@ -167,9 +164,9 @@
#define MEMP_NUM_NETCONN 0
/**
- * PBUF_POOL_SIZE: the number of buffers in the pbuf pool.
+ * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. Needs to be enough for IP packet reassembly.
*/
-#define PBUF_POOL_SIZE (GMAC_RX_BUFFERS + 4)
+#define PBUF_POOL_SIZE (GMAC_RX_BUFFERS + GMAC_TX_BUFFERS + 12)
/**
* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool.
diff --git a/src/Networking/LwipEthernet/LwipEthernetInterface.cpp b/src/Networking/LwipEthernet/LwipEthernetInterface.cpp
index c9e14533..f32bf251 100644
--- a/src/Networking/LwipEthernet/LwipEthernetInterface.cpp
+++ b/src/Networking/LwipEthernet/LwipEthernetInterface.cpp
@@ -46,86 +46,91 @@ const unsigned int MdnsTtl = 10 * 60; // same value as on the Duet 0.6/0.8.5
static LwipEthernetInterface *ethernetInterface;
-extern "C"
-{
-static volatile bool lwipLocked = false;
+#if LWIP_GMAC_TASK
+
+# include <RTOSIface/RTOSIface.h>
+Mutex lwipMutex;
-#if !LWIP_GMAC_TASK
-static volatile bool resetCallback = false;
#endif
-// Lock functions for LwIP (LwIP isn't thread-safe when working with the raw API)
-bool LockLWIP()
+extern "C"
{
- if (lwipLocked)
- {
- return false;
- }
- lwipLocked = true;
- return true;
-}
+#if !LWIP_GMAC_TASK
-void UnlockLWIP()
-{
- lwipLocked = false;
-}
+ static volatile bool lwipLocked = false;
+ static volatile bool resetCallback = false;
-// Callback functions for the GMAC driver and for LwIP
+ // Lock functions for LwIP (LwIP isn't thread-safe when working with the raw API)
+ bool LockLWIP()
+ {
+ if (lwipLocked)
+ {
+ return false;
+ }
-#if !LWIP_GMAC_TASK
+ lwipLocked = true;
+ return true;
+ }
-// Called from ISR
-static void ethernet_rx_callback(uint32_t ul_status)
-{
- // Because the LWIP stack can become corrupted if we work with it in parallel,
- // we may have to wait for the next Spin() call to read the next packet.
- if (LockLWIP())
+ void UnlockLWIP()
{
- ethernet_task();
- UnlockLWIP();
+ lwipLocked = false;
}
- else
+
+ // Callback functions for the GMAC driver and for LwIP
+
+ // Called from ISR
+ static void ethernet_rx_callback(uint32_t ul_status)
{
- ethernet_set_rx_callback(nullptr);
- resetCallback = true;
+ // Because the LWIP stack can become corrupted if we work with it in parallel,
+ // we may have to wait for the next Spin() call to read the next packet.
+ if (LockLWIP())
+ {
+ ethernet_task();
+ UnlockLWIP();
+ }
+ else
+ {
+ ethernet_set_rx_callback(nullptr);
+ resetCallback = true;
+ }
}
-}
-#endif
+ #endif
-// Task function to keep the GMAC and LwIP running
-void DoEthernetTask()
-{
- ethernet_task();
+ // Task function to keep the GMAC and LwIP running
+ void DoEthernetTask()
+ {
+ ethernet_task();
#if !LWIP_GMAC_TASK
- if (resetCallback)
- {
- resetCallback = false;
- ethernet_set_rx_callback(&ethernet_rx_callback);
- }
+ if (resetCallback)
+ {
+ resetCallback = false;
+ ethernet_set_rx_callback(&ethernet_rx_callback);
+ }
#endif
-}
+ }
-// Callback functions for LWIP (may be called from ISR)
+ // Callback functions for LWIP (may be called from ISR)
-static err_t conn_accept(void *arg, tcp_pcb *pcb, err_t err)
-{
- LWIP_UNUSED_ARG(arg);
- LWIP_UNUSED_ARG(err);
-
- if (ethernetInterface->ConnectionEstablished(pcb))
+ static err_t conn_accept(void *arg, tcp_pcb *pcb, err_t err)
{
- // A socket has accepted this connection and will deal with it
- return ERR_OK;
- }
+ LWIP_UNUSED_ARG(arg);
+ LWIP_UNUSED_ARG(err);
- tcp_abort(pcb);
- return ERR_ABRT;
-}
+ if (ethernetInterface->ConnectionEstablished(pcb))
+ {
+ // A socket has accepted this connection and will deal with it
+ return ERR_OK;
+ }
-}
+ tcp_abort(pcb);
+ return ERR_ABRT;
+ }
+
+} // end extern "C"
/*-----------------------------------------------------------------------------------*/
@@ -172,9 +177,13 @@ DEFINE_GET_OBJECT_MODEL_TABLE(LwipEthernetInterface)
void LwipEthernetInterface::Init()
{
- interfaceMutex.Create("Lwip");
+ interfaceMutex.Create("LwipIface");
//TODO we don't yet use this mutex anywhere!
+#if LWIP_GMAC_TASK
+ lwipMutex.Create("LwipCore");
+#endif
+
// Clear the PCBs
for (size_t i = 0; i < NumTcpPorts; ++i)
{
@@ -368,7 +377,7 @@ GCodeResult LwipEthernetInterface::GetNetworkState(const StringRef& reply)
void LwipEthernetInterface::Start()
{
#if defined(DUET3)
- digitalWrite(PhyResetPin, true); // being the Ethernet Phy out of reset
+ digitalWrite(PhyResetPin, true); // bring the Ethernet Phy out of reset
#endif
if (initialised)
@@ -409,8 +418,8 @@ void LwipEthernetInterface::Stop()
netif_set_down(&gs_net_if);
#if !LWIP_GMAC_TASK
resetCallback = false;
-#endif
ethernet_set_rx_callback(nullptr);
+#endif
#if defined(DUET3)
pinMode(PhyResetPin, OUTPUT_LOW); // hold the Ethernet Phy chip in reset
@@ -420,10 +429,14 @@ void LwipEthernetInterface::Stop()
}
// Main spin loop. If 'full' is true then we are being called from the main spin loop. If false then we are being called during HSMCI idle time.
-void LwipEthernetInterface::Spin(bool full)
+void LwipEthernetInterface::Spin()
{
+#if LWIP_GMAC_TASK
+ MutexLocker lock(lwipMutex);
+#else
if (LockLWIP()) // basically we can't do anything if we can't interact with LWIP
{
+#endif
switch(state)
{
case NetworkState::enabled:
@@ -456,28 +469,25 @@ void LwipEthernetInterface::Spin(bool full)
break;
case NetworkState::obtainingIP:
- if (full)
+ if (ethernet_link_established())
{
- if (ethernet_link_established())
+ // Check for incoming packets
+ DoEthernetTask();
+
+ // Have we obtained an IP address yet?
+ ethernet_get_ipaddress(ipAddress, netmask, gateway);
+ if (!ipAddress.IsNull())
{
- // Check for incoming packets
- DoEthernetTask();
-
- // Have we obtained an IP address yet?
- ethernet_get_ipaddress(ipAddress, netmask, gateway);
- if (!ipAddress.IsNull())
- {
- // Notify the mDNS responder about this
- state = NetworkState::connected;
+ // Notify the mDNS responder about this
+ state = NetworkState::connected;
// debugPrintf("IP address obtained, network running\n");
- }
}
- else
- {
+ }
+ else
+ {
// debugPrintf("Lost phy link\n");
- TerminateSockets();
- state = NetworkState::establishingLink;
- }
+ TerminateSockets();
+ state = NetworkState::establishingLink;
}
break;
@@ -487,14 +497,11 @@ void LwipEthernetInterface::Spin(bool full)
dhcp_stop(&gs_net_if);
}
- if (full)
- {
- InitSockets();
- RebuildMdnsServices();
- ethernet_get_ipaddress(ipAddress, netmask, gateway);
- platform.MessageF(NetworkInfoMessage, "Ethernet running, IP address = %s\n", IP4String(ipAddress).c_str());
- state = NetworkState::active;
- }
+ InitSockets();
+ RebuildMdnsServices();
+ ethernet_get_ipaddress(ipAddress, netmask, gateway);
+ platform.MessageF(NetworkInfoMessage, "Ethernet running, IP address = %s\n", IP4String(ipAddress).c_str());
+ state = NetworkState::active;
break;
case NetworkState::active:
@@ -505,7 +512,7 @@ void LwipEthernetInterface::Spin(bool full)
DoEthernetTask();
// Poll the next TCP socket
- sockets[nextSocketToPoll]->Poll(full);
+ sockets[nextSocketToPoll]->Poll();
// Move on to the next TCP socket for next time
++nextSocketToPoll;
@@ -520,7 +527,7 @@ void LwipEthernetInterface::Spin(bool full)
TerminateDataPort();
}
}
- else if (full)
+ else
{
// debugPrintf("Lost phy link\n");
TerminateSockets();
@@ -528,8 +535,10 @@ void LwipEthernetInterface::Spin(bool full)
}
break;
}
+#if !LWIP_GMAC_TASK
UnlockLWIP();
}
+#endif
}
void LwipEthernetInterface::Interrupt()
@@ -547,6 +556,7 @@ void LwipEthernetInterface::Diagnostics(MessageType mtype)
{
platform.Message(mtype, "- Ethernet -\n");
platform.MessageF(mtype, "State: %d\n", (int)state);
+ platform.MessageF(mtype, "Error counts: %u %u %u %u %u\n", rxErrorCount, rxBuffersNotFullyPopulatedCount, txErrorCount, txBufferNotFreeCount, txBufferTooShortCount);
platform.Message(mtype, "Socket states:");
for (LwipSocket *s : sockets)
{
@@ -594,7 +604,11 @@ int LwipEthernetInterface::EnableState() const
bool LwipEthernetInterface::InNetworkStack() const
{
+#if LWIP_GMAC_TASK
+ return false;
+#else
return lwipLocked;
+#endif
}
bool LwipEthernetInterface::ConnectionEstablished(tcp_pcb *pcb)
diff --git a/src/Networking/LwipEthernet/LwipEthernetInterface.h b/src/Networking/LwipEthernet/LwipEthernetInterface.h
index 7eacbc29..94ec30e0 100644
--- a/src/Networking/LwipEthernet/LwipEthernetInterface.h
+++ b/src/Networking/LwipEthernet/LwipEthernetInterface.h
@@ -33,7 +33,7 @@ public:
void Init() override;
void Activate() override;
void Exit() override;
- void Spin(bool full) override;
+ void Spin() override;
void Interrupt() override;
void Diagnostics(MessageType mtype) override;
diff --git a/src/Networking/LwipEthernet/LwipSocket.cpp b/src/Networking/LwipEthernet/LwipSocket.cpp
index 786a2db0..69d7bab5 100644
--- a/src/Networking/LwipEthernet/LwipSocket.cpp
+++ b/src/Networking/LwipEthernet/LwipSocket.cpp
@@ -12,6 +12,9 @@
#include "Networking/NetworkBuffer.h"
#include "RepRap.h"
+#if LWIP_GMAC_TASK
+extern Mutex lwipMutex;
+#endif
//***************************************************************************************************
@@ -63,8 +66,10 @@ static err_t conn_sent(void *arg, tcp_pcb *pcb, u16_t len)
return ERR_OK;
}
+#if !LWIP_GMAC_TASK
extern bool LockLWIP();
extern void UnlockLWIP();
+#endif
}
@@ -203,6 +208,9 @@ void LwipSocket::Close()
{
if (state != SocketState::disabled && state != SocketState::listening)
{
+#if LWIP_GMAC_TASK
+ MutexLocker lock(lwipMutex);
+#endif
DiscardReceivedData();
state = SocketState::closing;
whenClosed = millis();
@@ -219,6 +227,9 @@ void LwipSocket::Terminate()
{
if (state != SocketState::disabled)
{
+#if LWIP_GMAC_TASK
+ MutexLocker lock(lwipMutex);
+#endif
if (connectionPcb != nullptr)
{
tcp_err(connectionPcb, nullptr);
@@ -251,11 +262,14 @@ bool LwipSocket::ReadChar(char& c)
{
if (receivedData != nullptr)
{
- const char *data = (char *)receivedData->payload;
+ const char * const data = (const char *)receivedData->payload;
c = data[readIndex++];
if (readIndex >= receivedData->len)
{
+#if LWIP_GMAC_TASK
+ MutexLocker lock(lwipMutex);
+#endif
// We've processed one more pbuf
if (connectionPcb != nullptr)
{
@@ -282,7 +296,7 @@ bool LwipSocket::ReadBuffer(const uint8_t *&buffer, size_t &len)
{
if (receivedData != nullptr)
{
- const uint8_t *data = (const uint8_t *)receivedData->payload;
+ const uint8_t * const data = (const uint8_t *)receivedData->payload;
buffer = &data[readIndex];
len = receivedData->len - readIndex;
return true;
@@ -299,6 +313,9 @@ void LwipSocket::Taken(size_t len)
readIndex += len;
if (readIndex >= receivedData->len)
{
+#if LWIP_GMAC_TASK
+ MutexLocker lock(lwipMutex);
+#endif
// Notify LwIP
if (connectionPcb != nullptr)
{
@@ -316,7 +333,7 @@ void LwipSocket::Taken(size_t len)
}
// Poll a socket to see if it needs to be serviced
-void LwipSocket::Poll(bool full)
+void LwipSocket::Poll()
{
switch (state)
{
@@ -327,27 +344,24 @@ void LwipSocket::Poll(bool full)
case SocketState::connected:
// A connection has been established, but no responder has been found yet
// See if we can assign this socket
- if (full)
+ if (responderFound)
{
- if (responderFound)
+ // Are we still waiting for data to be written?
+ if (whenWritten != 0 && millis() - whenWritten >= MaxWriteTime)
{
- // Are we still waiting for data to be written?
- if (whenWritten != 0 && millis() - whenWritten >= MaxWriteTime)
- {
- Terminate();
- }
+ Terminate();
}
- else
+ }
+ else
+ {
+ // Try to find a responder to deal with this connection
+ if (reprap.GetNetwork().FindResponder(this, protocol))
{
- // Try to find a responder to deal with this connection
- if (reprap.GetNetwork().FindResponder(this, protocol))
- {
- responderFound = true;
- }
- else if (millis() - whenConnected >= FindResponderTimeout)
- {
- Terminate();
- }
+ responderFound = true;
+ }
+ else if (millis() - whenConnected >= FindResponderTimeout)
+ {
+ Terminate();
}
}
break;
@@ -356,28 +370,25 @@ void LwipSocket::Poll(bool full)
case SocketState::closing:
// The connection is being closed, but we may be waiting for sent data to be ACKed
// or for the received data to be processed by a NetworkResponder
- if (full)
+ if (unAcked == 0 || millis() - whenClosed > MaxAckTime)
{
- if (unAcked == 0 || millis() - whenClosed > MaxAckTime)
+ if (connectionPcb != nullptr)
{
- if (connectionPcb != nullptr)
+ tcp_err(connectionPcb, nullptr);
+ tcp_recv(connectionPcb, nullptr);
+ tcp_sent(connectionPcb, nullptr);
+ if (unAcked == 0)
{
- tcp_err(connectionPcb, nullptr);
- tcp_recv(connectionPcb, nullptr);
- tcp_sent(connectionPcb, nullptr);
- if (unAcked == 0)
- {
- tcp_close(connectionPcb);
- }
- else
- {
- tcp_abort(connectionPcb);
- }
- connectionPcb = nullptr;
+ tcp_close(connectionPcb);
}
-
- state = (localPort == 0) ? SocketState::disabled : SocketState::listening;
+ else
+ {
+ tcp_abort(connectionPcb);
+ }
+ connectionPcb = nullptr;
}
+
+ state = (localPort == 0) ? SocketState::disabled : SocketState::listening;
}
break;
@@ -401,13 +412,19 @@ void LwipSocket::DiscardReceivedData()
// Send the data, returning the length buffered
size_t LwipSocket::Send(const uint8_t *data, size_t length)
{
+#if LWIP_GMAC_TASK
+ MutexLocker lock(lwipMutex);
+#else
// This is always called outside the EthernetInterface::Spin method. Wait for pending ISRs to finish
while (!LockLWIP()) { }
+#endif
if (!CanSend())
{
// Don't bother if we cannot send anything at all+
+#if !LWIP_GMAC_TASK
UnlockLWIP();
+#endif
return 0;
}
@@ -429,7 +446,9 @@ size_t LwipSocket::Send(const uint8_t *data, size_t length)
if (ERR_IS_FATAL(err))
{
Terminate();
+#if !LWIP_GMAC_TASK
UnlockLWIP();
+#endif
return 0;
}
else if (err == ERR_MEM)
@@ -438,7 +457,9 @@ size_t LwipSocket::Send(const uint8_t *data, size_t length)
{
// The buffers are full - try again later
tcp_output(connectionPcb);
+#if !LWIP_GMAC_TASK
UnlockLWIP();
+#endif
return 0;
}
bytesToSend /= 2;
@@ -450,7 +471,9 @@ size_t LwipSocket::Send(const uint8_t *data, size_t length)
if (ERR_IS_FATAL(tcp_output(connectionPcb)))
{
Terminate();
+#if !LWIP_GMAC_TASK
UnlockLWIP();
+#endif
return 0;
}
@@ -458,11 +481,15 @@ size_t LwipSocket::Send(const uint8_t *data, size_t length)
whenWritten = millis();
unAcked += bytesToSend;
+#if !LWIP_GMAC_TASK
UnlockLWIP();
+#endif
return bytesToSend;
}
+#if !LWIP_GMAC_TASK
UnlockLWIP();
+#endif
return 0;
}
diff --git a/src/Networking/LwipEthernet/LwipSocket.h b/src/Networking/LwipEthernet/LwipSocket.h
index 31c5d794..5f9b1f0f 100644
--- a/src/Networking/LwipEthernet/LwipSocket.h
+++ b/src/Networking/LwipEthernet/LwipSocket.h
@@ -34,7 +34,7 @@ public:
// Inherited members of the Socket class
void Init(SocketNumber s, Port serverPort, NetworkProtocol p);
void TerminateAndDisable() override;
- void Poll(bool full) override;
+ void Poll() override;
void Close() override;
bool IsClosing() const { return (state == SocketState::closing); }
void Terminate() override;
diff --git a/src/Networking/Network.cpp b/src/Networking/Network.cpp
index feae781b..038078a4 100644
--- a/src/Networking/Network.cpp
+++ b/src/Networking/Network.cpp
@@ -307,7 +307,7 @@ extern "C" [[noreturn]]void NetworkLoop(void *)
{
for (;;)
{
- reprap.GetNetwork().Spin(true);
+ reprap.GetNetwork().Spin();
RTOSIface::Yield();
}
}
@@ -366,32 +366,29 @@ bool Network::IsWiFiInterface(unsigned int interface) const
}
// Main spin loop. If 'full' is true then we are being called from the main spin loop. If false then we are being called during HSMCI idle time.
-void Network::Spin(bool full)
+void Network::Spin()
{
const uint32_t lastTime = StepTimer::GetTimerTicks();
// Keep the network modules running
for (NetworkInterface *iface : interfaces)
{
- iface->Spin(full);
+ iface->Spin();
}
// Poll the responders
- if (full)
+ NetworkResponder *nr = nextResponderToPoll;
+ bool doneSomething = false;
+ do
{
- NetworkResponder *nr = nextResponderToPoll;
- bool doneSomething = false;
- do
+ if (nr == nullptr)
{
- if (nr == nullptr)
- {
- nr = responders; // 'responders' can't be null at this point
- }
- doneSomething = nr->Spin();
- nr = nr->GetNext();
- } while (!doneSomething && nr != nextResponderToPoll);
- nextResponderToPoll = nr;
- }
+ nr = responders; // 'responders' can't be null at this point
+ }
+ doneSomething = nr->Spin();
+ nr = nr->GetNext();
+ } while (!doneSomething && nr != nextResponderToPoll);
+ nextResponderToPoll = nr;
HttpResponder::CheckSessions(); // time out any sessions that have gone away
diff --git a/src/Networking/Network.h b/src/Networking/Network.h
index a0b21561..403e65cb 100644
--- a/src/Networking/Network.h
+++ b/src/Networking/Network.h
@@ -58,7 +58,7 @@ public:
void Init();
void Activate();
void Exit();
- void Spin(bool full);
+ void Spin();
void Interrupt();
void Diagnostics(MessageType mtype);
bool InNetworkStack() const;
diff --git a/src/Networking/NetworkInterface.h b/src/Networking/NetworkInterface.h
index ba417d05..335041d6 100644
--- a/src/Networking/NetworkInterface.h
+++ b/src/Networking/NetworkInterface.h
@@ -17,7 +17,7 @@ public:
virtual void Init() = 0;
virtual void Activate() = 0;
virtual void Exit() = 0;
- virtual void Spin(bool full) = 0;
+ virtual void Spin() = 0;
virtual void Interrupt() { };
virtual void Diagnostics(MessageType mtype) = 0;
diff --git a/src/Networking/Socket.h b/src/Networking/Socket.h
index 5a0b22ce..c866e770 100644
--- a/src/Networking/Socket.h
+++ b/src/Networking/Socket.h
@@ -30,7 +30,7 @@ public:
Port GetRemotePort() const { return remotePort; }
NetworkProtocol GetProtocol() const { return protocol; }
- virtual void Poll(bool full) = 0;
+ virtual void Poll() = 0;
virtual void Close() = 0;
virtual void Terminate() = 0;
virtual void TerminateAndDisable() = 0;
diff --git a/src/Networking/W5500Ethernet/W5500Interface.cpp b/src/Networking/W5500Ethernet/W5500Interface.cpp
index 0afe772d..f6379a89 100644
--- a/src/Networking/W5500Ethernet/W5500Interface.cpp
+++ b/src/Networking/W5500Ethernet/W5500Interface.cpp
@@ -247,8 +247,8 @@ void W5500Interface::Stop()
}
}
-// Main spin loop. If 'full' is true then we are being called from the main spin loop. If false then we are being called during HSMCI idle time.
-void W5500Interface::Spin(bool full)
+// Main spin loop
+void W5500Interface::Spin()
{
switch(state)
{
@@ -262,7 +262,7 @@ void W5500Interface::Spin(bool full)
{
MutexLocker lock(interfaceMutex);
- if (full && wizphy_getphylink() == PHY_LINK_ON)
+ if (wizphy_getphylink() == PHY_LINK_ON)
{
usingDhcp = ipAddress.IsNull();
if (usingDhcp)
@@ -283,7 +283,6 @@ void W5500Interface::Spin(bool full)
break;
case NetworkState::obtainingIP:
- if (full)
{
MutexLocker lock(interfaceMutex);
@@ -314,13 +313,10 @@ void W5500Interface::Spin(bool full)
break;
case NetworkState::connected:
- if (full)
- {
- InitSockets();
- platform.MessageF(NetworkInfoMessage, "Network running, IP address = %s\n", IP4String(ipAddress).c_str());
- mdnsResponder->Announce();
- state = NetworkState::active;
- }
+ InitSockets();
+ platform.MessageF(NetworkInfoMessage, "Network running, IP address = %s\n", IP4String(ipAddress).c_str());
+ mdnsResponder->Announce();
+ state = NetworkState::active;
break;
case NetworkState::active:
@@ -331,7 +327,7 @@ void W5500Interface::Spin(bool full)
if (wizphy_getphylink() == PHY_LINK_ON)
{
// Maintain DHCP
- if (full && usingDhcp)
+ if (usingDhcp)
{
const uint32_t now = millis();
if (now - lastTickMillis >= 1000)
@@ -349,14 +345,11 @@ void W5500Interface::Spin(bool full)
}
// Poll the next TCP socket
- sockets[nextSocketToPoll]->Poll(full);
+ sockets[nextSocketToPoll]->Poll();
// Keep mDNS alive
- mdnsSocket->Poll(full);
- if (full)
- {
- mdnsResponder->Spin();
- }
+ mdnsSocket->Poll();
+ mdnsResponder->Spin();
// Move on to the next TCP socket for next time
++nextSocketToPoll;
@@ -365,7 +358,7 @@ void W5500Interface::Spin(bool full)
nextSocketToPoll = 0;
}
}
- else if (full)
+ else
{
// debugPrintf("Lost phy link\n");
if (usingDhcp)
diff --git a/src/Networking/W5500Ethernet/W5500Interface.h b/src/Networking/W5500Ethernet/W5500Interface.h
index 870fa7dc..d191c492 100644
--- a/src/Networking/W5500Ethernet/W5500Interface.h
+++ b/src/Networking/W5500Ethernet/W5500Interface.h
@@ -37,7 +37,7 @@ public:
void Init() override;
void Activate() override;
void Exit() override;
- void Spin(bool full) override;
+ void Spin() override;
void Diagnostics(MessageType mtype) override;
GCodeResult EnableInterface(int mode, const StringRef& ssid, const StringRef& reply) override; // enable or disable the network
diff --git a/src/Networking/W5500Ethernet/W5500Socket.cpp b/src/Networking/W5500Ethernet/W5500Socket.cpp
index e07ce8ce..6dd7a133 100644
--- a/src/Networking/W5500Ethernet/W5500Socket.cpp
+++ b/src/Networking/W5500Ethernet/W5500Socket.cpp
@@ -172,7 +172,7 @@ void W5500Socket::Taken(size_t len)
}
// Poll a socket to see if it needs to be serviced
-void W5500Socket::Poll(bool full)
+void W5500Socket::Poll()
{
if (state != SocketState::disabled)
{
@@ -205,7 +205,7 @@ void W5500Socket::Poll(bool full)
whenConnected = millis();
}
- if (full && state == SocketState::listening) // if it is a new connection
+ if (state == SocketState::listening) // if it is a new connection
{
if (reprap.GetNetwork().FindResponder(this, protocol))
{
diff --git a/src/Networking/W5500Ethernet/W5500Socket.h b/src/Networking/W5500Ethernet/W5500Socket.h
index bc00827f..c0750289 100644
--- a/src/Networking/W5500Ethernet/W5500Socket.h
+++ b/src/Networking/W5500Ethernet/W5500Socket.h
@@ -19,7 +19,7 @@ public:
W5500Socket(NetworkInterface *iface);
void Init(SocketNumber s, Port serverPort, NetworkProtocol p);
- void Poll(bool full) override;
+ void Poll() override;
void Close() override;
void Terminate() override;
void TerminateAndDisable() override;
diff --git a/src/Platform.cpp b/src/Platform.cpp
index a19e4695..1b66e040 100644
--- a/src/Platform.cpp
+++ b/src/Platform.cpp
@@ -564,10 +564,10 @@ void Platform::Init()
// If MISO from a MAX31856 board breaks after initialising the MAX31856 then if MISO floats low and reads as all zeros, this looks like a temperature of 0C and no error.
// Enable the pullup resistor, with luck this will make it float high instead.
-#if defined(APIN_USART_SSPI_MISO)
- pinMode(APIN_USART_SSPI_MISO, INPUT_PULLUP);
-#elif defined(APIN_SHARED_SPI_MISO)
+#if SAM3XA
pinMode(APIN_SHARED_SPI_MISO, INPUT_PULLUP);
+#else
+ pinMode(APIN_USART_SSPI_MISO, INPUT_PULLUP);
#endif
#ifdef PCCB
@@ -1951,7 +1951,8 @@ void Platform::Diagnostics(MessageType mtype)
MessageF(mtype, "Last software reset %s, reason: %s%s, spinning module %s, available RAM %" PRIu32 " bytes (slot %d)\n",
scratchString.c_str(),
(srdBuf[slot].resetReason & (uint32_t)SoftwareResetReason::deliberate) ? "deliberate " : "",
- reasonText, moduleName[srdBuf[slot].resetReason & 0x1F], srdBuf[slot].neverUsedRam, slot);
+ reasonText,
+ GetModuleName(srdBuf[slot].resetReason & 0x1F), srdBuf[slot].neverUsedRam, slot);
// Our format buffer is only 256 characters long, so the next 2 lines must be written separately
MessageF(mtype,
"Software reset code 0x%04x HFSR 0x%08" PRIx32 " CFSR 0x%08" PRIx32 " ICSR 0x%08" PRIx32 " BFAR 0x%08" PRIx32 " SP 0x%08" PRIx32 " Task 0x%08" PRIx32 "\n",
diff --git a/src/RepRap.cpp b/src/RepRap.cpp
index 940a22b5..299bab24 100644
--- a/src/RepRap.cpp
+++ b/src/RepRap.cpp
@@ -579,7 +579,7 @@ void RepRap::PrintDebug(MessageType mt)
{
if ((debug & (1u << i)) != 0)
{
- platform->MessageF((MessageType)(mt | PushFlag), " %s(%u)", moduleName[i], i);
+ platform->MessageF((MessageType)(mt | PushFlag), " %s(%u)", GetModuleName(i), i);
}
}
@@ -588,7 +588,7 @@ void RepRap::PrintDebug(MessageType mt)
{
if ((debug & (1u << i)) == 0)
{
- platform->MessageF((MessageType)(mt | PushFlag), " %s(%u)", moduleName[i], i);
+ platform->MessageF((MessageType)(mt | PushFlag), " %s(%u)", GetModuleName(i), i);
}
}
platform->Message(mt, "\n");
diff --git a/src/RepRapFirmware.cpp b/src/RepRapFirmware.cpp
index cf171c7d..48cd1517 100644
--- a/src/RepRapFirmware.cpp
+++ b/src/RepRapFirmware.cpp
@@ -172,7 +172,7 @@ Licence: GPL
RepRap reprap;
-const char * const moduleName[] =
+static const char * const moduleName[] =
{
"Platform",
"Network",
@@ -196,6 +196,11 @@ const char * const moduleName[] =
static_assert(ARRAY_SIZE(moduleName) == Module::numModules + 1);
+const char *GetModuleName(uint8_t module)
+{
+ return (module < ARRAY_SIZE(moduleName)) ? moduleName[module] : "unknown";
+}
+
// class MillisTimer members
// Start or restart the timer
diff --git a/src/RepRapFirmware.h b/src/RepRapFirmware.h
index 3d1ed488..ef6c0f59 100644
--- a/src/RepRapFirmware.h
+++ b/src/RepRapFirmware.h
@@ -194,10 +194,10 @@ enum Module : uint8_t
moduleDisplay = 15,
moduleLinuxInterface = 16,
numModules = 17, // make this one greater than the last real module number
- noModule = 18
+ noModule = numModules
};
-extern const char * const moduleName[];
+const char *GetModuleName(uint8_t module);
// Warn of what's to come, so we can use pointers and references to classes without including the entire header files
class Network;
diff --git a/src/Storage/CRC32.cpp b/src/Storage/CRC32.cpp
index 1d563def..a69df0fe 100644
--- a/src/Storage/CRC32.cpp
+++ b/src/Storage/CRC32.cpp
@@ -53,17 +53,39 @@ CRC32::CRC32()
Reset();
}
-inline void CRC32::Update(char c)
+void CRC32::Update(char c)
{
crc = (CRC_32_TAB[(crc ^ c) & 0xFF] ^ (crc >> 8));
}
-void CRC32::Update(const char *c, size_t len)
+void CRC32::Update(const char *s, size_t len)
{
- for (size_t i = 0; i < len; ++i)
+ // The speed of this function affects the speed of file uploads, so make it as fast as possible. Sadly the SAME70 doesn't do hardware CRC calculation.
+ // Work on a local copy of the crc to avoid storing it all the time
+ uint32_t locCrc = crc;
+ const char * const end = s + len;
+
+ // Process any bytes at the start until we reach a dword boundary
+ while ((reinterpret_cast<uint32_t>(s) & 3) != 0 && s != end)
+ {
+ locCrc = (CRC_32_TAB[(locCrc ^ *s++) & 0xFF] ^ (locCrc >> 8));
+ }
+
+ const char * const endAligned = s + ((end - s) & ~3);
+ while (s != endAligned)
+ {
+ uint32_t data = *reinterpret_cast<const uint32_t*>(s);
+ s += 4;
+ locCrc = (CRC_32_TAB[(locCrc ^ data) & 0xFF] ^ (locCrc >> 8));
+ locCrc = (CRC_32_TAB[(locCrc ^ (data >> 8)) & 0xFF] ^ (locCrc >> 8));
+ locCrc = (CRC_32_TAB[(locCrc ^ (data >> 16)) & 0xFF] ^ (locCrc >> 8));
+ locCrc = (CRC_32_TAB[(locCrc ^ (data >> 24)) & 0xFF] ^ (locCrc >> 8));
+ }
+ while (s != end)
{
- Update(c[i]);
+ locCrc = (CRC_32_TAB[(locCrc ^ *s++) & 0xFF] ^ (locCrc >> 8));
}
+ crc = locCrc;
}
void CRC32::Reset()
diff --git a/src/Tasks.cpp b/src/Tasks.cpp
index 396fd6e9..57f81e60 100644
--- a/src/Tasks.cpp
+++ b/src/Tasks.cpp
@@ -8,7 +8,6 @@
#include "Tasks.h"
#include "RepRap.h"
#include "Platform.h"
-#include "Storage/CRC32.h"
#include "Hardware/Cache.h"
#include <TaskPriorities.h>
@@ -89,6 +88,7 @@ extern "C" [[noreturn]] void AppMain()
{
pinMode(DiagPin, OUTPUT_LOW); // set up diag LED for debugging and turn it off
+#ifndef DEBUG // don't check the CRC of a debug build because debugger breakpoints mess up the CRC
// Check the integrity of the firmware by checking the firmware CRC
{
#ifdef IFLASH_ADDR
@@ -111,6 +111,7 @@ extern "C" [[noreturn]] void AppMain()
}
}
}
+#endif
// Fill the free memory with a pattern so that we can check for stack usage and memory corruption
char* heapend = sbrk(0);
diff --git a/src/Version.h b/src/Version.h
index b984fb0c..e60bf4bc 100644
--- a/src/Version.h
+++ b/src/Version.h
@@ -20,7 +20,7 @@
#endif
#ifndef DATE
-# define DATE "2019-11-27b2"
+# define DATE "2019-12-01b1"
#endif
#define AUTHORS "reprappro, dc42, chrishamm, t3p3, dnewman, printm3d"