diff options
author | Christian Hammacher <bmasterc@gmail.com> | 2021-10-28 14:58:15 +0300 |
---|---|---|
committer | Christian Hammacher <bmasterc@gmail.com> | 2021-10-28 14:58:15 +0300 |
commit | 8207b22cc13e7893ae1cb43f4aef4a7632cac5b3 (patch) | |
tree | bd49861385980e72aeb6fe16fae0c3acc5895852 | |
parent | 5e9d621403eb54b00a84d4824b75c056121730aa (diff) |
SBC improvements for 3.4-b6
Refactored various parts of the SBC interface
Renamed Linux to SBC in various places
CAN updater checks if file is present on SBC before update
SBC task is only woken up when SPI transfers finish
Bug fix: Codes that were sent back to the SBC (e.g. from USB) caused temp reports to be printed
Bug fix: SBC reconnects could take longer than expected
78 files changed, 2396 insertions, 2349 deletions
@@ -129,7 +129,7 @@ </toolChain> </folderInfo> <sourceEntries> - <entry excluding="src/Duet3Mini|src/Linux|src/Hardware/SAME70|src/Hardware/SAME5x|src/Networking/LwipEthernet|src/Duet3_V06|src/Hardware/ksz8081rna|src/Pccb|src/DuetM|src/Hardware/SAM4S" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/> + <entry excluding="src/SBC|src/Duet3_V06|src/Hardware/SAME70|src/Hardware/SAME5x|src/Hardware/ksz8081rna|src/Duet3Mini|src/Networking/LwipEthernet|src/Pccb|src/Hardware/SAM4S|src/DuetM" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/> </sourceEntries> </configuration> </storageModule> @@ -287,7 +287,7 @@ </toolChain> </folderInfo> <sourceEntries> - <entry excluding="src/Hardware/SAM4E|src/Duet3Mini|src/Linux|src/Hardware/SAME70|src/Hardware/SAME5x|src/Networking/LwipEthernet|src/DuetNG|src/Duet3_V06|src/Hardware/ksz8081rna|src/Networking/ESP8266WiFi|src/Pccb" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> + <entry excluding="src/SBC|src/Duet3_V06|src/Hardware/SAME70|src/Hardware/SAME5x|src/Hardware/ksz8081rna|src/Networking/ESP8266WiFi|src/Duet3Mini|src/Hardware/SAM4E|src/Networking/LwipEthernet|src/Pccb|src/DuetNG" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> </sourceEntries> </configuration> </storageModule> @@ -446,7 +446,7 @@ </toolChain> </folderInfo> <sourceEntries> - <entry excluding="src/Hardware/SAM4E|src/Duet3Mini|src/Linux|src/Hardware/SAME70|src/Hardware/SAME5x|src/Networking/LwipEthernet|src/DuetNG|src/Networking/W5500Ethernet/|src/Duet3_V06|src/Display|src/Hardware/ksz8081rna|src/Networking/ESP8266WiFi|src/DuetM" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> + <entry excluding="src/SBC|src/Hardware/SAME70|src/Hardware/SAME5x|src/Networking/LwipEthernet|src/DuetNG|src/Networking/W5500Ethernet/|src/Duet3_V06|src/Display|src/Hardware/ksz8081rna|src/Networking/ESP8266WiFi|src/Duet3Mini|src/Hardware/SAM4E|src/DuetM" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> </sourceEntries> </configuration> </storageModule> @@ -608,7 +608,7 @@ </toolChain> </folderInfo> <sourceEntries> - <entry excluding="src/Hardware/SAM4E|src/Duet3Mini|/src/Networking/LwipEthernet/Lwip/test|src/DuetNG|src/Networking/W5500Ethernet|src/Display|src/Pccb|/src/Networking/LwipEthernet/Lwip/src/apps/mqtt|src/Networking/LwipEthernet/Lwip/doc|src/Networking/LwipEthernet/Lwip/src/apps/smtp|src/Networking/LwipEthernet/Lwip/src/apps/snmp|src/Networking/LwipEthernet/Lwip/src/apps/httpd|src/Hardware/SAME5x|src/Networking/LwipEthernet/Lwip/src/apps/tftp|src/Networking/LwipEthernet/Lwip/src/netif/ppp|src/Networking/LwipEthernet/Lwip/src/apps/lwiperf|src/Networking/LwipEthernet/Lwip/src/apps/altcp_tls|src/Networking/LwipEthernet/Lwip/src/apps/sntp|src/Networking/LwipEthernet/Lwip/src/apps/http|src/Networking/ESP8266WiFi|src/DuetM|src/Hardware/SAM4S" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/> + <entry excluding="src/Networking/LwipEthernet/Lwip/src/apps/smtp|src/Networking/LwipEthernet/Lwip/src/apps/snmp|src/Networking/LwipEthernet/Lwip/src/apps/httpd|src/Hardware/SAME5x|/src/Networking/LwipEthernet/Lwip/test|src/DuetNG|src/Networking/LwipEthernet/Lwip/src/apps/tftp|src/Networking/W5500Ethernet|src/Networking/LwipEthernet/Lwip/src/netif/ppp|src/Networking/LwipEthernet/Lwip/src/apps/lwiperf|src/Networking/LwipEthernet/Lwip/src/apps/altcp_tls|src/Networking/LwipEthernet/Lwip/src/apps/sntp|src/Display|src/Networking/LwipEthernet/Lwip/src/apps/http|src/Networking/ESP8266WiFi|src/Duet3Mini|src/Hardware/SAM4E|src/Pccb|/src/Networking/LwipEthernet/Lwip/src/apps/mqtt|src/Hardware/SAM4S|src/DuetM|src/Networking/LwipEthernet/Lwip/doc" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/> </sourceEntries> </configuration> </storageModule> @@ -769,7 +769,7 @@ </toolChain> </folderInfo> <sourceEntries> - <entry excluding="src/Hardware/SAM4E|src/Duet3Mini|/src/Networking/LwipEthernet/Lwip/test|src/DuetNG|src/Networking/W5500Ethernet|src/Display|src/Pccb|/src/Networking/LwipEthernet/Lwip/src/apps/mqtt|src/Networking/LwipEthernet/Lwip/doc|src/Networking/LwipEthernet/Lwip/src/apps/smtp|src/Networking/LwipEthernet/Lwip/src/apps/snmp|src/Networking/LwipEthernet/Lwip/src/apps/httpd|src/Hardware/SAME5x|src/Networking/LwipEthernet/Lwip/src/apps/tftp|src/Networking/LwipEthernet/Lwip/src/netif/ppp|src/Networking/LwipEthernet/Lwip/src/apps/lwiperf|src/Networking/LwipEthernet/Lwip/src/apps/altcp_tls|src/Networking/LwipEthernet/Lwip/src/apps/sntp|src/Networking/LwipEthernet/Lwip/src/apps/http|src/Networking/ESP8266WiFi|src/DuetM|src/Hardware/SAM4S" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/> + <entry excluding="src/Networking/LwipEthernet/Lwip/src/apps/smtp|src/Networking/LwipEthernet/Lwip/src/apps/snmp|src/Networking/LwipEthernet/Lwip/src/apps/httpd|src/Hardware/SAME5x|/src/Networking/LwipEthernet/Lwip/test|src/DuetNG|src/Networking/LwipEthernet/Lwip/src/apps/tftp|src/Networking/W5500Ethernet|src/Networking/LwipEthernet/Lwip/src/netif/ppp|src/Networking/LwipEthernet/Lwip/src/apps/lwiperf|src/Networking/LwipEthernet/Lwip/src/apps/altcp_tls|src/Networking/LwipEthernet/Lwip/src/apps/sntp|src/Display|src/Networking/LwipEthernet/Lwip/src/apps/http|src/Networking/ESP8266WiFi|src/Duet3Mini|src/Hardware/SAM4E|src/Pccb|/src/Networking/LwipEthernet/Lwip/src/apps/mqtt|src/Hardware/SAM4S|src/DuetM|src/Networking/LwipEthernet/Lwip/doc" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/> </sourceEntries> </configuration> </storageModule> @@ -931,7 +931,7 @@ </toolChain> </folderInfo> <sourceEntries> - <entry excluding="src/Duet3Mini|src/Hardware/SAME70|src/Hardware/SAME5x|src/Networking/LwipEthernet|src/Networking/W5500Ethernet/|src/Duet3_V06|src/Hardware/ksz8081rna|src/Networking/ESP8266WiFi/|src/Pccb|src/DuetM|src/Hardware/SAM4S" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/> + <entry excluding="src/Duet3_V06|src/Hardware/SAME70|src/Hardware/SAME5x|src/Hardware/ksz8081rna|src/Networking/ESP8266WiFi/|src/Duet3Mini|src/Networking/LwipEthernet|src/Pccb|src/Hardware/SAM4S|src/DuetM|src/Networking/W5500Ethernet/" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/> </sourceEntries> </configuration> </storageModule> @@ -1083,7 +1083,7 @@ </toolChain> </folderInfo> <sourceEntries> - <entry excluding="src/Hardware/SAM4E|src/Networking/LwipEthernet/Lwip/src/apps/snmp|src/Networking/LwipEthernet/Lwip/src/apps/smtp|src/Hardware/SAME70|src/DuetNG|src/Networking/LwipEthernet/Lwip/src/apps/tftp|src/Networking/W5500Ethernet|src/Networking/LwipEthernet/Lwip/src/netif/ppp|src/Networking/LwipEthernet/Lwip/src/apps/lwiperf|src/Networking/LwipEthernet/Lwip/src/apps/altcp_tls|src/Networking/LwipEthernet/Lwip/src/apps/sntp|src/Networking/LwipEthernet/Lwip/src/apps/http|src/Duet3_V06|src/Pccb|src/Networking/LwipEthernet/Lwip/src/apps/mqtt|src/DuetM|src/Networking/LwipEthernet/Lwip/doc|src/Hardware/SAM4S" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/> + <entry excluding="src/Networking/LwipEthernet/Lwip/src/apps/snmp|src/Networking/LwipEthernet/Lwip/src/apps/smtp|src/Hardware/SAME70|src/DuetNG|src/Networking/LwipEthernet/Lwip/src/apps/tftp|src/Networking/W5500Ethernet|src/Networking/LwipEthernet/Lwip/src/netif/ppp|src/Networking/LwipEthernet/Lwip/src/apps/lwiperf|src/Networking/LwipEthernet/Lwip/src/apps/altcp_tls|src/Networking/LwipEthernet/Lwip/src/apps/sntp|src/Networking/LwipEthernet/Lwip/src/apps/http|src/Duet3_V06|src/Hardware/SAM4E|src/Pccb|src/Hardware/SAM4S|src/Networking/LwipEthernet/Lwip/src/apps/mqtt|src/DuetM|src/Networking/LwipEthernet/Lwip/doc" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/> </sourceEntries> </configuration> </storageModule> @@ -1240,7 +1240,7 @@ </toolChain> </folderInfo> <sourceEntries> - <entry excluding="src/Hardware/SAM4E|src/Networking/LwipEthernet/Lwip/src/apps/snmp|src/Networking/LwipEthernet/Lwip/src/apps/smtp|src/Hardware/SAME70|src/DuetNG|src/Networking/LwipEthernet/Lwip/src/apps/tftp|src/Networking/W5500Ethernet|src/Networking/LwipEthernet/Lwip/src/netif/ppp|src/Networking/LwipEthernet/Lwip/src/apps/lwiperf|src/Networking/LwipEthernet/Lwip/src/apps/altcp_tls|src/Networking/LwipEthernet/Lwip/src/apps/sntp|src/Networking/LwipEthernet/Lwip/src/apps/http|src/Duet3_V06|src/Pccb|src/Networking/LwipEthernet/Lwip/src/apps/mqtt|src/DuetM|src/Networking/LwipEthernet/Lwip/doc|src/Hardware/SAM4S" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/> + <entry excluding="src/Networking/LwipEthernet/Lwip/src/apps/snmp|src/Networking/LwipEthernet/Lwip/src/apps/smtp|src/Hardware/SAME70|src/DuetNG|src/Networking/LwipEthernet/Lwip/src/apps/tftp|src/Networking/W5500Ethernet|src/Networking/LwipEthernet/Lwip/src/netif/ppp|src/Networking/LwipEthernet/Lwip/src/apps/lwiperf|src/Networking/LwipEthernet/Lwip/src/apps/altcp_tls|src/Networking/LwipEthernet/Lwip/src/apps/sntp|src/Networking/LwipEthernet/Lwip/src/apps/http|src/Duet3_V06|src/Hardware/SAM4E|src/Pccb|src/Hardware/SAM4S|src/Networking/LwipEthernet/Lwip/src/apps/mqtt|src/DuetM|src/Networking/LwipEthernet/Lwip/doc" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/> </sourceEntries> </configuration> </storageModule> @@ -1397,7 +1397,7 @@ </toolChain> </folderInfo> <sourceEntries> - <entry excluding="src/Hardware/SAM4E|src/Networking/LwipEthernet/Lwip/src/apps/snmp|src/Networking/LwipEthernet/Lwip/src/apps/smtp|src/Hardware/SAME70|src/DuetNG|src/Networking/LwipEthernet/Lwip/src/apps/tftp|src/Networking/W5500Ethernet|src/Networking/LwipEthernet/Lwip/src/netif/ppp|src/Networking/LwipEthernet/Lwip/src/apps/lwiperf|src/Networking/LwipEthernet/Lwip/src/apps/altcp_tls|src/Networking/LwipEthernet/Lwip/src/apps/sntp|src/Networking/LwipEthernet/Lwip/src/apps/http|src/Duet3_V06|src/Pccb|src/Networking/LwipEthernet/Lwip/src/apps/mqtt|src/DuetM|src/Networking/LwipEthernet/Lwip/doc|src/Hardware/SAM4S" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/> + <entry excluding="src/Networking/LwipEthernet/Lwip/src/apps/snmp|src/Networking/LwipEthernet/Lwip/src/apps/smtp|src/Hardware/SAME70|src/DuetNG|src/Networking/LwipEthernet/Lwip/src/apps/tftp|src/Networking/W5500Ethernet|src/Networking/LwipEthernet/Lwip/src/netif/ppp|src/Networking/LwipEthernet/Lwip/src/apps/lwiperf|src/Networking/LwipEthernet/Lwip/src/apps/altcp_tls|src/Networking/LwipEthernet/Lwip/src/apps/sntp|src/Networking/LwipEthernet/Lwip/src/apps/http|src/Duet3_V06|src/Hardware/SAM4E|src/Pccb|src/Hardware/SAM4S|src/Networking/LwipEthernet/Lwip/src/apps/mqtt|src/DuetM|src/Networking/LwipEthernet/Lwip/doc" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/> </sourceEntries> </configuration> </storageModule> @@ -1566,7 +1566,7 @@ </toolChain> </folderInfo> <sourceEntries> - <entry excluding="src/Hardware/SAM4E|src/Duet3Mini|/src/Networking/LwipEthernet/Lwip/test|src/DuetNG|src/Networking/W5500Ethernet|src/Display|src/Pccb|/src/Networking/LwipEthernet/Lwip/src/apps/mqtt|src/Networking/LwipEthernet/Lwip/doc|src/Networking/LwipEthernet/Lwip/src/apps/smtp|src/Networking/LwipEthernet/Lwip/src/apps/snmp|src/Networking/LwipEthernet/Lwip/src/apps/httpd|src/Hardware/SAME5x|src/Networking/LwipEthernet/Lwip/src/apps/tftp|src/Networking/LwipEthernet/Lwip/src/netif/ppp|src/Networking/LwipEthernet/Lwip/src/apps/lwiperf|src/Networking/LwipEthernet/Lwip/src/apps/altcp_tls|src/Networking/LwipEthernet/Lwip/src/apps/sntp|src/Networking/LwipEthernet/Lwip/src/apps/http|src/Networking/ESP8266WiFi|src/DuetM|src/Hardware/SAM4S" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/> + <entry excluding="src/Networking/LwipEthernet/Lwip/src/apps/smtp|src/Networking/LwipEthernet/Lwip/src/apps/snmp|src/Networking/LwipEthernet/Lwip/src/apps/httpd|src/Hardware/SAME5x|/src/Networking/LwipEthernet/Lwip/test|src/DuetNG|src/Networking/LwipEthernet/Lwip/src/apps/tftp|src/Networking/W5500Ethernet|src/Networking/LwipEthernet/Lwip/src/netif/ppp|src/Networking/LwipEthernet/Lwip/src/apps/lwiperf|src/Networking/LwipEthernet/Lwip/src/apps/altcp_tls|src/Networking/LwipEthernet/Lwip/src/apps/sntp|src/Display|src/Networking/LwipEthernet/Lwip/src/apps/http|src/Networking/ESP8266WiFi|src/Duet3Mini|src/Hardware/SAM4E|src/Pccb|/src/Networking/LwipEthernet/Lwip/src/apps/mqtt|src/Hardware/SAM4S|src/DuetM|src/Networking/LwipEthernet/Lwip/doc" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/> </sourceEntries> </configuration> </storageModule> diff --git a/src/CAN/CanInterface.cpp b/src/CAN/CanInterface.cpp index 1a0f51d6..75d7e763 100644 --- a/src/CAN/CanInterface.cpp +++ b/src/CAN/CanInterface.cpp @@ -26,8 +26,8 @@ #include <ClosedLoop/ClosedLoop.h> -#if HAS_LINUX_INTERFACE -# include "Linux/LinuxInterface.h" +#if HAS_SBC_INTERFACE +# include "SBC/SbcInterface.h" #endif #include <memory> diff --git a/src/CAN/CommandProcessor.cpp b/src/CAN/CommandProcessor.cpp index ccaa5771..e1d5ec23 100644 --- a/src/CAN/CommandProcessor.cpp +++ b/src/CAN/CommandProcessor.cpp @@ -37,8 +37,8 @@ # include <Accelerometers/Accelerometers.h> #endif -#if HAS_LINUX_INTERFACE -# include "Linux/LinuxInterface.h" +#if HAS_SBC_INTERFACE +# include "SBC/SbcInterface.h" constexpr size_t MaxFileChunkSize = 448; // Maximum size of file chunks for reading files from the SBC. Should be a multiple of sizeof(CanMessageFirmwareUpdateResponse::data) for best CAN performance char sbcFirmwareChunk[MaxFileChunkSize]; @@ -62,12 +62,12 @@ pre(buf->id.MsgType() == CanMessageType::firmwareBlockRequest) uint32_t fileOffset = msg.fileOffset, fileLength = 0; uint32_t lreq = msg.lengthRequested; -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { // Fetch the firmware file from the SBC uint32_t bytesRead = min<uint32_t>(lreq, MaxFileChunkSize); - if (reprap.GetLinuxInterface().GetFileChunk(fname.c_str(), fileOffset, sbcFirmwareChunk, bytesRead, fileLength)) + if (reprap.GetSbcInterface().GetFileChunk(fname.c_str(), fileOffset, sbcFirmwareChunk, bytesRead, fileLength)) { if (fileOffset >= fileLength) { @@ -114,7 +114,7 @@ pre(buf->id.MsgType() == CanMessageType::firmwareBlockRequest) if (bytesSent == (size_t)bytesRead) { bytesRead = min<uint32_t>(lreq, MaxFileChunkSize); - if (!reprap.GetLinuxInterface().GetFileChunk(fname.c_str(), fileOffset, sbcFirmwareChunk, bytesRead, fileLength)) + if (!reprap.GetSbcInterface().GetFileChunk(fname.c_str(), fileOffset, sbcFirmwareChunk, bytesRead, fileLength)) { msgp = buf->SetupResponseMessage<CanMessageFirmwareUpdateResponse>(0, CanInterface::GetCurrentMasterAddress(), src); msgp->dataLength = 0; diff --git a/src/CAN/ExpansionManager.cpp b/src/CAN/ExpansionManager.cpp index aabcc533..5e4494bd 100644 --- a/src/CAN/ExpansionManager.cpp +++ b/src/CAN/ExpansionManager.cpp @@ -246,16 +246,8 @@ GCodeResult ExpansionManager::UpdateRemoteFirmware(uint32_t boardAddress, GCodeB reply.Clear(); firmwareFilename.cat(".bin"); - // Do not ask Linux for a file here because that would create a deadlock. - // If blocking calls to Linux are supposed to be made from the Spin loop, the Linux interface, - // or at least the code doing SPI data transfers, has to be moved to a separate task first -#if HAS_MASS_STORAGE - // It's fine to check if the file exists on the local SD though - if ( -# if HAS_LINUX_INTERFACE - !reprap.UsingLinuxInterface() && -# endif - !reprap.GetPlatform().FileExists(FIRMWARE_DIRECTORY, firmwareFilename.c_str())) +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE + if (!reprap.GetPlatform().FileExists(FIRMWARE_DIRECTORY, firmwareFilename.c_str())) { reply.printf("Firmware file %s not found", firmwareFilename.c_str()); return GCodeResult::error; diff --git a/src/Display/Menu.cpp b/src/Display/Menu.cpp index 92ff340e..964565a6 100644 --- a/src/Display/Menu.cpp +++ b/src/Display/Menu.cpp @@ -657,8 +657,8 @@ void Menu::EncoderAction(int action) noexcept void Menu::Refresh() noexcept { if ( -#if HAS_LINUX_INTERFACE - !reprap.UsingLinuxInterface() && +#if HAS_SBC_INTERFACE + !reprap.UsingSbcInterface() && #endif #if HAS_MASS_STORAGE !MassStorage::IsDriveMounted(0) diff --git a/src/Duet3Mini/Pins_Duet3Mini.h b/src/Duet3Mini/Pins_Duet3Mini.h index 7517864a..03b26543 100644 --- a/src/Duet3Mini/Pins_Duet3Mini.h +++ b/src/Duet3Mini/Pins_Duet3Mini.h @@ -33,7 +33,7 @@ constexpr uint32_t IAP_IMAGE_START = 0x20038000; #define HAS_LWIP_NETWORKING 1 #define HAS_WIFI_NETWORKING 1 #define HAS_W5500_NETWORKING 0 -#define HAS_LINUX_INTERFACE 1 +#define HAS_SBC_INTERFACE 1 #define HAS_MASS_STORAGE 1 #define HAS_HIGH_SPEED_SD 1 diff --git a/src/Duet3_V06/Pins_Duet3_V06.h b/src/Duet3_V06/Pins_Duet3_V06.h index ffccdec0..f674df88 100644 --- a/src/Duet3_V06/Pins_Duet3_V06.h +++ b/src/Duet3_V06/Pins_Duet3_V06.h @@ -18,7 +18,7 @@ constexpr uint32_t IAP_IMAGE_START = 0x20458000; // last 32kb of RAM // Features definition #define HAS_LWIP_NETWORKING 1 #define HAS_WIFI_NETWORKING 0 -#define HAS_LINUX_INTERFACE 1 +#define HAS_SBC_INTERFACE 1 #define HAS_MASS_STORAGE 1 #define HAS_HIGH_SPEED_SD 1 diff --git a/src/DuetNG/Pins_DuetNG.h b/src/DuetNG/Pins_DuetNG.h index 579def4a..62b5e25f 100644 --- a/src/DuetNG/Pins_DuetNG.h +++ b/src/DuetNG/Pins_DuetNG.h @@ -42,12 +42,12 @@ constexpr uint32_t IAP_IMAGE_START = 0x20018000; // IAP is loaded into the last #if defined(USE_SBC) # define HAS_WIFI_NETWORKING 0 # define HAS_W5500_NETWORKING 0 -# define HAS_LINUX_INTERFACE 1 +# define HAS_SBC_INTERFACE 1 # define HAS_MASS_STORAGE 0 #else # define HAS_WIFI_NETWORKING 1 # define HAS_W5500_NETWORKING 1 -# define HAS_LINUX_INTERFACE 0 +# define HAS_SBC_INTERFACE 0 #endif #define HAS_CPU_TEMP_SENSOR 1 @@ -561,7 +561,7 @@ constexpr Pin SbcTfrReadyPin = PortDPin(31); #define STEP_TC_ID ID_TC2 // DMA channel allocation -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE constexpr DmaChannel DmacChanSbcTx = 1; constexpr DmaChannel DmacChanSbcRx = 2; #endif diff --git a/src/Endstops/EndstopsManager.cpp b/src/Endstops/EndstopsManager.cpp index 30000887..467a9fc2 100644 --- a/src/Endstops/EndstopsManager.cpp +++ b/src/Endstops/EndstopsManager.cpp @@ -565,7 +565,7 @@ GCodeResult EndstopsManager::ProgramZProbe(GCodeBuffer& gb, const StringRef& rep return GCodeResult::error; } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool EndstopsManager::WriteZProbeParameters(FileStore *f, bool includingG31) const noexcept { diff --git a/src/Endstops/EndstopsManager.h b/src/Endstops/EndstopsManager.h index 398c93ee..7221b014 100644 --- a/src/Endstops/EndstopsManager.h +++ b/src/Endstops/EndstopsManager.h @@ -68,7 +68,7 @@ public: void OnEndstopOrZProbeStatesChanged() noexcept; #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool WriteZProbeParameters(FileStore *f, bool includingG31) const noexcept; #endif diff --git a/src/Endstops/ZProbe.cpp b/src/Endstops/ZProbe.cpp index 921d8fc6..4429b2d5 100644 --- a/src/Endstops/ZProbe.cpp +++ b/src/Endstops/ZProbe.cpp @@ -134,7 +134,7 @@ float ZProbe::GetActualTriggerHeight() const noexcept return -offsets[Z_AXIS]; } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool ZProbe::WriteParameters(FileStore *f, unsigned int probeNumber) const noexcept { diff --git a/src/Endstops/ZProbe.h b/src/Endstops/ZProbe.h index 8be3b351..f43ea340 100644 --- a/src/Endstops/ZProbe.h +++ b/src/Endstops/ZProbe.h @@ -60,7 +60,7 @@ public: void SetDeployedByUser(bool b) noexcept { isDeployedByUser = b; } void SetLastStoppedHeight(float h) noexcept; -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool WriteParameters(FileStore *f, unsigned int probeNumber) const noexcept; #endif diff --git a/src/Fans/Fan.cpp b/src/Fans/Fan.cpp index 3b3dccbe..17d53cef 100644 --- a/src/Fans/Fan.cpp +++ b/src/Fans/Fan.cpp @@ -215,7 +215,7 @@ GCodeResult Fan::Configure(const CanMessageFanParameters& msg, const StringRef& #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE // Save the settings of this fan if it isn't thermostatic bool Fan::WriteSettings(FileStore *f, size_t fanNum) const noexcept diff --git a/src/Fans/Fan.h b/src/Fans/Fan.h index d0acc23b..b1af0d11 100644 --- a/src/Fans/Fan.h +++ b/src/Fans/Fan.h @@ -58,7 +58,7 @@ public: unsigned int GetNumber() const { return fanNumber; } const char *GetName() const noexcept { return name.c_str(); } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool WriteSettings(FileStore *f, size_t fanNum) const noexcept; // save the settings of this fan if it isn't thermostatic #endif diff --git a/src/Fans/FansManager.cpp b/src/Fans/FansManager.cpp index d463c867..4efd7345 100644 --- a/src/Fans/FansManager.cpp +++ b/src/Fans/FansManager.cpp @@ -80,7 +80,7 @@ size_t FansManager::GetNumFansToReport() const noexcept return numFans; } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool FansManager::WriteFanSettings(FileStore *f) const noexcept { diff --git a/src/Fans/FansManager.h b/src/Fans/FansManager.h index fad7bc88..382b722c 100644 --- a/src/Fans/FansManager.h +++ b/src/Fans/FansManager.h @@ -47,7 +47,7 @@ public: GCodeResult SetFanSpeed(const CanMessageSetFanSpeed& msg, const StringRef& reply) noexcept; unsigned int PopulateFansReport(CanMessageFansReport& msg) noexcept; #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool WriteFanSettings(FileStore *f) const noexcept; #endif diff --git a/src/GCodes/GCodeBuffer/BinaryParser.cpp b/src/GCodes/GCodeBuffer/BinaryParser.cpp index 8d98102d..954c4e29 100644 --- a/src/GCodes/GCodeBuffer/BinaryParser.cpp +++ b/src/GCodes/GCodeBuffer/BinaryParser.cpp @@ -7,7 +7,7 @@ #include "BinaryParser.h" -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE #include "GCodeBuffer.h" #include "ExpressionParser.h" diff --git a/src/GCodes/GCodeBuffer/BinaryParser.h b/src/GCodes/GCodeBuffer/BinaryParser.h index adb2286b..3c1dcbda 100644 --- a/src/GCodes/GCodeBuffer/BinaryParser.h +++ b/src/GCodes/GCodeBuffer/BinaryParser.h @@ -10,9 +10,9 @@ #include <RepRapFirmware.h> -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE -#include <Linux/LinuxMessageFormats.h> +#include <SBC/SbcMessageFormats.h> #include <GCodes/GCodeException.h> #include <GCodes/GCodeMachineState.h> diff --git a/src/GCodes/GCodeBuffer/GCodeBuffer.cpp b/src/GCodes/GCodeBuffer/GCodeBuffer.cpp index 404dc653..5f212eac 100644 --- a/src/GCodes/GCodeBuffer/GCodeBuffer.cpp +++ b/src/GCodes/GCodeBuffer/GCodeBuffer.cpp @@ -11,8 +11,8 @@ #if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES # include <GCodes/GCodeInput.h> #endif -#if HAS_LINUX_INTERFACE -# include <Linux/LinuxInterface.h> +#if HAS_SBC_INTERFACE +# include <SBC/SbcInterface.h> #endif #include "BinaryParser.h" #include "StringParser.h" @@ -22,7 +22,7 @@ #include <Movement/StepTimer.h> // Macros to reduce the amount of explicit conditional compilation in this file -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE # define PARSER_OPERATION(_x) ((isBinaryBuffer) ? (binaryParser._x) : (stringParser._x)) # define IS_BINARY_OR(_x) ((isBinaryBuffer) || (_x)) @@ -93,16 +93,16 @@ GCodeBuffer::GCodeBuffer(GCodeChannel::RawType channel, GCodeInput *normalIn, Fi fileInput(fileIn), #endif responseMessageType(mt), lastResult(GCodeResult::ok), -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE binaryParser(*this), #endif stringParser(*this), machineState(new GCodeMachineState()), whenReportDueTimerStarted(millis()), -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE isBinaryBuffer(false), #endif timerRunning(false), motionCommanded(false) -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE , isWaitingForMacro(false), invalidated(false) #endif { @@ -114,7 +114,7 @@ GCodeBuffer::GCodeBuffer(GCodeChannel::RawType channel, GCodeInput *normalIn, Fi // Reset it to its state after start-up void GCodeBuffer::Reset() noexcept { -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE if (isWaitingForMacro) { ResolveMacroRequest(true, false); @@ -123,7 +123,7 @@ void GCodeBuffer::Reset() noexcept while (PopState()) { } -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE isBinaryBuffer = false; requestedMacroFile.Clear(); isWaitingForMacro = macroFileClosed = false; @@ -136,7 +136,7 @@ void GCodeBuffer::Reset() noexcept // Set it up to parse another G-code void GCodeBuffer::Init() noexcept { -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE sendToSbc = false; binaryParser.Init(); #endif @@ -190,7 +190,7 @@ void GCodeBuffer::Diagnostics(MessageType mtype) noexcept { String<StringLength256> scratchString; scratchString.copy(codeChannel.ToString()); -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE scratchString.cat(IsBinary() ? "* " : " "); #else scratchString.cat(" "); @@ -235,7 +235,7 @@ void GCodeBuffer::Diagnostics(MessageType mtype) noexcept // Add a character to the end bool GCodeBuffer::Put(char c) noexcept { -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE machineState->lastCodeFromSbc = false; isBinaryBuffer = false; #endif @@ -254,7 +254,7 @@ bool GCodeBuffer::CheckMetaCommand(const StringRef& reply) return NOT_BINARY_AND(stringParser.CheckMetaCommand(reply)); } -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE // Add an entire binary G-Code, overwriting any existing content // CAUTION! This may be called with the task scheduler suspended, so don't do anything that might block or take more than a few microseconds to execute @@ -271,7 +271,7 @@ void GCodeBuffer::PutBinary(const uint32_t *data, size_t len) noexcept // Add an entire G-Code, overwriting any existing content void GCodeBuffer::PutAndDecode(const char *str, size_t len) noexcept { -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE machineState->lastCodeFromSbc = false; isBinaryBuffer = false; #endif @@ -281,7 +281,7 @@ void GCodeBuffer::PutAndDecode(const char *str, size_t len) noexcept // Add a null-terminated string, overwriting any existing content void GCodeBuffer::PutAndDecode(const char *str) noexcept { -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE machineState->lastCodeFromSbc = false; isBinaryBuffer = false; #endif @@ -290,7 +290,7 @@ void GCodeBuffer::PutAndDecode(const char *str) noexcept void GCodeBuffer::StartNewFile() noexcept { -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE machineState->SetFileExecuting(); #endif machineState->lineNumber = 0; // reset line numbering when M32 is run @@ -740,7 +740,7 @@ void GCodeBuffer::SetFinished(bool f) noexcept { if (f) { -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE sendToSbc = false; #endif LatestMachineState().firstCommandAfterRestart = false; @@ -861,8 +861,8 @@ void GCodeBuffer::AbortFile(bool abortAll, bool requestAbort) noexcept if (machineState->DoingFile()) { #if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES -# if HAS_LINUX_INTERFACE - if (!reprap.UsingLinuxInterface()) +# if HAS_SBC_INTERFACE + if (!reprap.UsingSbcInterface()) # endif { fileInput->Reset(machineState->fileState); @@ -872,7 +872,7 @@ void GCodeBuffer::AbortFile(bool abortAll, bool requestAbort) noexcept } } while (PopState() && (abortAll || !machineState->DoingFile())); -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE abortFile = requestAbort; abortAllFiles = requestAbort && abortAll; } @@ -883,7 +883,7 @@ void GCodeBuffer::AbortFile(bool abortAll, bool requestAbort) noexcept } } -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE void GCodeBuffer::SetFileFinished() noexcept { @@ -912,7 +912,7 @@ void GCodeBuffer::SetFileFinished() noexcept if (macroFileId != NoFileId) { - reprap.GetLinuxInterface().EventOccurred(); + reprap.GetSbcInterface().EventOccurred(); } } @@ -929,14 +929,14 @@ void GCodeBuffer::SetPrintFinished() noexcept ms->fileFinished = true; } } - reprap.GetLinuxInterface().EventOccurred(); + reprap.GetSbcInterface().EventOccurred(); } } -// This is only called when using the Linux interface and returns if the macro file could be opened +// This is only called when using the SBC interface and returns if the macro file could be opened bool GCodeBuffer::RequestMacroFile(const char *filename, bool fromCode) noexcept { - if (!reprap.GetLinuxInterface().IsConnected()) + if (!reprap.GetSbcInterface().IsConnected()) { // Don't wait for a macro file if no SBC is connected return false; @@ -953,7 +953,7 @@ bool GCodeBuffer::RequestMacroFile(const char *filename, bool fromCode) noexcept { // Wait for a response (but not forever) isWaitingForMacro = true; - reprap.GetLinuxInterface().EventOccurred(true); + reprap.GetSbcInterface().EventOccurred(true); if (!macroSemaphore.Take(SpiMacroRequestTimeout)) { isWaitingForMacro = false; @@ -962,7 +962,7 @@ bool GCodeBuffer::RequestMacroFile(const char *filename, bool fromCode) noexcept } } - // When we get here we expect the Linux interface to have set the variables above for us + // When we get here we expect the SBC interface to have set the variables above for us if (!macroFileError) { macroJustStarted = true; @@ -984,7 +984,7 @@ void GCodeBuffer::MacroFileClosed() noexcept machineState->CloseFile(); macroJustStarted = false; macroFileClosed = true; - reprap.GetLinuxInterface().EventOccurred(); + reprap.GetSbcInterface().EventOccurred(); } #endif @@ -1000,9 +1000,9 @@ void GCodeBuffer::MessageAcknowledged(bool cancelled) noexcept ms->waitingForAcknowledgement = false; ms->messageAcknowledged = true; ms->messageCancelled = cancelled; -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE messageAcknowledged = !cancelled; - reprap.GetLinuxInterface().EventOccurred(); + reprap.GetSbcInterface().EventOccurred(); #endif } } @@ -1010,7 +1010,7 @@ void GCodeBuffer::MessageAcknowledged(bool cancelled) noexcept MessageType GCodeBuffer::GetResponseMessageType() const noexcept { -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE if (machineState->lastCodeFromSbc) { return (MessageType)((1u << codeChannel.ToBaseType()) | BinaryCodeReplyFlag); @@ -1027,8 +1027,8 @@ FilePosition GCodeBuffer::GetFilePosition() const noexcept void GCodeBuffer::WaitForAcknowledgement() noexcept { machineState->WaitForAcknowledgement(); -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { messagePromptPending = true; } diff --git a/src/GCodes/GCodeBuffer/GCodeBuffer.h b/src/GCodes/GCodeBuffer/GCodeBuffer.h index 878bd2e6..98a5d47e 100644 --- a/src/GCodes/GCodeBuffer/GCodeBuffer.h +++ b/src/GCodes/GCodeBuffer/GCodeBuffer.h @@ -14,7 +14,9 @@ #include <RepRapFirmware.h> #include <GCodes/GCodeChannel.h> #include <GCodes/GCodeMachineState.h> -#include <Linux/LinuxMessageFormats.h> +#if HAS_SBC_INTERFACE +# include <SBC/SbcMessageFormats.h> +#endif #include <ObjectModel/ObjectModel.h> class FileGCodeInput; @@ -48,7 +50,7 @@ public: void Diagnostics(MessageType mtype) noexcept; // Write some debug info bool Put(char c) noexcept SPEED_CRITICAL; // Add a character to the end -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE void PutBinary(const uint32_t *data, size_t len) noexcept; // Add an entire binary G-Code, overwriting any existing content #endif void PutAndDecode(const char *data, size_t len) noexcept; // Add an entire G-Code, overwriting any existing content @@ -150,7 +152,7 @@ public: void WaitForAcknowledgement() noexcept; // Flag that we are waiting for acknowledgement -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE bool IsBinary() const noexcept { return isBinaryBuffer; } // Return true if the code is in binary format bool IsFileFinished() const noexcept; // Return true if this source has finished execution of a file @@ -269,7 +271,7 @@ private: GCodeResult lastResult; -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE BinaryParser binaryParser; #endif @@ -282,20 +284,20 @@ private: uint32_t whenReportDueTimerStarted; // When the report-due-timer has been started static constexpr uint32_t reportDueInterval = 1000; // Interval in which we send in ms -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE bool isBinaryBuffer; #endif bool timerRunning; // True if we are waiting bool motionCommanded; // true if this GCode stream has commanded motion since it last waited for motion to stop -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE alignas(4) char buffer[MaxCodeBufferSize]; // must be aligned because we do dword fetches from it #else char buffer[GCODE_LENGTH]; #endif -#if HAS_LINUX_INTERFACE - // Accessed by both the Main and Linux tasks +#if HAS_SBC_INTERFACE + // Accessed by both the Main and SBC tasks BinarySemaphore macroSemaphore; volatile bool isWaitingForMacro; // Is this GB waiting in DoFileMacro? volatile bool macroFileClosed; // Last macro file has been closed in RRF, tell the SBC @@ -312,21 +314,21 @@ private: messagePromptPending : 1, // Has the SBC been notified about a message waiting for acknowledgement? messageAcknowledged : 1; // Last message has been acknowledged - // Accessed only by the Linux task + // Accessed only by the SBC task bool invalidated; // Set to true if the GB content is not valid and about to be cleared #endif }; inline bool GCodeBuffer::IsDoingFileMacro() const noexcept { -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE return machineState->doingFileMacro || IsMacroRequestPending(); #else return machineState->doingFileMacro; #endif } -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE inline bool GCodeBuffer::IsFileFinished() const noexcept { @@ -369,7 +371,7 @@ inline bool GCodeBuffer::CanQueueCodes() const noexcept inline bool GCodeBuffer::IsDoingFile() const noexcept { -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE return machineState->DoingFile() || IsMacroRequestPending(); #else return machineState->DoingFile(); @@ -389,7 +391,7 @@ inline bool GCodeBuffer::IsExecuting() const noexcept // Return true if this source is executing a file from the local SD card inline bool GCodeBuffer::IsDoingLocalFile() const noexcept { -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE return !IsBinary() && IsDoingFile(); #else return IsDoingFile(); diff --git a/src/GCodes/GCodeBuffer/StringParser.cpp b/src/GCodes/GCodeBuffer/StringParser.cpp index 9205e453..24a6aaa3 100644 --- a/src/GCodes/GCodeBuffer/StringParser.cpp +++ b/src/GCodes/GCodeBuffer/StringParser.cpp @@ -785,13 +785,13 @@ void StringParser::ProcessEchoCommand(const StringRef& reply) THROWS(GCodeExcept { SkipWhiteSpace(); -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE FileData outputFile; #endif if (gb.buffer[readPointer] == '>') { -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE // Redirect the line to file ++readPointer; OpenMode openMode; @@ -843,7 +843,7 @@ void StringParser::ProcessEchoCommand(const StringRef& reply) THROWS(GCodeExcept } } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE if (outputFile.IsLive()) { reply.cat('\n'); @@ -1062,8 +1062,8 @@ FilePosition StringParser::GetFilePosition() const noexcept { #if HAS_MASS_STORAGE if (gb.LatestMachineState().DoingFile() -# if HAS_LINUX_INTERFACE - && !reprap.UsingLinuxInterface() +# if HAS_SBC_INTERFACE + && !reprap.UsingSbcInterface() # endif ) { diff --git a/src/GCodes/GCodeMachineState.cpp b/src/GCodes/GCodeMachineState.cpp index 01d35c88..ad02bdd8 100644 --- a/src/GCodes/GCodeMachineState.cpp +++ b/src/GCodes/GCodeMachineState.cpp @@ -13,7 +13,7 @@ // Create a default initialised GCodeMachineState GCodeMachineState::GCodeMachineState() noexcept : feedRate(ConvertSpeedFromMmPerMin(DefaultFeedRate)), -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE fileId(NoFileId), #endif lineNumber(0), @@ -21,7 +21,7 @@ GCodeMachineState::GCodeMachineState() noexcept doingFileMacro(false), waitWhileCooling(false), runningM501(false), runningM502(false), volumetricExtrusion(false), g53Active(false), runningSystemMacro(false), usingInches(false), waitingForAcknowledgement(false), messageAcknowledged(false), localPush(false), macroRestartable(false), firstCommandAfterRestart(false), commandRepeated(false), -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE lastCodeFromSbc(false), macroStartedByCode(false), fileFinished(false), #endif compatibility(Compatibility::RepRapFirmware), @@ -37,7 +37,7 @@ GCodeMachineState::GCodeMachineState(GCodeMachineState& prev, bool withinSameFil #if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES fileState(prev.fileState), #endif -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE fileId(prev.fileId), #endif lockedResources(prev.lockedResources), @@ -46,7 +46,7 @@ GCodeMachineState::GCodeMachineState(GCodeMachineState& prev, bool withinSameFil doingFileMacro(prev.doingFileMacro), waitWhileCooling(prev.waitWhileCooling), runningM501(prev.runningM501), runningM502(prev.runningM502), volumetricExtrusion(false), g53Active(false), runningSystemMacro(prev.runningSystemMacro), usingInches(prev.usingInches), waitingForAcknowledgement(false), messageAcknowledged(false), localPush(withinSameFile), firstCommandAfterRestart(prev.firstCommandAfterRestart), commandRepeated(false), -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE lastCodeFromSbc(prev.lastCodeFromSbc), macroStartedByCode(prev.macroStartedByCode), fileFinished(prev.fileFinished), #endif compatibility(prev.compatibility), @@ -90,7 +90,7 @@ bool GCodeMachineState::CanRestartMacro() const noexcept return true; } -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE // Set the state to indicate a file is being processed void GCodeMachineState::SetFileExecuting() noexcept @@ -114,8 +114,8 @@ void GCodeMachineState::SetFileExecuting() noexcept // Return true if we are reading GCode commands from a file or macro bool GCodeMachineState::DoingFile() const noexcept { -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface() && fileId != NoFileId) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface() && fileId != NoFileId) { return true; } @@ -130,8 +130,8 @@ bool GCodeMachineState::DoingFile() const noexcept // Close the currently executing file void GCodeMachineState::CloseFile() noexcept { -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { if (fileId != NoFileId) { diff --git a/src/GCodes/GCodeMachineState.h b/src/GCodes/GCodeMachineState.h index f45e77f3..a6bb3e2a 100644 --- a/src/GCodes/GCodeMachineState.h +++ b/src/GCodes/GCodeMachineState.h @@ -117,7 +117,7 @@ enum class GCodeState : uint8_t timingSDread, #endif -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE waitingForAcknowledgement, #endif @@ -139,7 +139,7 @@ enum class BlockType : uint8_t loop // block inside a 'while' command }; -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE typedef uint8_t FileId; constexpr FileId NoFileId = 0; @@ -203,7 +203,7 @@ public: #if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES FileData fileState; #endif -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE FileId fileId; // virtual ID to distinguish files in different stack levels (only unique per GB) #endif ResourceBitmap lockedResources; @@ -229,7 +229,7 @@ public: macroRestartable : 1, // true if the current macro has used M98 R1 to say that it can be interrupted and restarted firstCommandAfterRestart : 1, // true if this is the first command after restarting a macro that was interrupted commandRepeated : 1 // true if the current command is being repeated because it returned GCodeResult::notFinished the first time -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE , lastCodeFromSbc : 1, macroStartedByCode : 1, fileFinished : 1 @@ -244,7 +244,7 @@ public: void WaitForAcknowledgement() noexcept; -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE void SetFileExecuting() noexcept; #endif diff --git a/src/GCodes/GCodeQueue.cpp b/src/GCodes/GCodeQueue.cpp index 4fc4cb02..cf11c03b 100644 --- a/src/GCodes/GCodeQueue.cpp +++ b/src/GCodes/GCodeQueue.cpp @@ -234,10 +234,10 @@ void GCodeQueue::Diagnostics(MessageType mtype) noexcept const QueuedCode *item = queuedItems; do { -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE // The following may output binary gibberish if this code is stored in binary. // We could restore this message by using GCodeBuffer::AppendFullCommand but there is probably no need to - if (!reprap.UsingLinuxInterface()) + if (!reprap.UsingSbcInterface()) #endif { reprap.GetPlatform().MessageF(mtype, "Queued '%.*s' for move %" PRIu32 "\n", item->dataLength, item->data, item->executeAtMove); @@ -250,7 +250,7 @@ void GCodeQueue::Diagnostics(MessageType mtype) noexcept void QueuedCode::AssignFrom(GCodeBuffer &gb) noexcept { -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE isBinary = gb.IsBinary(); #endif memcpy(data, gb.DataStart(), gb.DataLength()); @@ -259,7 +259,7 @@ void QueuedCode::AssignFrom(GCodeBuffer &gb) noexcept void QueuedCode::AssignTo(GCodeBuffer *gb) noexcept { -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE if (isBinary) { // Note that the data has to remain on a 4-byte boundary for this to work diff --git a/src/GCodes/GCodeQueue.h b/src/GCodes/GCodeQueue.h index f29090e0..16a7fda9 100644 --- a/src/GCodes/GCodeQueue.h +++ b/src/GCodes/GCodeQueue.h @@ -48,7 +48,7 @@ public: private: QueuedCode *next; -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE bool isBinary; alignas(4) char data[BufferSizePerQueueItem]; #else diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp index b148f5f6..440e981f 100644 --- a/src/GCodes/GCodes.cpp +++ b/src/GCodes/GCodes.cpp @@ -42,8 +42,8 @@ # include <Fans/LedStripDriver.h> #endif -#if HAS_LINUX_INTERFACE -# include <Linux/LinuxInterface.h> +#if HAS_SBC_INTERFACE +# include <SBC/SbcInterface.h> #endif #if SUPPORT_REMOTE_COMMANDS @@ -81,19 +81,18 @@ GCodes::GCodes(Platform& p) noexcept : #endif fileGCode = new GCodeBuffer(GCodeChannel::File, nullptr, fileInput, GenericMessage); -# if SUPPORT_HTTP || HAS_LINUX_INTERFACE +# if SUPPORT_HTTP || HAS_SBC_INTERFACE httpInput = new NetworkGCodeInput(); httpGCode = new GCodeBuffer(GCodeChannel::HTTP, httpInput, fileInput, HttpMessage); # else httpGCode = nullptr; -# endif // SUPPORT_HTTP || HAS_LINUX_INTERFACE -# if SUPPORT_TELNET || HAS_LINUX_INTERFACE +# endif // SUPPORT_HTTP || HAS_SBC_INTERFACE +# if SUPPORT_TELNET || HAS_SBC_INTERFACE telnetInput = new NetworkGCodeInput(); telnetGCode = new GCodeBuffer(GCodeChannel::Telnet, telnetInput, fileInput, TelnetMessage, Compatibility::Marlin); # else telnetGCode = nullptr; -# endif // SUPPORT_TELNET || HAS_LINUX_INTERFACE - +# endif // SUPPORT_TELNET || HAS_SBC_INTERFACE #if defined(SERIAL_MAIN_DEVICE) # if SAME5x // SAME5x USB driver already uses an efficient buffer for receiving data from USB @@ -103,7 +102,7 @@ GCodes::GCodes(Platform& p) noexcept : BufferedStreamGCodeInput * const usbInput = new BufferedStreamGCodeInput(SERIAL_MAIN_DEVICE); # endif usbGCode = new GCodeBuffer(GCodeChannel::USB, usbInput, fileInput, UsbMessage, Compatibility::Marlin); -#elif HAS_LINUX_INTERFACE +#elif HAS_SBC_INTERFACE usbGCode = new GCodeBuffer(GCodeChannel::USB, nullptr, fileInput, UsbMessage, Compatbility::marlin); #else usbGCode = nullptr; @@ -112,7 +111,7 @@ GCodes::GCodes(Platform& p) noexcept : #if HAS_AUX_DEVICES StreamGCodeInput * const auxInput = new StreamGCodeInput(SERIAL_AUX_DEVICE); auxGCode = new GCodeBuffer(GCodeChannel::Aux, auxInput, fileInput, AuxMessage); -#elif HAS_LINUX_INTERFACE +#elif HAS_SBC_INTERFACE auxGCode = new GCodeBuffer(GCodeChannel::Aux, nullptr, fileInput, AuxMessage); #else auxGCode = nullptr; @@ -123,13 +122,13 @@ GCodes::GCodes(Platform& p) noexcept : codeQueue = new GCodeQueue(); queuedGCode = new GCodeBuffer(GCodeChannel::Queue, codeQueue, fileInput, GenericMessage); -#if SUPPORT_12864_LCD || HAS_LINUX_INTERFACE +#if SUPPORT_12864_LCD || HAS_SBC_INTERFACE lcdGCode = new GCodeBuffer(GCodeChannel::LCD, nullptr, fileInput, LcdMessage); #else lcdGCode = nullptr; #endif -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE spiGCode = new GCodeBuffer(GCodeChannel::SBC, nullptr, fileInput, GenericMessage); #else spiGCode = nullptr; @@ -138,7 +137,7 @@ GCodes::GCodes(Platform& p) noexcept : #if defined(SERIAL_AUX2_DEVICE) StreamGCodeInput * const aux2Input = new StreamGCodeInput(SERIAL_AUX2_DEVICE); aux2GCode = new GCodeBuffer(GCodeChannel::Aux2, aux2Input, fileInput, Aux2Message); -#elif HAS_LINUX_INTERFACE +#elif HAS_SBC_INTERFACE aux2GCode = new GCodeBuffer(GCodeChannel::Aux2, nullptr, fileInput, Aux2Message); #else aux2GCode = nullptr; @@ -292,7 +291,7 @@ void GCodes::Reset() noexcept #endif doingToolChange = false; doingManualBedProbe = false; -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES fileOffsetToPrint = 0; restartMoveFractionDone = 0.0; #endif @@ -346,8 +345,8 @@ bool GCodes::WaitingForAcknowledgement() const noexcept // May return noFilePosition if allowNoFilePos is true FilePosition GCodes::GetFilePosition(bool allowNoFilePos) const noexcept { -#if HAS_LINUX_INTERFACE - if (!reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (!reprap.UsingSbcInterface()) #endif { #if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES @@ -359,7 +358,7 @@ FilePosition GCodes::GetFilePosition(bool allowNoFilePos) const noexcept #endif } -#if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES || HAS_SBC_INTERFACE const FilePosition pos = (fileGCode->IsDoingFileMacro()) ? printFilePositionAtMacroStart // the position before we started executing the macro : fileGCode->GetFilePosition(); // the actual position, allowing for bytes cached but not yet processed @@ -441,7 +440,7 @@ void GCodes::Spin() noexcept // Get the GCodeBuffer that we want to process a command from. Use round-robin scheduling but give priority to auto-pause. GCodeBuffer *gbp = autoPauseGCode; if (!autoPauseGCode->IsCompletelyIdle() -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES || autoPauseGCode->LatestMachineState().DoingFile() #endif ) // if autoPause is active @@ -474,9 +473,9 @@ void GCodes::Spin() noexcept } -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE // Need to check if the print has been stopped by the SBC - if (reprap.UsingLinuxInterface() && reprap.GetLinuxInterface().IsPrintAborted()) + if (reprap.UsingSbcInterface() && reprap.GetSbcInterface().IsPrintAborted()) { StopPrint(StopPrintReason::abort); } @@ -535,8 +534,11 @@ bool GCodes::SpinGCodeBuffer(GCodeBuffer& gb) noexcept result = true; // assume we did something useful (not necessarily true, e.g. could be waiting for movement to stop) } - if ( gb.IsExecuting() - || (isWaiting && !cancelWait) // this is needed to get reports sent during M109 commands + if ((gb.IsExecuting() +#if HAS_SBC_INTERFACE + && !gb.IsSendRequested() +#endif + ) || (isWaiting && !cancelWait) // this is needed to get reports sent during M109 commands ) { CheckReportDue(gb, reply.GetRef()); @@ -614,10 +616,10 @@ bool GCodes::StartNextGCode(GCodeBuffer& gb, const StringRef& reply) noexcept return true; } } -#if HAS_LINUX_INTERFACE - else if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + else if (reprap.UsingSbcInterface()) { - return reprap.GetLinuxInterface().FillBuffer(gb); + return reprap.GetSbcInterface().FillBuffer(gb); } #endif } @@ -627,8 +629,8 @@ bool GCodes::StartNextGCode(GCodeBuffer& gb, const StringRef& reply) noexcept // Try to continue with a print from file, returning true if we did anything significant bool GCodes::DoFilePrint(GCodeBuffer& gb, const StringRef& reply) noexcept { -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { if (gb.IsFileFinished()) { @@ -680,7 +682,7 @@ bool GCodes::DoFilePrint(GCodeBuffer& gb, const StringRef& reply) noexcept return true; } } - return reprap.GetLinuxInterface().FillBuffer(gb); + return reprap.GetSbcInterface().FillBuffer(gb); } } else @@ -948,15 +950,15 @@ void GCodes::DoPause(GCodeBuffer& gb, PauseReason reason, const char *msg, uint1 pauseRestorePoint.moveCoords[axis] = moveState.currentUserPosition[axis]; } -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { fileGCode->Init(); // clear the next move UnlockAll(*fileGCode); // release any locks it had } else - { #endif + { #if HAS_MASS_STORAGE // If we skipped any moves, reset the file pointer to the start of the first move we need to replay // The following could be delayed until we resume the print @@ -970,9 +972,7 @@ void GCodes::DoPause(GCodeBuffer& gb, PauseReason reason, const char *msg, uint1 } } #endif -#if HAS_LINUX_INTERFACE } -#endif codeQueue->PurgeEntries(); @@ -992,7 +992,7 @@ void GCodes::DoPause(GCodeBuffer& gb, PauseReason reason, const char *msg, uint1 pauseRestorePoint.toolNumber = reprap.GetCurrentToolNumber(); pauseRestorePoint.fanSpeed = lastDefaultFanSpeed; -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE if (!IsSimulating()) { SaveResumeInfo(false); // create the resume file so that we can resume after power down @@ -1027,8 +1027,8 @@ void GCodes::DoPause(GCodeBuffer& gb, PauseReason reason, const char *msg, uint1 gb.SetState(newState, param); pauseState = PauseState::pausing; -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { // Get the print pause reason that is compatible with the API PrintPausedReason pauseReason = PrintPausedReason::user; @@ -1059,8 +1059,8 @@ void GCodes::DoPause(GCodeBuffer& gb, PauseReason reason, const char *msg, uint1 break; } - // Prepare notification for the Linux side - reprap.GetLinuxInterface().SetPauseReason(pauseRestorePoint.filePos, pauseReason); + // Prepare notification for the SBC + reprap.GetSbcInterface().SetPauseReason(pauseRestorePoint.filePos, pauseReason); } #endif @@ -1168,11 +1168,11 @@ bool GCodes::DoEmergencyPause() noexcept #endif } -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { PrintPausedReason reason = platform.IsPowerOk() ? PrintPausedReason::stall : PrintPausedReason::lowVoltage; - reprap.GetLinuxInterface().SetEmergencyPauseReason(pauseRestorePoint.filePos, reason); + reprap.GetSbcInterface().SetEmergencyPauseReason(pauseRestorePoint.filePos, reason); } #endif @@ -1331,7 +1331,7 @@ bool GCodes::ReHomeOnStall(DriversBitmap stalledDrivers) noexcept #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE void GCodes::SaveResumeInfo(bool wasPowerFailure) noexcept { @@ -2780,8 +2780,8 @@ bool GCodes::DoFileMacro(GCodeBuffer& gb, const char* fileName, bool reportMissi printFilePositionAtMacroStart = gb.GetFilePosition(); } -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { if (!gb.RequestMacroFile(fileName, gb.IsBinary() && codeRunning != AsyncSystemMacroCode)) { @@ -2842,7 +2842,7 @@ bool GCodes::DoFileMacro(GCodeBuffer& gb, const char* fileName, bool reportMissi #endif } -#if HAS_LINUX_INTERFACE || HAS_MASS_STORAGE || HAS_EMBEDDED_FILES +#if HAS_SBC_INTERFACE || HAS_MASS_STORAGE || HAS_EMBEDDED_FILES gb.LatestMachineState().doingFileMacro = true; // The following three flags need to be inherited in the case that a system macro calls another macro, e.g.homeall.g calls homez.g. The Push call copied them over already. @@ -2873,8 +2873,8 @@ bool GCodes::DoFileMacro(GCodeBuffer& gb, const char* fileName, bool reportMissi gb.SetState(GCodeState::normal); gb.Init(); -# if HAS_LINUX_INTERFACE - if (!reprap.UsingLinuxInterface() && codeRunning != AsyncSystemMacroCode) +# if HAS_SBC_INTERFACE + if (!reprap.UsingSbcInterface() && codeRunning != AsyncSystemMacroCode) # endif { // Don't notify DSF when files are requested asynchronously, it creates excessive traffic @@ -2895,8 +2895,8 @@ void GCodes::FileMacroCyclesReturn(GCodeBuffer& gb) noexcept { if (gb.IsDoingFileMacro()) { -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { gb.AbortFile(false); } @@ -3117,9 +3117,9 @@ GCodeResult GCodes::ProbeGrid(GCodeBuffer& gb, const StringRef& reply) GCodeResult GCodes::LoadHeightMap(GCodeBuffer& gb, const StringRef& reply) { -#if HAS_LINUX_INTERFACE - // If we have a Linux interface and we're using it, the Linux components will take care of file I/O and this should not be called. - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + // If we have an SBC interface and we're using it, the SBC service will take care of file I/O and this should not be called + if (reprap.UsingSbcInterface()) { reply.copy("Cannot use height map on local SD card when SBC interface is used"); return GCodeResult::error; @@ -3169,9 +3169,9 @@ GCodeResult GCodes::LoadHeightMap(GCodeBuffer& gb, const StringRef& reply) // Save the height map and append the success or error message to 'reply', returning true if an error occurred bool GCodes::TrySaveHeightMap(const char *filename, const StringRef& reply) const noexcept { -#if HAS_LINUX_INTERFACE - // If we have a Linux interface and we're using it, the Linux components will take care of file I/O. - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + // If we have an SBC connected, the SBC service will take care of heightmap-related file I/O + if (reprap.UsingSbcInterface()) { reply.copy("Cannot use height map on local SD card when SBC interface is used"); return true; @@ -3209,7 +3209,7 @@ GCodeResult GCodes::SaveHeightMap(GCodeBuffer& gb, const StringRef& reply) const { ReadLocker locker(reprap.GetMove().heightMapLock); - // No need to check if we're using the Linux interface here, because TrySaveHeightMap does that + // No need to check if we're using the SBC interface here, because TrySaveHeightMap does that already if (gb.Seen('P')) { String<MaxFilenameLength> heightMapFileName; @@ -3312,8 +3312,8 @@ void GCodes::StartPrinting(bool fromStart) noexcept rawExtruderTotal = 0.0; reprap.GetMove().ResetExtruderPositions(); -#if HAS_LINUX_INTERFACE - if (!reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (!reprap.UsingSbcInterface()) #endif { #if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES @@ -3755,8 +3755,8 @@ void GCodes::HandleReply(GCodeBuffer& gb, GCodeResult rslt, const char* reply) n // Note that 'reply' may be empty. If it isn't, then we need to append newline when sending it. void GCodes::HandleReplyPreserveResult(GCodeBuffer& gb, GCodeResult rslt, const char *reply) noexcept { -#if HAS_LINUX_INTERFACE - // Deal with replies to the Linux interface +#if HAS_SBC_INTERFACE + // Deal with replies to the SBC if (gb.LatestMachineState().lastCodeFromSbc) { MessageType type = gb.GetResponseMessageType(); @@ -3859,8 +3859,8 @@ void GCodes::HandleReply(GCodeBuffer& gb, OutputBuffer *reply) noexcept return; } -#if HAS_LINUX_INTERFACE - // Deal with replies to the Linux interface +#if HAS_SBC_INTERFACE + // Deal with replies to the SBC if (gb.IsBinary()) { platform.Message(gb.GetResponseMessageType(), reply); @@ -4136,8 +4136,8 @@ void GCodes::StopPrint(StopPrintReason reason) noexcept deferredPauseCommandPending = nullptr; pauseState = PauseState::notPaused; -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { fileGCode->LatestMachineState().CloseFile(); fileGCode->Init(); @@ -4250,7 +4250,7 @@ void GCodes::StopPrint(StopPrintReason reason) noexcept platform.MessageF(LoggedGenericMessage, "%s printing file %s, print time was %" PRIu32 "h %" PRIu32 "m\n", (reason == StopPrintReason::normalCompletion) ? "Finished" : "Cancelled", printingFilename, printMinutes/60u, printMinutes % 60u); -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE if (reason == StopPrintReason::normalCompletion && !IsSimulating()) { platform.DeleteSysFile(RESUME_AFTER_POWER_FAIL_G); @@ -4527,7 +4527,7 @@ void GCodes::SetAllAxesNotHomed() noexcept } } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE // Write the config-override file returning true if an error occurred GCodeResult GCodes::WriteConfigOverrideFile(GCodeBuffer& gb, const StringRef& reply) const noexcept @@ -4995,9 +4995,9 @@ void GCodes::ActivateHeightmap(bool activate) noexcept reprap.GetMove().GetCurrentUserPosition(moveState.coords, 0, reprap.GetCurrentTool()); ToolOffsetInverseTransform(moveState.coords, moveState.currentUserPosition); // update user coordinates to reflect any height map offset at the current position -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE // Set a dummy heightmap filename - if (reprap.UsingLinuxInterface()) + if (reprap.UsingSbcInterface()) { HeightMap& map = reprap.GetMove().AccessHeightMap(); map.SetFileName(DefaultHeightMapFile); @@ -5016,8 +5016,8 @@ bool GCodes::CheckNetworkCommandAllowed(GCodeBuffer& gb, const StringRef& reply, return false; // just ignore the command but report success } -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { // Networking is disabled when using the SBC interface, to save RAM reply.copy("Network-related commands are not supported when using an attached Single Board Computer"); diff --git a/src/GCodes/GCodes.h b/src/GCodes/GCodes.h index 8863ff89..5724bc6e 100644 --- a/src/GCodes/GCodes.h +++ b/src/GCodes/GCodes.h @@ -67,7 +67,7 @@ enum class PauseReason #endif }; -// Keep this in sync with PrintStopReason in Linux/MessageFormats.h +// Keep this in sync with PrintStopReason in SBC/SbcMessageFormats.h enum class StopPrintReason { normalCompletion, @@ -110,7 +110,7 @@ enum class SimulationMode : uint8_t highest = partial }; -class LinuxInterface; +class SbcInterface; // The GCode interpreter @@ -228,7 +228,7 @@ public: int GetNewToolNumber() const noexcept { return newToolNumber; } size_t GetCurrentZProbeNumber() const noexcept { return currentZProbeNumber; } - // These next two are public because they are used by class LinuxInterface + // These next two are public because they are used by class SbcInterface void UnlockAll(const GCodeBuffer& gb) noexcept; // Release all locks GCodeBuffer *GetGCodeBuffer(GCodeChannel channel) const noexcept { return gcodeSources[channel.ToBaseType()]; } @@ -424,7 +424,7 @@ private: #if SUPPORT_WORKPLACE_COORDINATES GCodeResult GetSetWorkplaceCoordinates(GCodeBuffer& gb, const StringRef& reply, bool compute) THROWS(GCodeException); // Set workspace coordinates -# if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +# if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool WriteWorkplaceCoordinates(FileStore *f) const noexcept; # endif #endif @@ -483,13 +483,13 @@ private: GCodeResult UpdateFirmware(GCodeBuffer& gb, const StringRef &reply) THROWS(GCodeException); // Handle M997 GCodeResult SendI2c(GCodeBuffer& gb, const StringRef &reply) THROWS(GCodeException); // Handle M260 GCodeResult ReceiveI2c(GCodeBuffer& gb, const StringRef &reply) THROWS(GCodeException); // Handle M261 -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES GCodeResult SimulateFile(GCodeBuffer& gb, const StringRef &reply, const StringRef& file, bool updateFile) THROWS(GCodeException); // Handle M37 to simulate a whole file GCodeResult ChangeSimulationMode(GCodeBuffer& gb, const StringRef &reply, SimulationMode newSimMode) THROWS(GCodeException); // Handle M37 to change the simulation mode #endif GCodeResult WaitForPin(GCodeBuffer& gb, const StringRef &reply) THROWS(GCodeException); // Handle M577 -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE GCodeResult WriteConfigOverrideFile(GCodeBuffer& gb, const StringRef& reply) const noexcept; // Write the config-override file bool WriteConfigOverrideHeader(FileStore *f) const noexcept; // Write the config-override header #endif @@ -507,7 +507,7 @@ private: void EndSimulation(GCodeBuffer *gb) noexcept; // Restore positions etc. when exiting simulation mode bool IsCodeQueueIdle() const noexcept; // Return true if the code queue is idle -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE void SaveResumeInfo(bool wasPowerFailure) noexcept; #endif @@ -541,7 +541,7 @@ private: Platform& platform; // The RepRap machine -#if HAS_NETWORKING || HAS_LINUX_INTERFACE +#if HAS_NETWORKING || HAS_SBC_INTERFACE NetworkGCodeInput* httpInput; // These cache incoming G-codes... NetworkGCodeInput* telnetInput; // ... #endif @@ -624,7 +624,7 @@ private: #if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES FileData fileToPrint; // The next file to print #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES FilePosition fileOffsetToPrint; // The offset to print from #endif diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp index 8cfa658d..8a41bb53 100644 --- a/src/GCodes/GCodes2.cpp +++ b/src/GCodes/GCodes2.cpp @@ -12,8 +12,8 @@ #include "GCodeException.h" #include "GCodeQueue.h" #include "Heating/Heat.h" -#if HAS_LINUX_INTERFACE -# include <Linux/LinuxInterface.h> +#if HAS_SBC_INTERFACE +# include <SBC/SbcInterface.h> #endif #include <Movement/Move.h> #include <Networking/Network.h> @@ -281,10 +281,10 @@ bool GCodes::HandleGcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx case 29: // Grid-based bed probing -#if HAS_LINUX_INTERFACE - // Pass file- and system-related commands to DSF if they came from somewhere else. +#if HAS_SBC_INTERFACE + // Pass file- and system-related commands to the SBC service if they came from anywhere else. // They will be passed back to us via a binary buffer or separate SPI message if necessary. - if (reprap.UsingLinuxInterface() && reprap.GetLinuxInterface().IsConnected() && !gb.IsBinary()) + if (reprap.UsingSbcInterface() && reprap.GetSbcInterface().IsConnected() && !gb.IsBinary()) { gb.SendToSbc(); return false; @@ -471,9 +471,10 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx return true; // we don't simulate most M codes } -#if HAS_LINUX_INTERFACE - // Pass file- and system-related commands to DSF if they came from somewhere else. They will be passed back to us via a binary buffer or separate SPI message if necessary. - if ( reprap.UsingLinuxInterface() && reprap.GetLinuxInterface().IsConnected() && !gb.IsBinary() +#if HAS_SBC_INTERFACE + // Pass file- and system-related commands to the SBC service if they came from somewhere else. + // They will be passed back to us via a binary buffer or separate SPI message if necessary. + if ( reprap.UsingSbcInterface() && reprap.GetSbcInterface().IsConnected() && !gb.IsBinary() && ( code == 0 || code == 1 || code == 20 || code == 21 || code == 22 || code == 23 || code == 24 || code == 26 || code == 27 || code == 28 || code == 29 || code == 30 || code == 32 || code == 36 || code == 37 || code == 38 || code == 39 @@ -847,7 +848,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx break; #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES case 23: // Set file to print case 32: // Select file and start SD print // We now allow a file that is being printed to chain to another file. This is required for the resume-after-power-fail functionality. @@ -866,8 +867,8 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx String<MaxFilenameLength> filename; gb.GetUnprecedentedString(filename.GetRef()); if ( -#if HAS_LINUX_INTERFACE - reprap.UsingLinuxInterface() +#if HAS_SBC_INTERFACE + reprap.UsingSbcInterface() # if HAS_MASS_STORAGE || # endif @@ -932,15 +933,15 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx } } } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES else if ( # if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES !fileToPrint.IsLive() # else true # endif -# if HAS_LINUX_INTERFACE - && !reprap.UsingLinuxInterface() +# if HAS_SBC_INTERFACE + && !reprap.UsingSbcInterface() # endif ) { @@ -964,8 +965,8 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx // We executed M26 to set the file offset, which normally means that we are executing resurrect.g. // We need to copy the absolute/relative and volumetric extrusion flags over fileGCode->OriginalMachineState().CopyStateFrom(gb.LatestMachineState()); -# if HAS_LINUX_INTERFACE - if (!reprap.UsingLinuxInterface()) +# if HAS_SBC_INTERFACE + if (!reprap.UsingSbcInterface()) # endif # if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES { @@ -1057,7 +1058,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx } break; -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES case 26: // Set SD position // This is used between executing M23 to set up the file to print, and M25 to print it gb.MustSee('S'); @@ -1123,10 +1124,10 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx // For case 32, see case 23 -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES case 36: // Return file information -# if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +# if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { reprap.GetFileInfoResponse(nullptr, outBuf, true); } @@ -1147,8 +1148,8 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx break; case 37: // Simulation mode on/off, or simulate a whole file -# if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface() && !gb.IsBinary()) +# if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface() && !gb.IsBinary()) { reply.copy("M37 can be only started from the SBC interface"); result = GCodeResult::error; @@ -2558,8 +2559,8 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx // Don't lock the movement system, because if we do then only the channel that issues the M291 can move the axes if (sParam == 2 || sParam == 3) { -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { gb.SetState(GCodeState::waitingForAcknowledgement); } @@ -2989,13 +2990,13 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx result = buildObjects.HandleM486(gb, reply, outBuf); break; -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE case 500: // Store parameters in config-override.g result = WriteConfigOverrideFile(gb, reply); break; #endif -#if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES || HAS_SBC_INTERFACE case 501: // Load parameters from config-override.g if (!gb.LatestMachineState().runningM502 && !gb.LatestMachineState().runningM501) // when running M502 we ignore config-override.g { @@ -3111,8 +3112,8 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx break; case 550: // Set/report machine name -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface() && !gb.IsBinary()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface() && !gb.IsBinary()) { result = GCodeResult::errorNotSupported; } @@ -3573,11 +3574,11 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx } break; -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE case 576: // Set SPI communication parameters - if (reprap.UsingLinuxInterface()) + if (reprap.UsingSbcInterface()) { - result = reprap.GetLinuxInterface().HandleM576(gb, reply); + result = reprap.GetSbcInterface().HandleM576(gb, reply); } else { @@ -4444,7 +4445,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx break; #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE case 916: if (!platform.SysFileExists(RESUME_AFTER_POWER_FAIL_G)) { diff --git a/src/GCodes/GCodes3.cpp b/src/GCodes/GCodes3.cpp index b5ac630d..4bb98433 100644 --- a/src/GCodes/GCodes3.cpp +++ b/src/GCodes/GCodes3.cpp @@ -204,7 +204,7 @@ GCodeResult GCodes::GetSetWorkplaceCoordinates(GCodeBuffer& gb, const StringRef& return GCodeResult::ok; } -# if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +# if HAS_MASS_STORAGE || HAS_SBC_INTERFACE // Save all the workplace coordinate offsets to file returning true if successful. Used by M500 and by SaveResumeInfo. bool GCodes::WriteWorkplaceCoordinates(FileStore *f) const noexcept @@ -405,7 +405,7 @@ GCodeResult GCodes::DefineGrid(GCodeBuffer& gb, const StringRef &reply) THROWS(G } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES // Handle M37 to simulate a whole file GCodeResult GCodes::SimulateFile(GCodeBuffer& gb, const StringRef &reply, const StringRef& file, bool updateFile) @@ -418,8 +418,8 @@ GCodeResult GCodes::SimulateFile(GCodeBuffer& gb, const StringRef &reply, const # if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES if ( -# if HAS_LINUX_INTERFACE - reprap.UsingLinuxInterface() || +# if HAS_SBC_INTERFACE + reprap.UsingSbcInterface() || # endif QueueFileToPrint(file.c_str(), reply)) # endif @@ -432,8 +432,8 @@ GCodeResult GCodes::SimulateFile(GCodeBuffer& gb, const StringRef &reply, const } simulationTime = 0.0; exitSimulationWhenFileComplete = true; -# if HAS_LINUX_INTERFACE - updateFileWhenSimulationComplete = updateFile && !reprap.UsingLinuxInterface(); +# if HAS_SBC_INTERFACE + updateFileWhenSimulationComplete = updateFile && !reprap.UsingSbcInterface(); # else updateFileWhenSimulationComplete = updateFile; # endif diff --git a/src/GCodes/GCodes4.cpp b/src/GCodes/GCodes4.cpp index 8351be96..fa1cc47d 100644 --- a/src/GCodes/GCodes4.cpp +++ b/src/GCodes/GCodes4.cpp @@ -8,8 +8,8 @@ #include <Heating/Heat.h> #include <Endstops/ZProbe.h> -#if HAS_LINUX_INTERFACE -# include <Linux/LinuxInterface.h> +#if HAS_SBC_INTERFACE +# include <SBC/SbcInterface.h> #endif #if HAS_WIFI_NETWORKING || HAS_AUX_DEVICES @@ -22,9 +22,9 @@ // So any large local objects allocated here increase the amount of MAIN stack size needed. void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept { -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE // Wait for the G-code replies and abort requests to go before anything else is done in the state machine - if (reprap.UsingLinuxInterface() && (gb.IsAbortRequested() || gb.IsAbortAllRequested())) + if (reprap.UsingSbcInterface() && (gb.IsAbortRequested() || gb.IsAbortAllRequested())) { return; } @@ -499,8 +499,8 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept } platform.MessageF(LogWarn, "%s\n", reply.c_str()); pauseState = PauseState::paused; -#if HAS_LINUX_INTERFACE - reportPause = reprap.UsingLinuxInterface(); +#if HAS_SBC_INTERFACE + reportPause = reprap.UsingSbcInterface(); #endif gb.SetState(GCodeState::normal); } @@ -909,8 +909,8 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept reply.printf("%" PRIu32 " points probed, min error %.3f, max error %.3f, mean %.3f, deviation %.3f\n", numPointsProbed, (double)minError, (double)maxError, (double)deviation.GetMean(), (double)deviation.GetDeviationFromMean()); #if HAS_MASS_STORAGE -# if HAS_LINUX_INTERFACE - if (!reprap.UsingLinuxInterface()) +# if HAS_SBC_INTERFACE + if (!reprap.UsingSbcInterface()) # endif { if (TrySaveHeightMap(DefaultHeightMapFile, reply)) @@ -1440,7 +1440,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept } else { -# if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +# if HAS_MASS_STORAGE || HAS_SBC_INTERFACE SaveResumeInfo(true); // create the resume file so that we can resume after power down # endif platform.Message(LoggedGenericMessage, "Print auto-paused due to low voltage\n"); @@ -1521,7 +1521,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept break; #endif -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE case GCodeState::waitingForAcknowledgement: // finished M291 and the SBC expects a response next #endif case GCodeState::checkError: // we return to this state after running the retractprobe macro when there may be a stored error message @@ -1543,11 +1543,11 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept HandleReply(gb, stateMachineResult, reply.c_str()); CheckForDeferredPause(gb); -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE if (reportPause) { fileGCode->Invalidate(); - reprap.GetLinuxInterface().ReportPause(); + reprap.GetSbcInterface().ReportPause(); } #endif } diff --git a/src/GCodes/ObjectTracker.cpp b/src/GCodes/ObjectTracker.cpp index fd1af4c1..5db37dbc 100644 --- a/src/GCodes/ObjectTracker.cpp +++ b/src/GCodes/ObjectTracker.cpp @@ -265,7 +265,7 @@ void ObjectTracker::ResumePrinting(GCodeBuffer& gb) noexcept } } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE // Write the object details to file, returning true if successful bool ObjectTracker::WriteObjectDirectory(FileStore *f) const noexcept diff --git a/src/GCodes/ObjectTracker.h b/src/GCodes/ObjectTracker.h index a3b2b098..6f5d8670 100644 --- a/src/GCodes/ObjectTracker.h +++ b/src/GCodes/ObjectTracker.h @@ -52,7 +52,7 @@ public: bool IsCancelled(size_t objectNumber) const noexcept { return objectsCancelled.IsBitSet(objectNumber); } #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool WriteObjectDirectory(FileStore *f) const noexcept; #endif diff --git a/src/Heating/FOPDT.cpp b/src/Heating/FOPDT.cpp index 911e9100..22b3f414 100644 --- a/src/Heating/FOPDT.cpp +++ b/src/Heating/FOPDT.cpp @@ -7,7 +7,7 @@ #include "FOPDT.h" -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE # include "Storage/FileStore.h" #endif @@ -151,7 +151,7 @@ void FopDt::SetRawPidParameters(float p_kP, float p_recipTi, float p_tD) noexcep pidParametersOverridden = true; } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE // Write the model parameters to file returning true if no error bool FopDt::WriteParameters(FileStore *f, size_t heater) const noexcept diff --git a/src/Heating/FOPDT.h b/src/Heating/FOPDT.h index 23802165..e69c3ac6 100644 --- a/src/Heating/FOPDT.h +++ b/src/Heating/FOPDT.h @@ -73,7 +73,7 @@ public: return (forLoadChange) ? loadChangeParams : setpointChangeParams; } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool WriteParameters(FileStore *f, size_t heater) const noexcept; // erite the model parameters to file returning true if no error #endif diff --git a/src/Heating/Heat.cpp b/src/Heating/Heat.cpp index f5705c7d..93df38e2 100644 --- a/src/Heating/Heat.cpp +++ b/src/Heating/Heat.cpp @@ -889,7 +889,7 @@ float Heat::GetHighestTemperatureLimit() const noexcept return limit; } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE // Write heater model parameters to file returning true if no error bool Heat::WriteModelParameters(FileStore *f) const noexcept @@ -1255,7 +1255,7 @@ void Heat::InsertSensor(TemperatureSensor *newSensor) noexcept } } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE // Save some resume information returning true if successful. // We assume that the bed and chamber heaters are either on and active, or off (not on standby). diff --git a/src/Heating/Heat.h b/src/Heating/Heat.h index 6d619e91..11418186 100644 --- a/src/Heating/Heat.h +++ b/src/Heating/Heat.h @@ -129,7 +129,7 @@ public: void FeedForwardAdjustment(unsigned int heater, float fanPwmChange, float extrusionChange) const noexcept; void SetExtrusionFeedForward(unsigned int heater, float pwm) const noexcept; -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool WriteModelParameters(FileStore *f) const noexcept; // Write heater model parameters to file returning true if no error bool WriteBedAndChamberTempSettings(FileStore *f) const noexcept; // Save some resume information #endif diff --git a/src/Linux/LinuxInterface.cpp b/src/Linux/LinuxInterface.cpp deleted file mode 100644 index 202c75f7..00000000 --- a/src/Linux/LinuxInterface.cpp +++ /dev/null @@ -1,1722 +0,0 @@ -/* - * LinuxInterface.cpp - * - * Created on: 29 Mar 2019 - * Author: Christian - */ - -#include "LinuxInterface.h" -#include "DataTransfer.h" - -#if HAS_LINUX_INTERFACE - -#include <GCodes/GCodeBuffer/ExpressionParser.h> -#include <GCodes/GCodeBuffer/GCodeBuffer.h> -#include <Heating/Heat.h> -#include <Movement/Move.h> -#include <Platform/Platform.h> -#include <PrintMonitor/PrintMonitor.h> -#include <Tools/Filament.h> -#include <Platform/RepRap.h> -#include <RepRapFirmware.h> -#include <Platform/Tasks.h> -#include <Hardware/SoftwareReset.h> -#include <Hardware/ExceptionHandlers.h> -#include <Platform/TaskPriorities.h> - -extern char _estack; // defined by the linker - -volatile OutputStack LinuxInterface::gcodeReply; -Mutex LinuxInterface::gcodeReplyMutex; - -// The SBC stack size needs to be enough to support rr_model and expression evaluation -// In RRF 3.3beta3, 744 is only just enough for simple expression evaluation in a release build when using globals -// In 3.3beta3.1 we have saved ~151 bytes (37 words) of stack compared to 3.3beta3 -#ifdef __LPC17xx__ -constexpr size_t SBCTaskStackWords = 375; -#elif defined(DEBUG) -constexpr size_t SBCTaskStackWords = 1200; // debug builds use more stack -#else -constexpr size_t SBCTaskStackWords = 1000; // increased from 820 so that we can evaluate "abs(move.calibration.initial.deviation - move.calibration.final.deviation) < 0.000" -#endif - -constexpr uint32_t LinuxYieldTimeout = 10; - -static Task<SBCTaskStackWords> *sbcTask; - -extern "C" [[noreturn]] void SBCTaskStart(void * pvParameters) noexcept -{ - reprap.GetLinuxInterface().TaskLoop(); -} - -LinuxInterface::LinuxInterface() noexcept : isConnected(false), numDisconnects(0), numTimeouts(0), - maxDelayBetweenTransfers(SpiTransferDelay), maxFileOpenDelay(SpiFileOpenDelay), numMaxEvents(SpiEventsRequired), - delaying(false), numEvents(0), reportPause(false), reportPauseWritten(false), printAborted(false), - codeBuffer(nullptr), rxPointer(0), txPointer(0), txEnd(0), sendBufferUpdate(true), writingIap(false), iapWritePointer(IAP_IMAGE_START), - waitingForFileChunk(false), fileMutex(), fileSemaphore(), fileOperation(FileOperation::none), fileOperationPending(false) -#ifdef TRACK_FILE_CODES - , fileCodesRead(0), fileCodesHandled(0), fileMacrosRunning(0), fileMacrosClosing(0) -#endif -{ -} - -void LinuxInterface::Init() noexcept -{ - if (reprap.UsingLinuxInterface()) - { - fileMutex.Create("SBCFile"); - gcodeReplyMutex.Create("SBCReply"); - codeBuffer = (char *)new uint32_t[(SpiCodeBufferSize + 3)/4]; - -#if defined(DUET_NG) - // Make sure that the Wifi module if present is disabled. The ESP Reset pin is already forced low in Platform::Init(); - pinMode(EspEnablePin, OUTPUT_LOW); -#endif - - transfer.Init(); - sbcTask = new Task<SBCTaskStackWords>(); - sbcTask->Create(SBCTaskStart, "SBC", nullptr, TaskPriority::SbcPriority); - iapRamAvailable = &_estack - Tasks::GetHeapTop(); - } - else - { - // Set up the data transfer to exchange the header + response code. No task is started to save memory - transfer.Init(); - } -} - -void LinuxInterface::Spin() noexcept -{ - if (transfer.IsReady()) - { - // Don't process anything, just kick off the next transfer to report we're operating in standalone mode - transfer.StartNextTransfer(); - } -} - -[[noreturn]] void LinuxInterface::TaskLoop() noexcept -{ - transfer.InitFromTask(); - transfer.StartNextTransfer(); - - bool isReady = false, hadReset = false, skipNextDelay = false; - for (;;) - { - if (hadReset) - { - isReady = true; - hadReset = false; - } - else if (transfer.IsReady()) - { - isReady = true; - hadReset = isConnected && transfer.LinuxHadReset(); - } - else - { - isReady = false; - } - - if (isReady && !hadReset) - { - // Check if the connection state has changed - if (!isConnected && !writingIap) - { - isConnected = true; - reprap.GetPlatform().Message(NetworkInfoMessage, "Connection to Linux established!\n"); - } - - // Process incoming packets - bool codeBufferAvailable = true; - for (size_t i = 0; i < transfer.PacketsToRead(); i++) - { - const PacketHeader * const packet = transfer.ReadPacket(); - if (packet == nullptr) - { - if (reprap.Debug(moduleLinuxInterface)) - { - debugPrintf("Error trying to read next SPI packet\n"); - } - break; - } - - if (packet->request >= (uint16_t)LinuxRequest::InvalidRequest) - { - REPORT_INTERNAL_ERROR; - break; - } - - bool packetAcknowledged = true; - switch ((LinuxRequest)packet->request) - { - // Perform an emergency stop - case LinuxRequest::EmergencyStop: - reprap.EmergencyStop(); - break; - - // Reset the controller - case LinuxRequest::Reset: - SoftwareReset(SoftwareResetReason::user); - break; - - // Perform a G/M/T-code - case LinuxRequest::Code: - { - // Read the next code - if (packet->length == 0) - { - reprap.GetPlatform().Message(WarningMessage, "Received empty binary code, discarding\n"); - break; - } - - const CodeHeader *code = reinterpret_cast<const CodeHeader*>(transfer.ReadData(packet->length)); - const GCodeChannel channel(code->channel); - GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); - if (gb->IsInvalidated()) - { - // Don't deal with codes that will be thrown away - break; - } - - // Check if a GB is waiting for a macro file to be started - if (gb->IsWaitingForMacro() && !gb->IsMacroRequestPending()) - { - gb->ResolveMacroRequest(false, false); -#ifdef TRACK_FILE_CODES - if (channel == GCodeChannel::File) - { - fileMacrosRunning++; - } -#endif - } - - // Don't process any more codes if we failed to store them last time... - if (!codeBufferAvailable) - { - packetAcknowledged = false; - break; - } - - TaskCriticalSectionLocker locker; - - // Make sure no existing codes are overwritten - uint16_t bufferedCodeSize = sizeof(BufferedCodeHeader) + packet->length; - if ((txEnd == 0 && bufferedCodeSize > max<uint16_t>(rxPointer, SpiCodeBufferSize - txPointer)) || - (txEnd != 0 && bufferedCodeSize > rxPointer - txPointer)) - { - //debugPrintf("Failed to store code, RX/TX %d/%d-%d\n", rxPointer, txPointer, txEnd); - packetAcknowledged = codeBufferAvailable = false; - break; - } - - // Overlap if necessary - if (txPointer + bufferedCodeSize > SpiCodeBufferSize) - { - txEnd = txPointer; - txPointer = 0; - sendBufferUpdate = true; - } - - // Store the buffer header - BufferedCodeHeader *bufHeader = reinterpret_cast<BufferedCodeHeader *>(codeBuffer + txPointer); - bufHeader->isPending = true; - bufHeader->length = packet->length; - - // Store the corresponding code. Binary codes are always aligned on a 4-byte boundary - uint32_t *dst = reinterpret_cast<uint32_t *>(codeBuffer + txPointer + sizeof(BufferedCodeHeader)); - const uint32_t *src = reinterpret_cast<const uint32_t *>(code); - memcpyu32(dst, src, packet->length / sizeof(uint32_t)); - txPointer += bufferedCodeSize; - break; - } - - // Get the object model - case LinuxRequest::GetObjectModel: - { - String<StringLength100> key; - String<StringLength20> flags; - transfer.ReadGetObjectModel(packet->length, key.GetRef(), flags.GetRef()); - - try - { - OutputBuffer *outBuf = reprap.GetModelResponse(key.c_str(), flags.c_str()); - if (outBuf == nullptr || !transfer.WriteObjectModel(outBuf)) - { - // Failed to write the whole object model, try again later - packetAcknowledged = false; - OutputBuffer::ReleaseAll(outBuf); - } - } - catch (const GCodeException& e) - { - // Get the error message and send it back to DSF - OutputBuffer *buf; - if (OutputBuffer::Allocate(buf)) - { - String<StringLength100> errorMessage; - e.GetMessage(errorMessage.GetRef(), nullptr); - buf->cat(errorMessage.c_str()); - if (!transfer.WriteObjectModel(buf)) - { - OutputBuffer::ReleaseAll(buf); - packetAcknowledged = false; - } - } - else - { - packetAcknowledged = false; - } - } - break; - } - - // Set value in the object model - case LinuxRequest::SetObjectModel: - { - const size_t dataLength = packet->length; - const char * const data = transfer.ReadData(dataLength); - // TODO implement this - (void)data; - break; - } - - // Print is about to be started, set file print info - case LinuxRequest::SetPrintFileInfo: - { - String<MaxFilenameLength> filename; - transfer.ReadPrintStartedInfo(packet->length, filename.GetRef(), fileInfo); - reprap.GetPrintMonitor().SetPrintingFileInfo(filename.c_str(), fileInfo); - break; - } - - // Print has been stopped - case LinuxRequest::PrintStopped: - { - const PrintStoppedReason reason = transfer.ReadPrintStoppedInfo(); - if (reason == PrintStoppedReason::abort) - { - // Stop the print with the given reason - printAborted = true; - InvalidateBufferedCodes(GCodeChannel::File); - } - else - { - // Just mark the print file as finished - GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(GCodeChannel::File); - MutexLocker locker(gb->mutex, LinuxYieldTimeout); - if (locker.IsAcquired()) - { - gb->SetPrintFinished(); - } - else - { - packetAcknowledged = false; - } - } - break; - } - - // Macro file has been finished - case LinuxRequest::MacroCompleted: - { - bool error; - const GCodeChannel channel = transfer.ReadMacroCompleteInfo(error); - if (channel.IsValid()) - { - GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); - if (gb->IsWaitingForMacro() && !gb->IsMacroRequestPending()) - { - gb->ResolveMacroRequest(error, true); - if (reprap.Debug(moduleLinuxInterface)) - { - debugPrintf("Waiting macro completed on channel %u\n", channel.ToBaseType()); - } - } - else - { - MutexLocker locker(gb->mutex, LinuxYieldTimeout); - if (locker.IsAcquired()) - { - if (error) - { - gb->CurrentFileMachineState().CloseFile(); - gb->PopState(); - gb->Init(); - } - else - { -#ifdef TRACK_FILE_CODES - if (channel == GCodeChannel::File) - { - fileMacrosClosing++; - } -#endif - gb->SetFileFinished(); - } - - if (reprap.Debug(moduleLinuxInterface)) - { - debugPrintf("Macro completed on channel %u\n", channel.ToBaseType()); - } - } - else - { - packetAcknowledged = false; - } - } - } - else - { - REPORT_INTERNAL_ERROR; - } - break; - } - - // Return heightmap as generated by G29 S0 - case LinuxRequest::GetHeightMap: - { - ConditionalReadLocker locker(reprap.GetMove().heightMapLock); - if (locker.IsLocked()) - { - packetAcknowledged = transfer.WriteHeightMap(); - } - else - { - packetAcknowledged = false; - } - break; - } - - // Set heightmap via G29 S1 - case LinuxRequest::SetHeightMap: - { - ConditionalWriteLocker locker(reprap.GetMove().heightMapLock); - if (locker.IsLocked()) - { - if (!transfer.ReadHeightMap()) - { - reprap.GetPlatform().Message(ErrorMessage, "Failed to set height map - bad data?\n"); - } - } - else - { - packetAcknowledged = false; - } - break; - } - - // Lock movement and wait for standstill - case LinuxRequest::LockMovementAndWaitForStandstill: - { - const GCodeChannel channel = transfer.ReadCodeChannel(); - if (channel.IsValid()) - { - GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); - MutexLocker locker(gb->mutex, LinuxYieldTimeout); - if (locker.IsAcquired() && reprap.GetGCodes().LockMovementAndWaitForStandstill(*gb)) - { - transfer.WriteLocked(channel); - } - else - { - packetAcknowledged = false; - } - } - else - { - REPORT_INTERNAL_ERROR; - } - break; - } - - // Unlock everything - case LinuxRequest::Unlock: - { - const GCodeChannel channel = transfer.ReadCodeChannel(); - if (channel.IsValid()) - { - GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); - MutexLocker locker(gb->mutex, LinuxYieldTimeout); - if (locker.IsAcquired()) - { - reprap.GetGCodes().UnlockAll(*gb); - } - else - { - packetAcknowledged = false; - } - } - else - { - REPORT_INTERNAL_ERROR; - } - break; - } - - // Write another chunk of the IAP binary to the designated Flash area - case LinuxRequest::WriteIap: - { - if (iapWritePointer == IAP_IMAGE_START) // if start of IAP write - { - reprap.PrepareToLoadIap(); - writingIap = true; - } - - // Copy another IAP chunk. It's always bound on a 4-byte boundary - uint32_t *dst = reinterpret_cast<uint32_t *>(iapWritePointer); - const uint32_t *src = reinterpret_cast<const uint32_t *>(transfer.ReadData(packet->length)); - memcpyu32(dst, src, packet->length / sizeof(uint32_t)); - iapWritePointer += packet->length; - break; - } - - // Launch the IAP binary - case LinuxRequest::StartIap: - reprap.StartIap(nullptr); - break; - - // Assign filament (deprecated) - case LinuxRequest::AssignFilament_deprecated: - (void)transfer.ReadData(packet->length); // skip the packet content - break; - - // Return a file chunk - case LinuxRequest::FileChunk: - transfer.ReadFileChunk(requestedFileBuffer, requestedFileDataLength, requestedFileLength); - requestedFileSemaphore.Give(); - break; - - // Evaluate an expression - case LinuxRequest::EvaluateExpression: - { - String<GCODE_LENGTH> expression; - const GCodeChannel channel = transfer.ReadEvaluateExpression(packet->length, expression.GetRef()); - if (channel.IsValid()) - { - GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); - - // If there is a macro file waiting, the first instruction must be conditional. Don't block any longer... - if (gb->IsWaitingForMacro()) - { - gb->ResolveMacroRequest(false, false); -#ifdef TRACK_FILE_CODES - if (channel == GCodeChannel::File) - { - fileMacrosRunning++; - } -#endif - } - - try - { - // Evaluate the expression and send the result to DSF - MutexLocker lock(gb->mutex, LinuxYieldTimeout); - if (lock.IsAcquired()) - { - ExpressionParser parser(*gb, expression.c_str(), expression.c_str() + expression.strlen()); - const ExpressionValue val = parser.Parse(); - packetAcknowledged = transfer.WriteEvaluationResult(expression.c_str(), val); - } - else - { - packetAcknowledged = false; - } - } - catch (const GCodeException& e) - { - // Get the error message and send it back to DSF - String<StringLength100> errorMessage; - e.GetMessage(errorMessage.GetRef(), nullptr); - packetAcknowledged = transfer.WriteEvaluationError(expression.c_str(), errorMessage.c_str()); - } - } - else - { - REPORT_INTERNAL_ERROR; - } - break; - } - - // Send a firmware message, typically a response to a command that has been passed to DSF. - // These responses can get quite long (e.g. responses to M20) so receive it into an OutputBuffer. - case LinuxRequest::Message: - { - OutputBuffer *buf; - if (OutputBuffer::Allocate(buf)) - { - MessageType type; - if (transfer.ReadMessage(type, buf)) - { - // FIXME Push flag is not supported yet - reprap.GetPlatform().Message(type, buf); - } - else - { - // Not enough memory for reading the whole message, try again later - OutputBuffer::ReleaseAll(buf); - packetAcknowledged = false; - } - } - break; - } - - // Macro file has been started - case LinuxRequest::MacroStarted: - { - const GCodeChannel channel = transfer.ReadCodeChannel(); - if (channel.IsValid()) - { - GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); - if (gb->IsWaitingForMacro() && !gb->IsMacroRequestPending()) - { - // File exists and is open, but no code has arrived yet - gb->ResolveMacroRequest(false, false); -#ifdef TRACK_FILE_CODES - if (channel == GCodeChannel::File) - { - fileMacrosRunning++; - } -#endif - } - else if (channel != GCodeChannel::Daemon) - { - reprap.GetPlatform().MessageF(WarningMessage, "Macro file has been started on channel %s but none was requested\n", channel.ToString()); - } - else - { - // dameon.g is running, now the OM may report the file is being executed - reprap.InputsUpdated(); - } - } - else - { - REPORT_INTERNAL_ERROR; - } - break; - } - - // Invalidate all files and codes on a given channel - case LinuxRequest::InvalidateChannel: - { - const GCodeChannel channel = transfer.ReadCodeChannel(); - if (channel.IsValid()) - { - GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); - if (gb->IsWaitingForMacro()) - { - gb->ResolveMacroRequest(true, false); - } - - MutexLocker locker(gb->mutex, LinuxYieldTimeout); - if (locker.IsAcquired()) - { - // Note that we do not call StopPrint here or set any other variables; DSF already does that - gb->AbortFile(true, false); - InvalidateBufferedCodes(channel); - } - else - { - packetAcknowledged = false; - } - } - else - { - REPORT_INTERNAL_ERROR; - } - break; - } - - // Set the content of a variable - case LinuxRequest::SetVariable: - { - bool createVariable; - String<MaxVariableNameLength> varName; - String<GCODE_LENGTH> expression; - const GCodeChannel channel = transfer.ReadSetVariable(createVariable, varName.GetRef(), expression.GetRef()); - - // Make sure we can access the gb safely... - if (!channel.IsValid()) - { - REPORT_INTERNAL_ERROR; - break; - } - - GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); - MutexLocker lock(gb->mutex, LinuxYieldTimeout); - if (!lock.IsAcquired()) - { - packetAcknowledged = false; - break; - } - - // Get the variable set - const bool isGlobal = StringStartsWith(varName.c_str(), "global."); - if (!isGlobal && !StringStartsWith(varName.c_str(), "var.")) - { - packetAcknowledged = transfer.WriteSetVariableError(varName.c_str(), "expected a global or local variable"); - break; - } - WriteLockedPointer<VariableSet> vset = (isGlobal) ? reprap.GetGlobalVariablesForWriting() : WriteLockedPointer<VariableSet>(nullptr, &gb->GetVariables()); - - // Check if the variable is valid - const char *shortVarName = varName.c_str() + strlen(isGlobal ? "global." : "var."); - Variable * const v = vset->Lookup(shortVarName); - if (createVariable && v != nullptr) - { - // For now we don't allow an existing variable to be reassigned using a 'var' or 'global' statement. We may need to allow it for 'global' statements. - // Save memory by re-using 'expression' to capture the error message - expression.printf("variable '%s' already exists", varName.c_str()); - packetAcknowledged = transfer.WriteSetVariableError(varName.c_str(), expression.c_str()); - break; - } - if (!createVariable && v == nullptr) - { - // Save memory by re-using 'expression' to capture the error message - expression.printf("unknown variable '%s'", varName.c_str()); - packetAcknowledged = transfer.WriteSetVariableError(varName.c_str(), expression.c_str()); - break; - } - - // Evaluate the expression and assign it - try - { - ExpressionParser parser(*gb, expression.c_str(), expression.c_str() + expression.strlen()); - ExpressionValue ev = parser.Parse(); - if (v == nullptr) - { - // DSF doesn't provide indent values but instructs RRF to delete local variables when the current block ends - vset->InsertNew(shortVarName, ev, 0); - } - else - { - v->Assign(ev); - } - - transfer.WriteSetVariableResult(varName.c_str(), ev); - if (isGlobal) - { - reprap.GlobalUpdated(); - } - } - catch (const GCodeException& e) - { - // Get the error message and send it back to DSF - // Save memory by re-using 'expression' to capture the error message - e.GetMessage(expression.GetRef(), nullptr); - packetAcknowledged = transfer.WriteSetVariableError(varName.c_str(), expression.c_str()); - } - break; - } - - // Delete a local variable - case LinuxRequest::DeleteLocalVariable: - { - String<MaxVariableNameLength> varName; - const GCodeChannel channel = transfer.ReadDeleteLocalVariable(varName.GetRef()); - - // Make sure we can access the gb safely... - if (!channel.IsValid()) - { - REPORT_INTERNAL_ERROR; - break; - } - - GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); - MutexLocker lock(gb->mutex, LinuxYieldTimeout); - if (!lock.IsAcquired()) - { - packetAcknowledged = false; - break; - } - - // Try to delete the variable again - WriteLockedPointer<VariableSet> vset = WriteLockedPointer<VariableSet>(nullptr, &gb->GetVariables()); - vset.Ptr()->Delete(varName.c_str()); - break; - } - - // Result of a file exists check - case LinuxRequest::CheckFileExistsResult: - if (fileOperation == FileOperation::checkFileExists) - { - fileSuccess = transfer.ReadBoolean(); - fileOperation = FileOperation::none; - fileSemaphore.Give(); - } - else - { - REPORT_INTERNAL_ERROR; - } - break; - - - // Result of a deletion request - case LinuxRequest::FileDeleteResult: - if (fileOperation == FileOperation::deleteFileOrDirectory) - { - fileSuccess = transfer.ReadBoolean(); - fileOperation = FileOperation::none; - fileSemaphore.Give(); - } - else - { - REPORT_INTERNAL_ERROR; - } - break; - - // Result of a file open request - case LinuxRequest::OpenFileResult: - if (fileOperation == FileOperation::openRead || - fileOperation == FileOperation::openWrite || - fileOperation == FileOperation::openAppend) - { - fileHandle = transfer.ReadOpenFileResult(fileOffset); - fileSuccess = (fileHandle != noFileHandle); - fileOperation = FileOperation::none; - fileSemaphore.Give(); - } - else - { - REPORT_INTERNAL_ERROR; - } - break; - - // Result of a file read request - case LinuxRequest::FileReadResult: - if (fileOperation == FileOperation::read) - { - int bytesRead = transfer.ReadFileData(fileReadBuffer, fileBufferLength); - fileSuccess = bytesRead >= 0; - fileOffset = fileSuccess ? bytesRead : 0; - fileOperation = FileOperation::none; - fileSemaphore.Give(); - } - else - { - REPORT_INTERNAL_ERROR; - } - break; - - // Result of a file write request - case LinuxRequest::FileWriteResult: - if (fileOperation == FileOperation::write) - { - fileSuccess = transfer.ReadBoolean(); - if (!fileSuccess || fileBufferLength == 0) - { - fileOperationPending = false; - fileOperation = FileOperation::none; - fileSemaphore.Give(); - } - } - else - { - REPORT_INTERNAL_ERROR; - } - break; - - // Result of a file seek request - case LinuxRequest::FileSeekResult: - if (fileOperation == FileOperation::seek) - { - fileSuccess = transfer.ReadBoolean(); - fileOperation = FileOperation::none; - fileSemaphore.Give(); - } - else - { - REPORT_INTERNAL_ERROR; - } - break; - - // Result of a file seek request - case LinuxRequest::FileTruncateResult: - if (fileOperation == FileOperation::truncate) - { - fileSuccess = transfer.ReadBoolean(); - fileOperation = FileOperation::none; - fileSemaphore.Give(); - } - else - { - REPORT_INTERNAL_ERROR; - } - break; - - // Invalid request - default: - REPORT_INTERNAL_ERROR; - break; - } - - // Request the packet again if no response could be sent back - if (!packetAcknowledged) - { - transfer.ResendPacket(packet); - } - } - - if (!writingIap) // it's not safe to access other resources once we have started writing the IAP - { - // Check if we can wait a short moment to reduce CPU load on the SBC - if (!skipNextDelay && numEvents < numMaxEvents && !waitingForFileChunk && - !fileOperationPending && fileOperation == FileOperation::none) - { - delaying = true; - if (!TaskBase::Take(MassStorage::AnyFileOpen() ? maxFileOpenDelay : maxDelayBetweenTransfers)) - { - delaying = false; - } - } - numEvents = 0; - skipNextDelay = false; - - // Send code replies and generic messages - if (!gcodeReply.IsEmpty()) - { - MutexLocker lock(gcodeReplyMutex); - while (!gcodeReply.IsEmpty()) - { - const MessageType type = gcodeReply.GetFirstItemType(); - OutputBuffer *buffer = gcodeReply.GetFirstItem(); // this may be null - if (!transfer.WriteCodeReply(type, buffer)) // this handles the null case too - { - break; - } - gcodeReply.SetFirstItem(buffer); // this does a pop if buffer is null - } - } - - // Notify DSF about the available buffer space - if (!codeBufferAvailable || sendBufferUpdate) - { - TaskCriticalSectionLocker locker; - - const uint16_t bufferSpace = (txEnd == 0) ? max<uint16_t>(rxPointer, SpiCodeBufferSize - txPointer) : rxPointer - txPointer; - sendBufferUpdate = !transfer.WriteCodeBufferUpdate(bufferSpace); - } - - // Get another chunk of the file being requested - if (waitingForFileChunk && - !fileChunkRequestSent && transfer.WriteFileChunkRequest(requestedFileName.c_str(), requestedFileOffset, requestedFileLength)) - { - fileChunkRequestSent = true; - } - - // Perform the next file operation if requested - if (fileOperationPending) - { - switch (fileOperation) - { - case FileOperation::checkFileExists: - fileOperationPending = !transfer.WriteCheckFileExists(filePath); - break; - - case FileOperation::deleteFileOrDirectory: - fileOperationPending = !transfer.WriteDeleteFileOrDirectory(filePath); - break; - - case FileOperation::openRead: - case FileOperation::openWrite: - case FileOperation::openAppend: - fileOperationPending = !transfer.WriteOpenFile(filePath, fileOperation == FileOperation::openWrite || fileOperation == FileOperation::openAppend, fileOperation == FileOperation::openAppend, filePreAllocSize); - break; - - case FileOperation::read: - fileOperationPending = !transfer.WriteReadFile(fileHandle, fileBufferLength); - break; - - case FileOperation::write: - { - size_t bytesNotWritten = fileBufferLength; - if (transfer.WriteFileData(fileHandle, fileWriteBuffer, fileBufferLength)) - { - fileWriteBuffer += bytesNotWritten - fileBufferLength; - if (fileBufferLength == 0) - { - fileOperationPending = false; - } - } - break; - } - - case FileOperation::seek: - fileOperationPending = !transfer.WriteSeekFile(fileHandle, fileOffset); - break; - - case FileOperation::truncate: - fileOperationPending = !transfer.WriteTruncateFile(fileHandle); - break; - - case FileOperation::close: - fileOperationPending = !transfer.WriteCloseFile(fileHandle); - if (!fileOperationPending) - { - // Close requests don't get a result back, so they can be resolved as soon as they are sent to the SBC - fileOperation = FileOperation::none; - fileSemaphore.Give(); - } - break; - - default: - REPORT_INTERNAL_ERROR; - break; - } - } - - // Deal with code channel requests - for (size_t i = 0; i < NumGCodeChannels; i++) - { - const GCodeChannel channel(i); - GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); - - // Invalidate buffered codes if required - if (gb->IsInvalidated()) - { - InvalidateBufferedCodes(gb->GetChannel()); - gb->Invalidate(false); - } - - // Deal with macro files being closed - if (gb->IsMacroFileClosed() && transfer.WriteMacroFileClosed(channel)) - { - // Note this is only sent when a macro file has finished successfully - gb->MacroFileClosedSent(); - } - - // Handle blocking macro requests - if (gb->IsWaitingForMacro() && gb->IsMacroRequestPending()) - { - const char * const requestedMacroFile = gb->GetRequestedMacroFile(); - bool fromCode = gb->IsMacroStartedByCode(); - if (transfer.WriteMacroRequest(channel, requestedMacroFile, fromCode)) - { - if (reprap.Debug(moduleLinuxInterface)) - { - debugPrintf("Requesting macro file '%s' (fromCode: %s)\n", requestedMacroFile, fromCode ? "true" : "false"); - } - gb->MacroRequestSent(); - gb->Invalidate(); - } - } - - // Deal with other requests unless we are still waiting in a semaphore - if (!gb->IsWaitingForMacro()) - { - MutexLocker gbLock(gb->mutex, LinuxYieldTimeout); - if (gbLock.IsAcquired()) - { - if (gb->GetChannel() != GCodeChannel::Daemon) - { - skipNextDelay |= gb->IsMacroRequestPending() || gb->HasJustStartedMacro(); - } - - // Handle file abort requests - if (gb->IsAbortRequested() && transfer.WriteAbortFileRequest(channel, gb->IsAbortAllRequested())) - { -#ifdef TRACK_FILE_CODES - if (channel == GCodeChannel::File) - { - if (gb->IsAbortAllRequested()) - { - fileCodesRead = fileCodesHandled = fileMacrosRunning = fileMacrosClosing = 0; - } - else - { - fileMacrosClosing++; - } - } -#endif - gb->FileAbortSent(); - gb->Invalidate(); - } - - // Handle blocking messages and their results - if (gb->LatestMachineState().waitingForAcknowledgement && gb->IsMessagePromptPending() && - transfer.WriteWaitForAcknowledgement(channel)) - { - gb->MessagePromptSent(); - gb->Invalidate(); - } - else if (gb->IsMessageAcknowledged() && transfer.WriteMessageAcknowledged(channel)) - { - // Note this is only sent when a message was acknowledged in a regular way (i.e. by M292) - gb->MessageAcknowledgementSent(); - } - - // Handle non-blocking macro requests (e.g. daemon.g) - if (gb->IsMacroRequestPending()) - { - const char * const requestedMacroFile = gb->GetRequestedMacroFile(); - bool fromCode = gb->IsMacroStartedByCode(); - if (transfer.WriteMacroRequest(channel, requestedMacroFile, fromCode)) - { - if (reprap.Debug(moduleLinuxInterface)) - { - debugPrintf("Requesting non-blocking macro file '%s' (fromCode: %s)\n", requestedMacroFile, fromCode ? "true" : "false"); - } - gb->MacroRequestSent(); - gb->Invalidate(); - } - } - - // Send pending firmware codes - if (gb->IsSendRequested() && transfer.WriteDoCode(channel, gb->DataStart(), gb->DataLength())) - { - gb->SetFinished(true); - } - } - } - } - - // Send pause notification on demand - if (reportPause && transfer.WritePrintPaused(pauseFilePosition, pauseReason)) - { - reportPause = false; - } - } - - // Start the next transfer and wait for it to complete - transfer.StartNextTransfer(); - } - else if (!writingIap) - { - if (isConnected && (!transfer.IsConnected() || hadReset)) - { - isConnected = false; - numDisconnects++; - if (!hadReset) - { - numTimeouts++; - } - reprap.GetPlatform().Message(NetworkInfoMessage, "Lost connection to Linux\n"); - - rxPointer = txPointer = txEnd = 0; - sendBufferUpdate = true; - iapWritePointer = IAP_IMAGE_START; - - if (!requestedFileName.IsEmpty()) - { - requestedFileDataLength = -1; - requestedFileSemaphore.Give(); - } - - if (fileOperation != FileOperation::none) - { - fileOperation = FileOperation::none; - fileSemaphore.Give(); - } - MassStorage::InvalidateAllFiles(); - - // Don't cache any messages if they cannot be sent - { - MutexLocker lock(gcodeReplyMutex); - gcodeReply.ReleaseAll(); - } - - // Close all open G-code files - for (size_t i = 0; i < NumGCodeChannels; i++) - { - GCodeBuffer *gb = reprap.GetGCodes().GetGCodeBuffer(GCodeChannel(i)); - if (gb->IsWaitingForMacro()) - { - gb->ResolveMacroRequest(true, false); - } - - MutexLocker locker(gb->mutex); - if (gb->IsMacroRequestPending()) - { - gb->MacroRequestSent(); - } - gb->AbortFile(true, false); - gb->MessageAcknowledged(true); - } - - // Abort the print (if applicable) - printAborted = true; - - // Turn off all the heaters - reprap.GetHeat().SwitchOffAll(true); - - // Reset the SPI connection - transfer.ResetConnection(); - - if (hadReset) - { - // Let the main task invalidate resources - TaskBase::Take(LinuxYieldTimeout); - } - } - else if (isConnected || transfer.IsConnected()) - { - // Wait for the next SPI transaction to complete or for a timeout to occur - TaskBase::Take(SpiConnectionTimeout); - } - else - { - // Wait indefinitely for the next transfer - TaskBase::Take(); - } - } - } -} - -void LinuxInterface::Diagnostics(MessageType mtype) noexcept -{ - reprap.GetPlatform().Message(mtype, "=== SBC interface ===\n"); - transfer.Diagnostics(mtype); - reprap.GetPlatform().MessageF(mtype, "Disconnects: %" PRIu32 ", timeouts: %" PRIu32 ", IAP RAM available 0x%05" PRIx32 "\n", numDisconnects, numTimeouts, iapRamAvailable); - reprap.GetPlatform().MessageF(mtype, "Buffer RX/TX: %d/%d-%d\n", (int)rxPointer, (int)txPointer, (int)txEnd); -#ifdef TRACK_FILE_CODES - reprap.GetPlatform().MessageF(mtype, "File codes read/handled: %d/%d, file macros open/closing: %d %d\n", (int)fileCodesRead, (int)fileCodesHandled, (int)fileMacrosRunning, (int)fileMacrosClosing); -#endif -} - -GCodeResult LinuxInterface::HandleM576(GCodeBuffer& gb, const StringRef& reply) noexcept -{ - bool seen = false; - - if (gb.Seen('S')) - { - uint32_t sParam = gb.GetUIValue(); - if (sParam > SpiConnectionTimeout) - { - reply.printf("SPI transfer delay must not exceed %" PRIu32 "ms", SpiConnectionTimeout); - return GCodeResult::error; - } - maxDelayBetweenTransfers = sParam; - seen = true; - } - - if (gb.Seen('F')) - { - uint32_t fParam = gb.GetUIValue(); - if (fParam > SpiConnectionTimeout) - { - reply.printf("SPI transfer delay must not exceed %" PRIu32 "ms", SpiConnectionTimeout); - return GCodeResult::error; - } - maxFileOpenDelay = fParam; - seen = true; - } - - if (gb.Seen('P')) - { - numMaxEvents = gb.GetUIValue(); - seen = true; - } - - if (!seen) - { - reply.printf("Max transfer delay %" PRIu32 "ms, max number of events during delays: %" PRIu32, maxDelayBetweenTransfers, numMaxEvents); - } - return GCodeResult::ok; -} - -bool LinuxInterface::FillBuffer(GCodeBuffer &gb) noexcept -{ - if (gb.IsInvalidated() || gb.IsMacroFileClosed() || gb.IsMessageAcknowledged() || - gb.IsAbortRequested() || (reportPause && gb.GetChannel() == GCodeChannel::File) || - (gb.LatestMachineState().waitingForAcknowledgement && gb.IsMessagePromptPending())) - { - // Don't process codes that are supposed to be suspended... - return false; - } - - bool gotCommand = false; - { - //TODO can we take the lock inside the loop body instead, if we re-read readPointer and writePointer after taking it? - TaskCriticalSectionLocker locker; - if (rxPointer != txPointer || txEnd != 0) - { - bool updateRxPointer = true; - uint16_t readPointer = rxPointer; - do - { - BufferedCodeHeader *bufHeader = reinterpret_cast<BufferedCodeHeader*>(codeBuffer + readPointer); - readPointer += sizeof(BufferedCodeHeader); - const CodeHeader *codeHeader = reinterpret_cast<const CodeHeader*>(codeBuffer + readPointer); - readPointer += bufHeader->length; - - RRF_ASSERT(bufHeader->length > 0); - RRF_ASSERT(readPointer <= SpiCodeBufferSize); - - if (bufHeader->isPending) - { - if (gb.GetChannel().RawValue() == codeHeader->channel) - { -#ifdef TRACK_FILE_CODES - if (gb.GetChannel() == GCodeChannel::File && gb.GetCommandLetter() != 'Q') - { - fileMacrosRunning -= fileMacrosClosing; - fileMacrosClosing = 0; - if (fileCodesRead > fileCodesHandled + fileMacrosRunning) - { - // Note that we cannot use MessageF here because the task scheduler is suspended - OutputBuffer *buf; - if (OutputBuffer::Allocate(buf)) - { - String<SHORT_GCODE_LENGTH> codeString; - gb.PrintCommand(codeString.GetRef()); - buf->printf("Code %s did not return a code result, delta %d, running macros %d\n", codeString.c_str(), fileCodesRead - fileCodesHandled - fileMacrosRunning, fileMacrosRunning); - gcodeReply.Push(buf, WarningMessage); - } - fileCodesRead = fileCodesHandled - fileMacrosRunning; - } - fileCodesRead++; - } -#endif - - // Process the next binary G-code - gb.PutBinary(reinterpret_cast<const uint32_t *>(codeHeader), bufHeader->length / sizeof(uint32_t)); - bufHeader->isPending = false; - - // Check if we can reset the ring buffer pointers - if (updateRxPointer) - { - sendBufferUpdate = true; - if (readPointer == txPointer && txEnd == 0) - { - // Buffer completely read, reset RX/TX pointers - rxPointer = txPointer = 0; - } - else if (readPointer == txEnd) - { - // Read last code before overlapping, restart from the beginning - rxPointer = txEnd = 0; - } - else - { - // Code has been read, move on to the next one - rxPointer = readPointer; - } - } - - gotCommand = true; - break; - } - updateRxPointer = false; - } - - if (readPointer == txEnd) - { - if (updateRxPointer) - { - // Skipped non-pending codes, restart from the beginning - rxPointer = txEnd = 0; - } - - // About to overlap, continue from the start - readPointer = 0; - } - } while (readPointer != txPointer); - } - } - - if (gotCommand) - { - gb.DecodeCommand(); - return true; - } - return false; -} - -bool LinuxInterface::FileExists(const char *filename) noexcept -{ - // Don't do anything if the SBC is not connected - if (!IsConnected()) - { - return false; - } - - // Set up the request content - MutexLocker locker(fileMutex); - filePath = filename; - fileOperation = FileOperation::checkFileExists; - fileOperationPending = true; - - // Let the SBC task process this request as quickly as possible - if (delaying) - { - delaying = false; - sbcTask->Give(); - } - fileSemaphore.Take(); - - // Return the result - return fileSuccess; -} - -bool LinuxInterface::DeleteFileOrDirectory(const char *fileOrDirectory) noexcept -{ - // Don't do anything if the SBC is not connected - if (!IsConnected()) - { - return false; - } - - // Set up the request content - MutexLocker locker(fileMutex); - filePath = fileOrDirectory; - fileOperation = FileOperation::deleteFileOrDirectory; - fileOperationPending = true; - - // Let the SBC task process this request as quickly as possible - if (delaying) - { - delaying = false; - sbcTask->Give(); - } - fileSemaphore.Take(); - - // Return the result - return fileSuccess; -} - -FileHandle LinuxInterface::OpenFile(const char *filename, OpenMode mode, FilePosition& fileLength, uint32_t preAllocSize) noexcept -{ - // Don't do anything if the SBC is not connected - if (!IsConnected()) - { - return false; - } - - // Set up the request content - MutexLocker locker(fileMutex); - filePath = filename; - filePreAllocSize = preAllocSize; - switch (mode) - { - case OpenMode::read: - fileOperation = FileOperation::openRead; - break; - - case OpenMode::write: - case OpenMode::writeWithCrc: - fileOperation = FileOperation::openWrite; - break; - - case OpenMode::append: - fileOperation = FileOperation::openAppend; - break; - - default: - filePath = nullptr; - REPORT_INTERNAL_ERROR; - break; - } - fileOperationPending = true; - - // Let the SBC task process this request as quickly as possible - if (delaying) - { - delaying = false; - sbcTask->Give(); - } - fileSemaphore.Take(); - - // Update the file length and return the handle - fileLength = fileOffset; - return fileHandle; -} - -int LinuxInterface::ReadFile(FileHandle handle, char *buffer, size_t bufferLength) noexcept -{ - // Don't do anything if the SBC is not connected - if (!IsConnected()) - { - return false; - } - - // Set up the request content - MutexLocker locker(fileMutex); - fileHandle = handle; - fileReadBuffer = buffer; - fileBufferLength = bufferLength; - fileOperation = FileOperation::read; - fileOperationPending = true; - - // Let the SBC task process this request as quickly as possible - if (delaying) - { - delaying = false; - sbcTask->Give(); - } - fileSemaphore.Take(); -; - - // Return the number of bytes read - return fileSuccess ? (int)fileOffset : -1; -} - -bool LinuxInterface::WriteFile(FileHandle handle, const char *buffer, size_t bufferLength) noexcept -{ - // Don't do anything if the SBC is not connected - if (!IsConnected()) - { - return false; - } - - // Set up the request content - MutexLocker locker(fileMutex); - fileHandle = handle; - fileWriteBuffer = buffer; - fileBufferLength = bufferLength; - fileOperation = FileOperation::write; - fileOperationPending = true; - - // Let the SBC task process this request as quickly as possible - if (delaying) - { - delaying = false; - sbcTask->Give(); - } - fileSemaphore.Take(); - - // Return the result - return fileSuccess; -} - -bool LinuxInterface::SeekFile(FileHandle handle, FilePosition offset) noexcept -{ - // Don't do anything if the SBC is not connected - if (!IsConnected()) - { - return false; - } - - // Set up the request content - MutexLocker locker(fileMutex); - fileHandle = handle; - fileOffset = offset; - fileOperation = FileOperation::seek; - fileOperationPending = true; - - // Let the SBC task process this request as quickly as possible - if (delaying) - { - delaying = false; - sbcTask->Give(); - } - fileSemaphore.Take(); - - // Return the result - return fileSuccess; -} - -bool LinuxInterface::TruncateFile(FileHandle handle) noexcept -{ - // Don't do anything if the SBC is not connected - if (!IsConnected()) - { - return false; - } - - // Set up the request content - MutexLocker locker(fileMutex); - fileHandle = handle; - fileOperation = FileOperation::truncate; - fileOperationPending = true; - - // Let the SBC task process this request as quickly as possible - if (delaying) - { - delaying = false; - sbcTask->Give(); - } - fileSemaphore.Take(); - - // Return the result - return fileSuccess; -} - -void LinuxInterface::CloseFile(FileHandle handle) noexcept -{ - // Don't do anything if the SBC is not connected - if (!IsConnected()) - { - return; - } - - // Set up the request content - MutexLocker locker(fileMutex); - fileHandle = handle; - fileOperation = FileOperation::close; - fileOperationPending = true; - - // Let the SBC task process this request as quickly as possible - if (delaying) - { - delaying = false; - sbcTask->Give(); - } - fileSemaphore.Take(); -} - -void LinuxInterface::HandleGCodeReply(MessageType mt, const char *reply) noexcept -{ - if (!IsConnected()) - { - return; - } - -#ifdef TRACK_FILE_CODES - if ((mt & (1 << GCodeChannel::File)) != 0) - { - fileCodesHandled++; - } -#endif - - MutexLocker lock(gcodeReplyMutex); - OutputBuffer *buffer = gcodeReply.GetLastItem(); - if (buffer != nullptr && mt == gcodeReply.GetLastItemType() && (mt & PushFlag) != 0 && !buffer->IsReferenced()) - { - // Try to save some space by combining segments that have the Push flag set - buffer->cat(reply); - } - else if (reply[0] != 0 && OutputBuffer::Allocate(buffer)) - { - // Attempt to allocate one G-code buffer per non-empty output message - buffer->cat(reply); - gcodeReply.Push(buffer, mt); - } - else - { - // Store nullptr to indicate an empty response. This way many OutputBuffer references can be saved - gcodeReply.Push(nullptr, mt); - } - EventOccurred(); -} - -void LinuxInterface::HandleGCodeReply(MessageType mt, OutputBuffer *buffer) noexcept -{ - if (!IsConnected()) - { - OutputBuffer::ReleaseAll(buffer); - return; - } - -#ifdef TRACK_FILE_CODES - if ((mt & (1 << GCodeChannel::File)) != 0) - { - fileCodesHandled++; - } -#endif - - MutexLocker lock(gcodeReplyMutex); - gcodeReply.Push(buffer, mt); - EventOccurred(); -} - -// Read a file chunk from the SBC. When a response has been received, the current task is woken up again. -// It changes bufferLength to the number of received bytes -// This method returns true on success and false if an error occurred (e.g. file not found) -bool LinuxInterface::GetFileChunk(const char *filename, uint32_t offset, char *buffer, uint32_t& bufferLength, uint32_t& fileLength) noexcept -{ - if (waitingForFileChunk) - { - reprap.GetPlatform().Message(ErrorMessage, "Trying to request a file chunk from two independent tasks\n"); - bufferLength = fileLength = 0; - return false; - } - - fileChunkRequestSent = false; - requestedFileName.copy(filename); - requestedFileLength = bufferLength; - requestedFileOffset = offset; - requestedFileBuffer = buffer; - - waitingForFileChunk = true; - requestedFileSemaphore.Take(); - - waitingForFileChunk = false; - if (requestedFileDataLength < 0) - { - bufferLength = fileLength = 0; - return false; - } - bufferLength = requestedFileDataLength; - fileLength = requestedFileLength; - return true; -} - -void LinuxInterface::EventOccurred(bool timeCritical) noexcept -{ - if (!IsConnected()) - { - return; - } - - // Increment the number of events - if (timeCritical) - { - numEvents = numMaxEvents; - } - else - { - numEvents++; - } - - // Stop delaying if the next transfer is time-critical - if (delaying && numEvents >= numMaxEvents) - { - delaying = false; - sbcTask->Give(); - } -} - -void LinuxInterface::InvalidateBufferedCodes(GCodeChannel channel) noexcept -{ - TaskCriticalSectionLocker locker; - if (rxPointer != txPointer || txEnd != 0) - { - bool updateRxPointer = true; - uint16_t readPointer = rxPointer; - do - { - BufferedCodeHeader *bufHeader = reinterpret_cast<BufferedCodeHeader *>(codeBuffer + readPointer); - if (bufHeader->isPending) - { - const CodeHeader *codeHeader = reinterpret_cast<const CodeHeader*>(codeBuffer + readPointer + sizeof(BufferedCodeHeader)); - if (codeHeader->channel == channel.RawValue()) - { - bufHeader->isPending = false; - } - else - { - updateRxPointer = false; - } - } - readPointer += sizeof(BufferedCodeHeader) + bufHeader->length; - - if (updateRxPointer) - { - sendBufferUpdate = true; - if (readPointer == txPointer && txEnd == 0) - { - // Buffer is empty again, reset the pointers - rxPointer = txPointer = 0; - break; - } - else if (readPointer == txEnd) - { - // Invalidated last code before overlapping, continue from the beginning - readPointer = 0; - rxPointer = txEnd = 0; - } - else - { - // Invalidated next code - rxPointer = readPointer; - } - } - else if (readPointer == txEnd) - { - // About to overlap, continue from the start - readPointer = 0; - } - } while (readPointer != txPointer); - } -} - -#endif diff --git a/src/Movement/BedProbing/Grid.cpp b/src/Movement/BedProbing/Grid.cpp index b94b5744..45b81a92 100644 --- a/src/Movement/BedProbing/Grid.cpp +++ b/src/Movement/BedProbing/Grid.cpp @@ -527,7 +527,7 @@ bool HeightMap::LoadFromFile(FileStore *f, const char *fname, const StringRef& r #endif -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE // Update the filename void HeightMap::SetFileName(const char *name) noexcept diff --git a/src/Movement/BedProbing/Grid.h b/src/Movement/BedProbing/Grid.h index aa4436c0..0bcafb16 100644 --- a/src/Movement/BedProbing/Grid.h +++ b/src/Movement/BedProbing/Grid.h @@ -87,11 +87,11 @@ public: bool LoadFromFile(FileStore *f, const char *fname, const StringRef& r) noexcept; // Load the grid from file returning true if an error occurred #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE const char *GetFileName() const noexcept { return fileName.c_str(); } #endif -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE void SetFileName(const char *name) noexcept; // Update the filename void SaveToArray(float *array, float zOffset) const noexcept // Save the grid Z coordinates to an array pre(IsValid()); @@ -112,7 +112,7 @@ private: GridDefinition def; float gridHeights[MaxGridProbePoints]; // The Z coordinates of the points on the bed that were probed LargeBitmap<MaxGridProbePoints> gridHeightSet; // Bitmap of which heights are set -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE String<MaxFilenameLength> fileName; // The name of the file that this height map was loaded from or saved to #endif bool useMap; // True to do bed compensation diff --git a/src/Movement/Kinematics/HangprinterKinematics.cpp b/src/Movement/Kinematics/HangprinterKinematics.cpp index ae211220..1c05fc27 100644 --- a/src/Movement/Kinematics/HangprinterKinematics.cpp +++ b/src/Movement/Kinematics/HangprinterKinematics.cpp @@ -437,7 +437,7 @@ AxesBitmap HangprinterKinematics::MustBeHomedAxes(AxesBitmap axesMoving, bool di return axesMoving; } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE // Write the parameters to a file, returning true if success bool HangprinterKinematics::WriteCalibrationParameters(FileStore *f) const noexcept diff --git a/src/Movement/Kinematics/HangprinterKinematics.h b/src/Movement/Kinematics/HangprinterKinematics.h index 1a9587a9..751d39f9 100644 --- a/src/Movement/Kinematics/HangprinterKinematics.h +++ b/src/Movement/Kinematics/HangprinterKinematics.h @@ -24,7 +24,7 @@ public: bool SupportsAutoCalibration() const noexcept override { return true; } bool IsReachable(float axesCoords[MaxAxes], AxesBitmap axes) const noexcept override; void SetCalibrationDefaults() noexcept override { Init(); } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool WriteCalibrationParameters(FileStore *f) const noexcept override; #endif LimitPositionResult LimitPosition(float finalCoords[], const float * null initialCoords, size_t numAxes, AxesBitmap axesToLimit, bool isCoordinated, bool applyM208Limits) const noexcept override; @@ -37,7 +37,7 @@ public: AxesBitmap GetHomingFileName(AxesBitmap toBeHomed, AxesBitmap alreadyHomed, size_t numVisibleAxes, const StringRef& filename) const noexcept override; bool QueryTerminateHomingMove(size_t axis) const noexcept override; void OnHomingSwitchTriggered(size_t axis, bool highEnd, const float stepsPerMm[], DDA& dda) const noexcept override; -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool WriteResumeSettings(FileStore *f) const noexcept override; #endif #if DUAL_CAN diff --git a/src/Movement/Kinematics/Kinematics.h b/src/Movement/Kinematics/Kinematics.h index 5ef95b11..7f587662 100644 --- a/src/Movement/Kinematics/Kinematics.h +++ b/src/Movement/Kinematics/Kinematics.h @@ -124,7 +124,7 @@ public: // Do nothing if auto calibration is not supported. virtual void SetCalibrationDefaults() noexcept { } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE // Write the parameters that are set by auto calibration to the config-override.g file, returning true if success // Just return true if auto calibration is not supported. virtual bool WriteCalibrationParameters(FileStore *f) const noexcept { return true; } @@ -186,7 +186,7 @@ public: // This default is good for Cartesian and Core printers, but not deltas or SCARA virtual AxesBitmap MustBeHomedAxes(AxesBitmap axesMoving, bool disallowMovesBeforeHoming) const noexcept { return (disallowMovesBeforeHoming) ? axesMoving : AxesBitmap(); } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE // Write any calibration data that we need to resume a print after power fail, returning true if successful. Override where necessary. virtual bool WriteResumeSettings(FileStore *f) const noexcept { return true; } #endif diff --git a/src/Movement/Kinematics/LinearDeltaKinematics.cpp b/src/Movement/Kinematics/LinearDeltaKinematics.cpp index e504f31e..13f951a5 100644 --- a/src/Movement/Kinematics/LinearDeltaKinematics.cpp +++ b/src/Movement/Kinematics/LinearDeltaKinematics.cpp @@ -785,7 +785,7 @@ void LinearDeltaKinematics::PrintParameters(const StringRef& reply) const noexce (double)(xTilt * 100.0), (double)(yTilt * 100.0)); } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE // Write the parameters that are set by auto calibration to a file, returning true if success bool LinearDeltaKinematics::WriteCalibrationParameters(FileStore *f) const noexcept diff --git a/src/Movement/Kinematics/LinearDeltaKinematics.h b/src/Movement/Kinematics/LinearDeltaKinematics.h index d0e9cdcd..f00d63de 100644 --- a/src/Movement/Kinematics/LinearDeltaKinematics.h +++ b/src/Movement/Kinematics/LinearDeltaKinematics.h @@ -27,7 +27,7 @@ public: bool DoAutoCalibration(size_t numFactors, const RandomProbePointSet& probePoints, const StringRef& reply) noexcept override; void SetCalibrationDefaults() noexcept override { Init(); } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool WriteCalibrationParameters(FileStore *f) const noexcept override; #endif @@ -44,7 +44,7 @@ public: bool QueryTerminateHomingMove(size_t axis) const noexcept override; void OnHomingSwitchTriggered(size_t axis, bool highEnd, const float stepsPerMm[], DDA& dda) const noexcept override; -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool WriteResumeSettings(FileStore *f) const noexcept override; #endif diff --git a/src/Movement/Kinematics/RotaryDeltaKinematics.cpp b/src/Movement/Kinematics/RotaryDeltaKinematics.cpp index 595304a0..6ec33dc4 100644 --- a/src/Movement/Kinematics/RotaryDeltaKinematics.cpp +++ b/src/Movement/Kinematics/RotaryDeltaKinematics.cpp @@ -560,7 +560,7 @@ void RotaryDeltaKinematics::PrintParameters(const StringRef& reply) const noexce (double)angleCorrections[DELTA_A_AXIS], (double)angleCorrections[DELTA_B_AXIS], (double)angleCorrections[DELTA_C_AXIS]); } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE // Add a space, character, and 3-element vector to the string static void CatVector3(const StringRef& str, char c, const float vec[3]) noexcept diff --git a/src/Movement/Kinematics/RotaryDeltaKinematics.h b/src/Movement/Kinematics/RotaryDeltaKinematics.h index 807e301c..4b3de297 100644 --- a/src/Movement/Kinematics/RotaryDeltaKinematics.h +++ b/src/Movement/Kinematics/RotaryDeltaKinematics.h @@ -24,7 +24,7 @@ public: bool SupportsAutoCalibration() const noexcept override { return true; } bool DoAutoCalibration(size_t numFactors, const RandomProbePointSet& probePoints, const StringRef& reply) noexcept override; void SetCalibrationDefaults() noexcept override { Init(); } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool WriteCalibrationParameters(FileStore *f) const noexcept override; #endif LimitPositionResult LimitPosition(float finalCoords[], const float * null initialCoords, size_t numVisibleAxes, AxesBitmap axesToLimit, bool isCoordinated, bool applyM208Limits) const noexcept override; @@ -37,7 +37,7 @@ public: AxesBitmap GetHomingFileName(AxesBitmap toBeHomed, AxesBitmap alreadyHomed, size_t numVisibleAxes, const StringRef& filename) const noexcept override; bool QueryTerminateHomingMove(size_t axis) const noexcept override; void OnHomingSwitchTriggered(size_t axis, bool highEnd, const float stepsPerMm[], DDA& dda) const noexcept override; -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool WriteResumeSettings(FileStore *f) const noexcept override; #endif diff --git a/src/Movement/Kinematics/ZLeadscrewKinematics.cpp b/src/Movement/Kinematics/ZLeadscrewKinematics.cpp index 63c2201c..1d56972a 100644 --- a/src/Movement/Kinematics/ZLeadscrewKinematics.cpp +++ b/src/Movement/Kinematics/ZLeadscrewKinematics.cpp @@ -421,7 +421,7 @@ void ZLeadscrewKinematics::AppendCorrections(const floatc_t corrections[], const } } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE // Write any calibration data that we need to resume a print after power fail, returning true if successful bool ZLeadscrewKinematics::WriteResumeSettings(FileStore *f) const noexcept diff --git a/src/Movement/Kinematics/ZLeadscrewKinematics.h b/src/Movement/Kinematics/ZLeadscrewKinematics.h index 75d2a489..4864204b 100644 --- a/src/Movement/Kinematics/ZLeadscrewKinematics.h +++ b/src/Movement/Kinematics/ZLeadscrewKinematics.h @@ -20,7 +20,7 @@ public: bool Configure(unsigned int mCode, GCodeBuffer& gb, const StringRef& reply, bool& error) THROWS(GCodeException) override; bool SupportsAutoCalibration() const noexcept override; bool DoAutoCalibration(size_t numFactors, const RandomProbePointSet& probePoints, const StringRef& reply) noexcept override; -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool WriteResumeSettings(FileStore *f) const noexcept override; #endif diff --git a/src/Movement/Move.cpp b/src/Movement/Move.cpp index e5645c72..04781a55 100644 --- a/src/Movement/Move.cpp +++ b/src/Movement/Move.cpp @@ -144,7 +144,7 @@ constexpr ObjectModelTableEntry Move::objectModelTable[] = // 6. move.compensation members { "fadeHeight", OBJECT_MODEL_FUNC((self->useTaper) ? self->taperHeight : std::numeric_limits<float>::quiet_NaN(), 1), ObjectModelEntryFlags::none }, -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE { "file", OBJECT_MODEL_FUNC_IF(self->usingMesh, self->heightMap.GetFileName()), ObjectModelEntryFlags::none }, #endif { "liveGrid", OBJECT_MODEL_FUNC_IF(self->usingMesh, (const GridDefinition *)&self->GetGrid()), ObjectModelEntryFlags::none }, @@ -179,7 +179,7 @@ constexpr uint8_t Move::objectModelTableDescriptor[] = 3, 2, 2, - 6 + (HAS_MASS_STORAGE || HAS_LINUX_INTERFACE), + 6 + (HAS_MASS_STORAGE || HAS_SBC_INTERFACE), 2, 4, #if SUPPORT_COORDINATE_ROTATION @@ -773,7 +773,7 @@ bool Move::SaveHeightMapToFile(FileStore *f, const char *fname) noexcept #endif -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE // Save the height map Z coordinates to an array void Move::SaveHeightMapToArray(float *arr) const noexcept @@ -980,7 +980,7 @@ void Move::SetIdleTimeout(float timeout) noexcept reprap.MoveUpdated(); } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE // Write settings for resuming the print // The GCodes module deals with the head position so all we need worry about is the bed compensation diff --git a/src/Movement/Move.h b/src/Movement/Move.h index ce67c023..239e8ea6 100644 --- a/src/Movement/Move.h +++ b/src/Movement/Move.h @@ -152,7 +152,7 @@ public: bool SaveHeightMapToFile(FileStore *f, const char *fname) noexcept; // Save the height map to a file returning true if an error occurred #endif -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE void SaveHeightMapToArray(float *arr) const noexcept; // Save the height map Z coordinates to an array #endif @@ -168,7 +168,7 @@ public: int32_t GetAccumulatedExtrusion(size_t drive, bool& isPrinting) noexcept; // Return and reset the accumulated commanded extrusion amount -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool WriteResumeSettings(FileStore *f) const noexcept; // Write settings for resuming the print #endif diff --git a/src/ObjectModel/ObjectModel.cpp b/src/ObjectModel/ObjectModel.cpp index a8a42ff4..165431e4 100644 --- a/src/ObjectModel/ObjectModel.cpp +++ b/src/ObjectModel/ObjectModel.cpp @@ -747,7 +747,7 @@ void ObjectModel::ReportItemAsJsonFull(OutputBuffer *buf, ObjectExplorationConte break; case TypeCode::Special: -#if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES || HAS_SBC_INTERFACE switch ((ExpressionValue::SpecialType)val.param) { case ExpressionValue::SpecialType::sysDir: @@ -169,8 +169,8 @@ # define SUPPORT_TELNET HAS_NETWORKING #endif -#ifndef HAS_LINUX_INTERFACE -# define HAS_LINUX_INTERFACE 0 +#ifndef HAS_SBC_INTERFACE +# define HAS_SBC_INTERFACE 0 #endif #ifndef HAS_MASS_STORAGE @@ -181,7 +181,7 @@ # define HAS_EMBEDDED_FILES 0 #endif -#if !HAS_MASS_STORAGE && !HAS_LINUX_INTERFACE +#if !HAS_MASS_STORAGE && !HAS_SBC_INTERFACE # if SUPPORT_12864_LCD # error "12864 LCD support requires mass storage or SBC interface" # endif diff --git a/src/Platform/MessageType.h b/src/Platform/MessageType.h index d1062542..4823dbb7 100644 --- a/src/Platform/MessageType.h +++ b/src/Platform/MessageType.h @@ -10,7 +10,7 @@ #include <cstdint> -// Supported message destinations. This is now a bitmap. Note that this type is used by the Linux service as well +// Supported message destinations. This is now a bitmap. Note that this type is used by the SBC service as well enum MessageType : uint32_t { // Destinations (bytes 1-2) diff --git a/src/Platform/OutputMemory.cpp b/src/Platform/OutputMemory.cpp index 39ffda41..801427a5 100644 --- a/src/Platform/OutputMemory.cpp +++ b/src/Platform/OutputMemory.cpp @@ -540,7 +540,7 @@ MessageType OutputStack::GetFirstItemType() const volatile noexcept return (count == 0) ? MessageType::NoDestinationMessage : types[0]; } -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE // Update the first item of the stack void OutputStack::SetFirstItem(OutputBuffer *buffer) volatile noexcept diff --git a/src/Platform/OutputMemory.h b/src/Platform/OutputMemory.h index 3b15855c..b86bb84f 100644 --- a/src/Platform/OutputMemory.h +++ b/src/Platform/OutputMemory.h @@ -11,7 +11,7 @@ #include <RepRapFirmware.h> #include <Storage/FileData.h> -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE const size_t OUTPUT_STACK_DEPTH = 64; // Number of OutputBuffer chains that can be pushed onto one stack instance #else const size_t OUTPUT_STACK_DEPTH = 4; // Number of OutputBuffer chains that can be pushed onto one stack instance @@ -144,7 +144,7 @@ public: // Returns the first item's type from the stack or NoDestinationMessage if none is available MessageType GetFirstItemType() const volatile noexcept; -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE // Set the first item of the stack. If it's NULL, then the first item will be removed void SetFirstItem(OutputBuffer *buffer) volatile noexcept; #endif diff --git a/src/Platform/Platform.cpp b/src/Platform/Platform.cpp index 5be4b3c9..be34c04a 100644 --- a/src/Platform/Platform.cpp +++ b/src/Platform/Platform.cpp @@ -86,9 +86,9 @@ using AnalogIn::AdcBits; // for compatibility with CoreNG, which doesn't have # include "PortControl.h" #endif -#if HAS_LINUX_INTERFACE -# include "Linux/LinuxInterface.h" -# include "Linux/DataTransfer.h" +#if HAS_SBC_INTERFACE +# include "SBC/SbcInterface.h" +# include "SBC/DataTransfer.h" #endif #if HAS_NETWORKING @@ -227,7 +227,7 @@ constexpr ObjectModelTableEntry Platform::objectModelTable[] = { "firmwareFileName", OBJECT_MODEL_FUNC_NOSELF(IAP_FIRMWARE_FILE), ObjectModelEntryFlags::none }, { "firmwareName", OBJECT_MODEL_FUNC_NOSELF(FIRMWARE_NAME), ObjectModelEntryFlags::none }, { "firmwareVersion", OBJECT_MODEL_FUNC_NOSELF(VERSION), ObjectModelEntryFlags::none }, -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE { "iapFileNameSBC", OBJECT_MODEL_FUNC_NOSELF(IAP_UPDATE_FILE_SBC), ObjectModelEntryFlags::none }, #endif #if HAS_MASS_STORAGE @@ -342,7 +342,7 @@ constexpr ObjectModelTableEntry Platform::objectModelTable[] = constexpr uint8_t Platform::objectModelTableDescriptor[] = { 10, // number of sections - 9 + SUPPORT_ACCELEROMETERS + HAS_LINUX_INTERFACE + HAS_MASS_STORAGE + HAS_VOLTAGE_MONITOR + HAS_12V_MONITOR + HAS_CPU_TEMP_SENSOR + SUPPORT_CAN_EXPANSION + SUPPORT_12864_LCD + MCU_HAS_UNIQUE_ID, // section 0: boards[0] + 9 + SUPPORT_ACCELEROMETERS + HAS_SBC_INTERFACE + HAS_MASS_STORAGE + HAS_VOLTAGE_MONITOR + HAS_12V_MONITOR + HAS_CPU_TEMP_SENSOR + SUPPORT_CAN_EXPANSION + SUPPORT_12864_LCD + MCU_HAS_UNIQUE_ID, // section 0: boards[0] #if HAS_CPU_TEMP_SENSOR 3, // section 1: mcuTemp #else @@ -413,7 +413,7 @@ Platform::Platform() noexcept : #if HAS_AUX_DEVICES panelDueUpdater(nullptr), #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES sysDir(nullptr), #endif tickState(0), debugCode(0), @@ -500,7 +500,7 @@ void Platform::Init() noexcept pinMode(SdCardDetectPins[i], INPUT_PULLUP); } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES MassStorage::Init(); #endif @@ -1022,7 +1022,7 @@ void Platform::Spin() noexcept #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES MassStorage::Spin(); #endif @@ -1472,8 +1472,8 @@ bool Platform::IsPowerOk() const noexcept { // FIXME Implement auto-save for the SBC return ( !autoSaveEnabled -#if HAS_LINUX_INTERFACE - || reprap.UsingLinuxInterface() +#if HAS_SBC_INTERFACE + || reprap.UsingSbcInterface() #endif ) || currentVin > autoPauseReading; @@ -2254,17 +2254,17 @@ GCodeResult Platform::DiagnosticTest(GCodeBuffer& gb, const StringRef& reply, Ou case (unsigned int)DiagnosticTestType::PrintObjectAddresses: MessageF(MessageType::GenericMessage, "Platform %08" PRIx32 "-%08" PRIx32 -#if HAS_LINUX_INTERFACE - "\nLinuxInterface %08" PRIx32 "-%08" PRIx32 +#if HAS_SBC_INTERFACE + "\nSbcInterface %08" PRIx32 "-%08" PRIx32 #endif "\nNetwork %08" PRIx32 "-%08" PRIx32 "\nGCodes %08" PRIx32 "-%08" PRIx32 "\nMove %08" PRIx32 "-%08" PRIx32 "\nHeat %08" PRIx32 "-%08" PRIx32 , reinterpret_cast<uint32_t>(this), reinterpret_cast<uint32_t>(this) + sizeof(Platform) - 1 -#if HAS_LINUX_INTERFACE - , reinterpret_cast<uint32_t>(&reprap.GetLinuxInterface()) - , (reinterpret_cast<uint32_t>(&reprap.GetLinuxInterface()) == 0) ? 0 : reinterpret_cast<uint32_t>(&reprap.GetLinuxInterface()) + sizeof(LinuxInterface) +#if HAS_SBC_INTERFACE + , reinterpret_cast<uint32_t>(&reprap.GetSbcInterface()) + , (reinterpret_cast<uint32_t>(&reprap.GetSbcInterface()) == 0) ? 0 : reinterpret_cast<uint32_t>(&reprap.GetSbcInterface()) + sizeof(SbcInterface) #endif , reinterpret_cast<uint32_t>(&reprap.GetNetwork()), reinterpret_cast<uint32_t>(&reprap.GetNetwork()) + sizeof(Network) - 1 , reinterpret_cast<uint32_t>(&reprap.GetGCodes()), reinterpret_cast<uint32_t>(&reprap.GetGCodes()) + sizeof(GCodes) - 1 @@ -2443,7 +2443,7 @@ int Platform::GetAveragingFilterIndex(const IoPort& port) const noexcept return -1; } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE // Write the platform parameters to file bool Platform::WritePlatformParameters(FileStore *f, bool includingG31) const noexcept @@ -3367,8 +3367,8 @@ void Platform::Message(const MessageType type, OutputBuffer *buffer) noexcept { ++numDestinations; } -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface() && ((type & GenericMessage) == GenericMessage || (type & BinaryCodeReplyFlag) != 0)) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface() && ((type & GenericMessage) == GenericMessage || (type & BinaryCodeReplyFlag) != 0)) { ++numDestinations; } @@ -3413,10 +3413,10 @@ void Platform::Message(const MessageType type, OutputBuffer *buffer) noexcept AppendUsbReply(buffer); } -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface() && ((type & GenericMessage) == GenericMessage || (type & BinaryCodeReplyFlag) != 0)) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface() && ((type & GenericMessage) == GenericMessage || (type & BinaryCodeReplyFlag) != 0)) { - reprap.GetLinuxInterface().HandleGCodeReply(type, buffer); + reprap.GetSbcInterface().HandleGCodeReply(type, buffer); } #endif } @@ -3425,11 +3425,11 @@ void Platform::Message(const MessageType type, OutputBuffer *buffer) noexcept void Platform::MessageF(MessageType type, const char *fmt, va_list vargs) noexcept { String<FormatStringLength> formatString; -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface() && ((type & GenericMessage) == GenericMessage || (type & BinaryCodeReplyFlag) != 0)) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface() && ((type & GenericMessage) == GenericMessage || (type & BinaryCodeReplyFlag) != 0)) { formatString.vprintf(fmt, vargs); - reprap.GetLinuxInterface().HandleGCodeReply(type, formatString.c_str()); + reprap.GetSbcInterface().HandleGCodeReply(type, formatString.c_str()); if ((type & BinaryCodeReplyFlag) != 0) { return; @@ -3465,11 +3465,11 @@ void Platform::MessageF(MessageType type, const char *fmt, ...) noexcept void Platform::Message(MessageType type, const char *message) noexcept { -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface() && +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface() && ((type & BinaryCodeReplyFlag) != 0 || (type & GenericMessage) == GenericMessage || (type & LogOff) != LogOff)) { - reprap.GetLinuxInterface().HandleGCodeReply(type, message); + reprap.GetSbcInterface().HandleGCodeReply(type, message); if ((type & BinaryCodeReplyFlag) != 0) { return; @@ -3979,7 +3979,7 @@ bool Platform::IsDuetWiFi() const noexcept #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool Platform::Delete(const char* folder, const char *filename) const noexcept { @@ -3995,7 +3995,7 @@ bool Platform::DeleteSysFile(const char *filename) const noexcept #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES // Open a file FileStore* Platform::OpenFile(const char* folder, const char* fileName, OpenMode mode, uint32_t preAllocSize) const noexcept diff --git a/src/Platform/Platform.h b/src/Platform/Platform.h index b6383a8b..a2246047 100644 --- a/src/Platform/Platform.h +++ b/src/Platform/Platform.h @@ -398,10 +398,10 @@ public: #endif // File functions -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES FileStore* OpenFile(const char* folder, const char* fileName, OpenMode mode, uint32_t preAllocSize = 0) const noexcept; bool FileExists(const char* folder, const char *filename) const noexcept; -# if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +# if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool Delete(const char* folder, const char *filename) const noexcept; #endif @@ -413,7 +413,7 @@ public: GCodeResult SetSysDir(const char* dir, const StringRef& reply) noexcept; // Set the system files path bool SysFileExists(const char *filename) const noexcept; FileStore* OpenSysFile(const char *filename, OpenMode mode) const noexcept; -# if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +# if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool DeleteSysFile(const char *filename) const noexcept; # endif bool MakeSysFileName(const StringRef& result, const char *filename) const noexcept; @@ -522,7 +522,7 @@ public: const volatile ZProbeAveragingFilter& GetZProbeOnFilter() const noexcept { return zProbeOnFilter; } const volatile ZProbeAveragingFilter& GetZProbeOffFilter() const noexcept{ return zProbeOffFilter; } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool WritePlatformParameters(FileStore *f, bool includingG31) const noexcept; #endif @@ -799,7 +799,7 @@ private: float axisMinima[MaxAxes]; AxesBitmap axisMinimaProbed, axisMaximaProbed; -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE static bool WriteAxisLimits(FileStore *f, AxesBitmap axesProbed, const float limits[MaxAxes], int sParam) noexcept; #endif @@ -819,7 +819,7 @@ private: #endif // Files -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES const char *sysDir; mutable ReadWriteLock sysDirLock; #endif @@ -891,7 +891,7 @@ private: static bool deliberateError; // true if we deliberately caused an exception for testing purposes. Must be static in case of exception during startup. }; -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES // Where the htm etc files are inline const char* Platform::GetWebDir() const noexcept diff --git a/src/Platform/RepRap.cpp b/src/Platform/RepRap.cpp index 8761ac03..57bfca22 100644 --- a/src/Platform/RepRap.cpp +++ b/src/Platform/RepRap.cpp @@ -46,8 +46,8 @@ # include "Display/Display.h" #endif -#if HAS_LINUX_INTERFACE -# include "Linux/LinuxInterface.h" +#if HAS_SBC_INTERFACE +# include "SBC/SbcInterface.h" #endif #ifdef DUET3_ATE @@ -249,7 +249,7 @@ constexpr ObjectModelTableEntry RepRap::objectModelTable[] = // Within each group, these entries must be in alphabetical order // 0. MachineModel root { "boards", OBJECT_MODEL_FUNC_NOSELF(&boardsArrayDescriptor), ObjectModelEntryFlags::live }, -#if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES || HAS_SBC_INTERFACE { "directories", OBJECT_MODEL_FUNC(self, 1), ObjectModelEntryFlags::none }, #endif { "fans", OBJECT_MODEL_FUNC_NOSELF(&fansArrayDescriptor), ObjectModelEntryFlags::live }, @@ -272,7 +272,7 @@ constexpr ObjectModelTableEntry RepRap::objectModelTable[] = { "volumes", OBJECT_MODEL_FUNC_NOSELF(&volumesArrayDescriptor), ObjectModelEntryFlags::none }, // 1. MachineModel.directories -#if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES || HAS_SBC_INTERFACE { "filaments", OBJECT_MODEL_FUNC_NOSELF(FILAMENTS_DIRECTORY), ObjectModelEntryFlags::verbose }, { "firmware", OBJECT_MODEL_FUNC_NOSELF(FIRMWARE_DIRECTORY), ObjectModelEntryFlags::verbose }, { "gCodes", OBJECT_MODEL_FUNC(self->platform->GetGCodeDir()), ObjectModelEntryFlags::verbose }, @@ -367,7 +367,7 @@ constexpr ObjectModelTableEntry RepRap::objectModelTable[] = // 6. MachineModel.seqs { "boards", OBJECT_MODEL_FUNC((int32_t)self->boardsSeq), ObjectModelEntryFlags::live }, -#if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES || HAS_SBC_INTERFACE { "directories", OBJECT_MODEL_FUNC((int32_t)self->directoriesSeq), ObjectModelEntryFlags::live }, #endif { "fans", OBJECT_MODEL_FUNC((int32_t)self->fansSeq), ObjectModelEntryFlags::live }, @@ -398,8 +398,8 @@ constexpr ObjectModelTableEntry RepRap::objectModelTable[] = constexpr uint8_t RepRap::objectModelTableDescriptor[] = { 7, // number of sub-tables - 15 + SUPPORT_SCANNER + (HAS_MASS_STORAGE | HAS_EMBEDDED_FILES | HAS_LINUX_INTERFACE), // root -#if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES || HAS_LINUX_INTERFACE + 15 + SUPPORT_SCANNER + (HAS_MASS_STORAGE | HAS_EMBEDDED_FILES | HAS_SBC_INTERFACE), // root +#if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES || HAS_SBC_INTERFACE 8, // directories #else 0, // directories @@ -409,7 +409,7 @@ constexpr uint8_t RepRap::objectModelTableDescriptor[] = 2, // state.beep 6, // state.messageBox 12 + HAS_NETWORKING + SUPPORT_SCANNER + - 2 * HAS_MASS_STORAGE + (HAS_MASS_STORAGE | HAS_EMBEDDED_FILES | HAS_LINUX_INTERFACE) // seqs + 2 * HAS_MASS_STORAGE + (HAS_MASS_STORAGE | HAS_EMBEDDED_FILES | HAS_SBC_INTERFACE) // seqs }; DEFINE_GET_OBJECT_MODEL_TABLE(RepRap) @@ -432,8 +432,8 @@ RepRap::RepRap() noexcept previousToolNumber(-1), diagnosticsDestination(MessageType::NoDestinationMessage), justSentDiagnostics(false), spinningModule(noModule), stopped(false), active(false), processingConfig(true) -#if HAS_LINUX_INTERFACE - , usingLinuxInterface(false) // default to not using the SBC interface until we have checked for config.g on an SD card, +#if HAS_SBC_INTERFACE + , usingSbcInterface(false) // default to not using the SBC interface until we have checked for config.g on an SD card, // because a disconnected SBC interface can generate noise which may trigger interrupts and DMA #endif { @@ -473,8 +473,8 @@ void RepRap::Init() noexcept { OutputBuffer::Init(); platform = new Platform(); -#if HAS_LINUX_INTERFACE - linuxInterface = new LinuxInterface(); // needs to be allocated early on Duet 2 so as to avoid using any of the last 64K of RAM +#if HAS_SBC_INTERFACE + sbcInterface = new SbcInterface(); // needs to be allocated early on Duet 2 so as to avoid using any of the last 64K of RAM #endif network = new Network(*platform); gCodes = new GCodes(*platform); @@ -535,7 +535,7 @@ void RepRap::Init() noexcept #ifdef DUET3_ATE Duet3Ate::Init(); #endif - // linuxInterface is not initialised until we know we are using it, to prevent a disconnected SBC interface generating interrupts and DMA + // sbcInterface is not initialised until we know we are using it, to prevent a disconnected SBC interface generating interrupts and DMA // Set up the timeout of the regular watchdog, and set up the backup watchdog if there is one. #if SAME5x @@ -585,9 +585,9 @@ void RepRap::Init() noexcept platform->MessageF(UsbMessage, "%s\n", VersionText); -#if HAS_LINUX_INTERFACE && !HAS_MASS_STORAGE - usingLinuxInterface = true; - linuxInterface->Init(); +#if HAS_SBC_INTERFACE && !HAS_MASS_STORAGE + usingSbcInterface = true; + sbcInterface->Init(); FileWriteBuffer::UsingSbcMode(); #endif @@ -611,10 +611,10 @@ void RepRap::Init() noexcept platform->Message(AddWarning(UsbMessage), "no configuration file found\n"); } } -# if HAS_LINUX_INTERFACE +# if HAS_SBC_INTERFACE else if (!MassStorage::IsCardDetected(0)) // if we failed to mount the SD card because there was no card in the slot { - usingLinuxInterface = true; + usingSbcInterface = true; FileWriteBuffer::UsingSbcMode(); } # endif @@ -623,17 +623,17 @@ void RepRap::Init() noexcept delay(3000); // Wait a few seconds so users have a chance to see this platform->MessageF(AddWarning(UsbMessage), "%s\n", reply.c_str()); } -# if HAS_LINUX_INTERFACE - linuxInterface->Init(); +# if HAS_SBC_INTERFACE + sbcInterface->Init(); # endif } #endif -#if HAS_LINUX_INTERFACE - if (usingLinuxInterface) +#if HAS_SBC_INTERFACE + if (usingSbcInterface) { // Keep spinning until the SBC connects - while (!linuxInterface->IsConnected()) + while (!sbcInterface->IsConnected()) { Spin(); } @@ -763,13 +763,13 @@ void RepRap::Spin() noexcept display->Spin(); #endif -#if HAS_LINUX_INTERFACE - // Keep the Linux task spinning from the main task in standalone mode to respond to a SBC if necessary - if (!UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + // Keep the SBC task spinning from the main task in standalone mode to respond to a SBC if necessary + if (!UsingSbcInterface()) { ticksInSpinState = 0; - spinningModule = moduleLinuxInterface; - linuxInterface->Spin(); + spinningModule = moduleSbcInterface; + sbcInterface->Spin(); } #endif @@ -874,7 +874,7 @@ void RepRap::Diagnostics(MessageType mtype) noexcept #ifdef __LPC17xx__ " at %uMhz" // clock speed #endif -#if HAS_LINUX_INTERFACE || SUPPORT_REMOTE_COMMANDS +#if HAS_SBC_INTERFACE || SUPPORT_REMOTE_COMMANDS " (%s mode)" // standalone, SBC or expansion mode #endif "\n", @@ -892,13 +892,13 @@ void RepRap::Diagnostics(MessageType mtype) noexcept #ifdef __LPC17xx__ , (unsigned int)(SystemCoreClock/1000000) #endif -#if HAS_LINUX_INTERFACE || SUPPORT_REMOTE_COMMANDS +#if HAS_SBC_INTERFACE || SUPPORT_REMOTE_COMMANDS , # if SUPPORT_REMOTE_COMMANDS (CanInterface::InExpansionMode()) ? "expansion" : # endif -# if HAS_LINUX_INTERFACE - (UsingLinuxInterface()) ? "SBC" : +# if HAS_SBC_INTERFACE + (UsingSbcInterface()) ? "SBC" : # endif "standalone" #endif @@ -935,10 +935,10 @@ void RepRap::Diagnostics(MessageType mtype) noexcept #if SUPPORT_CAN_EXPANSION CanInterface::Diagnostics(mtype); #endif -#if HAS_LINUX_INTERFACE - if (usingLinuxInterface) +#if HAS_SBC_INTERFACE + if (usingSbcInterface) { - linuxInterface->Diagnostics(mtype); + sbcInterface->Diagnostics(mtype); } else #endif @@ -2511,7 +2511,7 @@ void RepRap::ClearAlert() noexcept size_t RepRap::GetStatusIndex() const noexcept { return (processingConfig) ? 0 // Reading the configuration file -#if HAS_LINUX_INTERFACE && SUPPORT_CAN_EXPANSION +#if HAS_SBC_INTERFACE && SUPPORT_CAN_EXPANSION : (gCodes->IsFlashing() || expansion->IsFlashing()) ? 1 // Flashing a new firmware binary #else : (gCodes->IsFlashing()) ? 1 // Flashing a new firmware binary @@ -2654,7 +2654,7 @@ GCodeResult RepRap::ClearTemperatureFault(int8_t wasDudHeater, const StringRef& return rslt; } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE // Save some resume information, returning true if successful // We assume that the tool configuration doesn't change, only the temperatures and the mix diff --git a/src/Platform/RepRap.h b/src/Platform/RepRap.h index e3c11e28..a136f253 100644 --- a/src/Platform/RepRap.h +++ b/src/Platform/RepRap.h @@ -126,9 +126,9 @@ public: const char *GetLatestMessage(uint16_t& sequence) const noexcept; const MessageBox& GetMessageBox() const noexcept { return mbox; } #endif -#if HAS_LINUX_INTERFACE - bool UsingLinuxInterface() const noexcept { return usingLinuxInterface; } - LinuxInterface& GetLinuxInterface() const noexcept { return *linuxInterface; } +#if HAS_SBC_INTERFACE + bool UsingSbcInterface() const noexcept { return usingSbcInterface; } + SbcInterface& GetSbcInterface() const noexcept { return *sbcInterface; } #endif #if SUPPORT_CAN_EXPANSION ExpansionManager& GetExpansion() const noexcept { return *expansion; } @@ -161,7 +161,7 @@ public: void SetAlert(const char *msg, const char *title, int mode, float timeout, AxesBitmap controls) noexcept; void ClearAlert() noexcept; -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool WriteToolSettings(FileStore *f) noexcept; // save some information for the resume file bool WriteToolParameters(FileStore *f, const bool forceWriteOffsets) noexcept; // save some information in config-override.g #endif @@ -248,8 +248,8 @@ private: Display *display; #endif -#if HAS_LINUX_INTERFACE - LinuxInterface *linuxInterface; +#if HAS_SBC_INTERFACE + SbcInterface *sbcInterface; #endif #if SUPPORT_ROLAND @@ -304,8 +304,8 @@ private: bool stopped; bool active; bool processingConfig; -#if HAS_LINUX_INTERFACE - bool usingLinuxInterface; +#if HAS_SBC_INTERFACE + bool usingSbcInterface; #endif }; diff --git a/src/Platform/TaskPriorities.h b/src/Platform/TaskPriorities.h index b3023c3f..7a876799 100644 --- a/src/Platform/TaskPriorities.h +++ b/src/Platform/TaskPriorities.h @@ -13,7 +13,7 @@ namespace TaskPriority { constexpr unsigned int IdlePriority = 0; constexpr unsigned int SpinPriority = 1; // priority for tasks that rarely block -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE constexpr unsigned int SbcPriority = 2; // priority for SBC task #endif #if defined(LPC_NETWORKING) diff --git a/src/PrintMonitor/PrintMonitor.cpp b/src/PrintMonitor/PrintMonitor.cpp index 96cbac0f..c2c39f53 100644 --- a/src/PrintMonitor/PrintMonitor.cpp +++ b/src/PrintMonitor/PrintMonitor.cpp @@ -179,8 +179,8 @@ void PrintMonitor::SetSlicerTimeLeft(float seconds) noexcept void PrintMonitor::Spin() noexcept { -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { if (!printingFileParsed) { @@ -292,8 +292,8 @@ void PrintMonitor::StartingPrint(const char* filename) noexcept #if HAS_MASS_STORAGE || HAS_EMBEDDED_FILES WriteLocker locker(printMonitorLock); MassStorage::CombineName(filenameBeingPrinted.GetRef(), platform.GetGCodeDir(), filename); -# if HAS_LINUX_INTERFACE - if (!reprap.UsingLinuxInterface()) +# if HAS_SBC_INTERFACE + if (!reprap.UsingSbcInterface()) # endif { printingFileParsed = false; diff --git a/src/RepRapFirmware.cpp b/src/RepRapFirmware.cpp index 98a390cf..d91de2e3 100644 --- a/src/RepRapFirmware.cpp +++ b/src/RepRapFirmware.cpp @@ -197,7 +197,7 @@ static const char * const moduleName[] = "FilamentSensors", "WiFi", "Display", - "LinuxInterface", + "SbcInterface", "CAN", "none" }; diff --git a/src/RepRapFirmware.h b/src/RepRapFirmware.h index 1575632e..48470852 100644 --- a/src/RepRapFirmware.h +++ b/src/RepRapFirmware.h @@ -270,7 +270,7 @@ enum Module : uint8_t moduleFilamentSensors = 13, moduleWiFi = 14, moduleDisplay = 15, - moduleLinuxInterface = 16, + moduleSbcInterface = 16, moduleCan = 17, numModules = 18, // make this one greater than the last real module number noModule = numModules @@ -310,8 +310,8 @@ class PortControl; class Display; #endif -#if HAS_LINUX_INTERFACE -class LinuxInterface; +#if HAS_SBC_INTERFACE +class SbcInterface; #endif #if SUPPORT_CAN_EXPANSION @@ -566,7 +566,7 @@ constexpr size_t NumCoordinateSystems = 1; #define DEGREE_SYMBOL "\xC2\xB0" // degree-symbol encoding in UTF8 -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE typedef uint32_t FileHandle; const FileHandle noFileHandle = 0; #endif diff --git a/src/Linux/DataTransfer.cpp b/src/SBC/DataTransfer.cpp index 06a3f3bb..53166c38 100644 --- a/src/Linux/DataTransfer.cpp +++ b/src/SBC/DataTransfer.cpp @@ -7,9 +7,9 @@ #include "DataTransfer.h" -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE -#include "LinuxInterface.h" +#include "SbcInterface.h" #include <Storage/CRC32.h> #include <algorithm> @@ -69,7 +69,7 @@ constexpr IRQn SBC_SPI_IRQn = SbcSpiSercomIRQn; #include <General/IP4String.h> -static TaskHandle linuxTaskHandle = nullptr; +static TaskHandle sbcTaskHandle = nullptr; #if USE_DMAC @@ -89,7 +89,10 @@ static xdmac_channel_config_t xdmac_tx_cfg, xdmac_rx_cfg; #endif -volatile bool dataReceived = false; // warning: on the SAME5x this just means the transfer has started, not necessarily that it has ended! +volatile bool dataReceived = false; // warning: on the SAME5x this just means the transfer has started, not necessarily that it has ended! +#if SAME5x +uint32_t transferStartTime = 0; +#endif volatile bool transferReadyHigh = false; volatile unsigned int spiTxUnderruns = 0, spiRxOverruns = 0; @@ -112,7 +115,6 @@ static void spi_dma_disable() noexcept } #if !SAME5x - static bool spi_dma_check_rx_complete() noexcept { #if USE_DMAC @@ -271,6 +273,18 @@ pre(bytesToTransfer <= inBuffer.limit; bytesToTransfer <= outBuffer.limit) #endif } +void disable_spi() noexcept +{ + spi_dma_disable(); + +#if SAME5x + SbcSpiSercom->SPI.CTRLA.reg &= ~SERCOM_SPI_CTRLA_ENABLE; + while (SbcSpiSercom->SPI.SYNCBUSY.reg & (SERCOM_SPI_SYNCBUSY_SWRST | SERCOM_SPI_SYNCBUSY_ENABLE)) { }; +#else + spi_disable(SBC_SPI); +#endif +} + static void setup_spi(void *inBuffer, const void *outBuffer, size_t bytesToTransfer) noexcept pre(bytesToTransfer <= inBuffer.limit; bytesToTransfer <= outBuffer.limit) { @@ -322,22 +336,13 @@ pre(bytesToTransfer <= inBuffer.limit; bytesToTransfer <= outBuffer.limit) NVIC_EnableIRQ(SBC_SPI_IRQn); // Begin transfer +#if SAME5x + transferStartTime = 0; +#endif transferReadyHigh = !transferReadyHigh; digitalWrite(SbcTfrReadyPin, transferReadyHigh); } -void disable_spi() noexcept -{ - spi_dma_disable(); - - // Disable SPI -#if SAME5x - SbcSpiSercom->SPI.CTRLA.reg &= ~SERCOM_SPI_CTRLA_ENABLE; - while (SbcSpiSercom->SPI.SYNCBUSY.reg & (SERCOM_SPI_SYNCBUSY_SWRST | SERCOM_SPI_SYNCBUSY_ENABLE)) { }; -#else - spi_disable(SBC_SPI); -#endif -} #ifndef SBC_SPI_HANDLER # error SBC_SPI_HANDLER undefined @@ -354,8 +359,9 @@ extern "C" void SBC_SPI_HANDLER() noexcept SbcSpiSercom->SPI.INTENCLR.reg = SERCOM_SPI_INTENSET_SSL; // disable the interrupt SbcSpiSercom->SPI.INTFLAG.reg = SERCOM_SPI_INTENSET_SSL; // clear the status + // Wake up the SBC task dataReceived = true; - TaskBase::GiveFromISR(linuxTaskHandle); + TaskBase::GiveFromISR(sbcTaskHandle); } #else const uint32_t status = SBC_SPI->SPI_SR; // read status and clear interrupt @@ -375,9 +381,9 @@ extern "C" void SBC_SPI_HANDLER() noexcept ++spiTxUnderruns; } - // Wake up the Linux task + // Wake up the SBC task dataReceived = true; - TaskBase::GiveFromISR(linuxTaskHandle); + TaskBase::GiveFromISR(sbcTaskHandle); } #endif } @@ -391,11 +397,11 @@ __nocache TransferHeader DataTransfer::rxHeader; __nocache TransferHeader DataTransfer::txHeader; __nocache uint32_t DataTransfer::rxResponse; __nocache uint32_t DataTransfer::txResponse; -alignas(4) __nocache char DataTransfer::rxBuffer[LinuxTransferBufferSize]; -alignas(4) __nocache char DataTransfer::txBuffer[LinuxTransferBufferSize]; +alignas(4) __nocache char DataTransfer::rxBuffer[SbcTransferBufferSize]; +alignas(4) __nocache char DataTransfer::txBuffer[SbcTransferBufferSize]; #endif -DataTransfer::DataTransfer() noexcept : state(SpiState::ExchangingData), lastTransferTime(0), lastTransferNumber(0), failedTransfers(0), checksumErrors(0), +DataTransfer::DataTransfer() noexcept : state(InternalTransferState::ExchangingData), lastTransferNumber(0), failedTransfers(0), checksumErrors(0), #if SAME5x rxBuffer(nullptr), txBuffer(nullptr), #endif @@ -408,8 +414,8 @@ DataTransfer::DataTransfer() noexcept : state(SpiState::ExchangingData), lastTra rxHeader.sequenceNumber = 0; // Prepare TX header - txHeader.formatCode = LinuxFormatCode; - txHeader.protocolVersion = LinuxProtocolVersion; + txHeader.formatCode = SbcFormatCode; + txHeader.protocolVersion = SbcProtocolVersion; txHeader.numPackets = 0; txHeader.sequenceNumber = 0; } @@ -420,16 +426,16 @@ void DataTransfer::Init() noexcept pinMode(SbcTfrReadyPin, OUTPUT_LOW); #if !SAME70 - if (reprap.UsingLinuxInterface()) + if (reprap.UsingSbcInterface()) { // Allocate buffers in SBC mode - rxBuffer = (char *)new uint32_t[(LinuxTransferBufferSize + 3)/4]; - txBuffer = (char *)new uint32_t[(LinuxTransferBufferSize + 3)/4]; + rxBuffer = (char *)new uint32_t[(SbcTransferBufferSize + 3)/4]; + txBuffer = (char *)new uint32_t[(SbcTransferBufferSize + 3)/4]; } else { // Only send back the TX header + response code in standalone mode indicating we're running in standalone mode - txHeader.formatCode = LinuxFormatCodeStandalone; + txHeader.formatCode = SbcFormatCodeStandalone; } #endif @@ -489,7 +495,7 @@ void DataTransfer::Init() noexcept matrix_set_slave_slot_cycle(0, 8); #endif - if (!reprap.UsingLinuxInterface()) + if (!reprap.UsingSbcInterface()) { // Start off the first transfer in standalone mode StartNextTransfer(); @@ -498,13 +504,12 @@ void DataTransfer::Init() noexcept void DataTransfer::InitFromTask() noexcept { - linuxTaskHandle = TaskBase::GetCallerTaskHandle(); + sbcTaskHandle = TaskBase::GetCallerTaskHandle(); } void DataTransfer::Diagnostics(MessageType mtype) noexcept { - reprap.GetPlatform().MessageF(mtype, "State: %d, failed transfers: %u, checksum errors: %u\n", (int)state, failedTransfers, checksumErrors); - reprap.GetPlatform().MessageF(mtype, "Last transfer: %" PRIu32 "ms ago\n", millis() - lastTransferTime); + reprap.GetPlatform().MessageF(mtype, "Transfer state: %d, failed transfers: %u, checksum errors: %u\n", (int)state, failedTransfers, checksumErrors); reprap.GetPlatform().MessageF(mtype, "RX/TX seq numbers: %d/%d\n", (int)rxHeader.sequenceNumber, (int)txHeader.sequenceNumber); reprap.GetPlatform().MessageF(mtype, "SPI underruns %u, overruns %u\n", spiTxUnderruns, spiRxOverruns); } @@ -736,7 +741,7 @@ int DataTransfer::ReadFileData(char *buffer, size_t length) noexcept void DataTransfer::ExchangeHeader() noexcept { Cache::FlushBeforeDMASend(&txHeader, sizeof(txHeader)); - state = SpiState::ExchangingHeader; + state = InternalTransferState::ExchangingHeader; setup_spi(&rxHeader, &txHeader, sizeof(TransferHeader)); } @@ -744,7 +749,7 @@ void DataTransfer::ExchangeResponse(uint32_t response) noexcept { txResponse = response; Cache::FlushBeforeDMASend(&txResponse, sizeof(txResponse)); - state = (state == SpiState::ExchangingHeader) ? SpiState::ExchangingHeaderResponse : SpiState::ExchangingDataResponse; + state = (state == InternalTransferState::ExchangingHeader) ? InternalTransferState::ExchangingHeaderResponse : InternalTransferState::ExchangingDataResponse; setup_spi(&rxResponse, &txResponse, sizeof(uint32_t)); } @@ -752,15 +757,15 @@ void DataTransfer::ExchangeData() noexcept { Cache::FlushBeforeDMASend(txBuffer, txHeader.dataLength); size_t bytesToExchange = max<size_t>(rxHeader.dataLength, txHeader.dataLength); - state = SpiState::ExchangingData; + state = InternalTransferState::ExchangingData; setup_spi(rxBuffer, txBuffer, bytesToExchange); } -void DataTransfer::StatefulTransferReset(bool ownRequest) noexcept +void DataTransfer::ResetTransfer(bool ownRequest) noexcept { - if (reprap.Debug(moduleLinuxInterface)) + if (reprap.Debug(moduleSbcInterface)) { - debugPrintf(ownRequest ? "Resetting transfer\n" : "Resetting transfer due to Linux request\n"); + debugPrintf(ownRequest ? "Resetting transfer\n" : "Resetting transfer due to Sbc request\n"); } if (ownRequest) @@ -768,69 +773,67 @@ void DataTransfer::StatefulTransferReset(bool ownRequest) noexcept // Invalidate the data to send txResponse = TransferResponse::BadResponse; Cache::FlushBeforeDMASend(&txResponse, sizeof(txResponse)); - state = SpiState::Resetting; + state = InternalTransferState::Resetting; setup_spi(&rxResponse, &txResponse, sizeof(uint32_t)); } else { - // Linux wants to reset the state + // Sbc wants to reset the state ExchangeHeader(); } } -bool DataTransfer::IsReady() noexcept +TransferState DataTransfer::DoTransfer() noexcept { if (dataReceived) { #if SAME5x // Unfortunately the SAME5x doesn't have an end-of-transfer interrupt, but SPI transfers typically don't take long - uint32_t startTime = millis(); - while (!digitalRead(SbcSSPin)) // transfer is complete if SS is high + if (!digitalRead(SbcSSPin)) // transfer is complete if SS is high { - if (millis() - startTime > SpiTransferTimeout) + if (transferStartTime == 0) { - disable_spi(); // disable the SPI subsystem first, else only zeros are transferred - StatefulTransferReset(true); - return false; + transferStartTime = millis(); + return TransferState::finishingTransfer; } + return (millis() - transferStartTime > SpiMaxTransferTime) ? TransferState::connectionTimeout : TransferState::finishingTransfer; } + transferStartTime = 0; if (SbcSpiSercom->SPI.STATUS.bit.BUFOVF) { ++spiRxOverruns; } - disable_spi(); #else // Wait for the current XDMA transfer to finish. Relying on the XDMAC IRQ for this is does not work well... if (!spi_dma_check_rx_complete()) { - return false; + return TransferState::finishingTransfer; } #endif // Transfer has finished dataReceived = false; - lastTransferTime = millis(); switch (state) { - case SpiState::ExchangingHeader: + case InternalTransferState::ExchangingHeader: { Cache::InvalidateAfterDMAReceive(&rxHeader, sizeof(rxHeader)); // (1) Exchanged transfer headers const uint32_t headerResponse = *reinterpret_cast<const uint32_t*>(&rxHeader); if (headerResponse == TransferResponse::BadResponse) { - // Linux wants to restart the transfer - StatefulTransferReset(false); + // Sbc wants to restart the transfer + ResetTransfer(false); break; } const uint32_t checksum = CalcCRC32(reinterpret_cast<const char *>(&rxHeader), sizeof(TransferHeader) - sizeof(uint32_t)); if (rxHeader.crcHeader != checksum) { - if (reprap.Debug(moduleLinuxInterface)) + if (reprap.Debug(moduleSbcInterface)) { debugPrintf("Bad header CRC (expected %08" PRIx32 ", got %08" PRIx32 ")\n", rxHeader.crcHeader, checksum); } @@ -838,17 +841,17 @@ bool DataTransfer::IsReady() noexcept break; } - if (rxHeader.formatCode != LinuxFormatCode) + if (rxHeader.formatCode != SbcFormatCode) { ExchangeResponse(TransferResponse::BadFormat); break; } - if (rxHeader.protocolVersion != LinuxProtocolVersion) + if (rxHeader.protocolVersion != SbcProtocolVersion) { ExchangeResponse(TransferResponse::BadProtocolVersion); break; } - if (rxHeader.dataLength > LinuxTransferBufferSize) + if (rxHeader.dataLength > SbcTransferBufferSize) { ExchangeResponse(TransferResponse::BadDataLength); break; @@ -858,12 +861,12 @@ bool DataTransfer::IsReady() noexcept break; } - case SpiState::ExchangingHeaderResponse: + case InternalTransferState::ExchangingHeaderResponse: // (2) Exchanged response to transfer header Cache::InvalidateAfterDMAReceive(&rxResponse, sizeof(rxResponse)); if (rxResponse == TransferResponse::Success && txResponse == TransferResponse::Success) { - if (reprap.UsingLinuxInterface() && (rxHeader.dataLength != 0 || txHeader.dataLength != 0)) + if (reprap.UsingSbcInterface() && (rxHeader.dataLength != 0 || txHeader.dataLength != 0)) { // Perform the actual data transfer ExchangeData(); @@ -873,14 +876,14 @@ bool DataTransfer::IsReady() noexcept // Everything OK rxPointer = txPointer = 0; packetId = 0; - state = SpiState::ProcessingData; - return true; + state = InternalTransferState::ProcessingData; + return IsConnectionReset() ? TransferState::connectionReset : TransferState::finished; } } else if (rxResponse == TransferResponse::BadResponse) { - // Linux wants to restart the transfer - StatefulTransferReset(false); + // Sbc wants to restart the transfer + ResetTransfer(false); } else if (rxResponse == TransferResponse::BadHeaderChecksum || txResponse == TransferResponse::BadHeaderChecksum) { @@ -891,19 +894,19 @@ bool DataTransfer::IsReady() noexcept else { // Received invalid response code - StatefulTransferReset(true); + ResetTransfer(true); } break; - case SpiState::ExchangingData: + case InternalTransferState::ExchangingData: { Cache::InvalidateAfterDMAReceive(rxBuffer, rxHeader.dataLength); // (3) Exchanged data if (*reinterpret_cast<uint32_t*>(rxBuffer) == TransferResponse::BadResponse) { - if (reprap.Debug(moduleLinuxInterface)) + if (reprap.Debug(moduleSbcInterface)) { - debugPrintf("Resetting state due to Linux request\n"); + debugPrintf("Resetting state due to Sbc request\n"); } failedTransfers++; ExchangeHeader(); @@ -913,7 +916,7 @@ bool DataTransfer::IsReady() noexcept const uint32_t checksum = CalcCRC32(rxBuffer, rxHeader.dataLength); if (rxHeader.crcData != checksum) { - if (reprap.Debug(moduleLinuxInterface)) + if (reprap.Debug(moduleSbcInterface)) { debugPrintf("Bad data CRC (expected %08" PRIx32 ", got %08" PRIx32 ")\n", rxHeader.crcData, checksum); } @@ -925,7 +928,7 @@ bool DataTransfer::IsReady() noexcept break; } - case SpiState::ExchangingDataResponse: + case InternalTransferState::ExchangingDataResponse: // (4) Exchanged response to data transfer Cache::InvalidateAfterDMAReceive(&rxResponse, sizeof(rxResponse)); if (rxResponse == TransferResponse::Success && txResponse == TransferResponse::Success) @@ -933,14 +936,14 @@ bool DataTransfer::IsReady() noexcept // Everything OK rxPointer = txPointer = 0; packetId = 0; - state = SpiState::ProcessingData; - return true; + state = InternalTransferState::ProcessingData; + return IsConnectionReset() ? TransferState::connectionReset : TransferState::finished; } if (rxResponse == TransferResponse::BadResponse) { - // Linux wants to restart the transfer - StatefulTransferReset(false); + // Sbc wants to restart the transfer + ResetTransfer(false); } else if (rxResponse == TransferResponse::BadDataChecksum || txResponse == TransferResponse::BadDataChecksum) { @@ -951,11 +954,11 @@ bool DataTransfer::IsReady() noexcept else { // Received invalid response, reset the SPI transfer - StatefulTransferReset(true); + ResetTransfer(true); } break; - case SpiState::Resetting: + case InternalTransferState::Resetting: // Transmitted bad response, attempt to start a new transfer ExchangeHeader(); break; @@ -967,12 +970,7 @@ bool DataTransfer::IsReady() noexcept break; } } - else if (!reprap.GetLinuxInterface().IsWritingIap() && millis() - lastTransferTime > SpiTransferTimeout) - { - // Reset failed transfers automatically after a certain period of time - ResetTransfer(); - } - return false; + return (state == InternalTransferState::ExchangingHeader) ? TransferState::doingFullTransfer : TransferState::doingPartialTransfer; } void DataTransfer::StartNextTransfer() noexcept @@ -994,41 +992,29 @@ void DataTransfer::StartNextTransfer() noexcept txHeader.crcData = CalcCRC32(txBuffer, txPointer); txHeader.crcHeader = CalcCRC32(reinterpret_cast<const char *>(&txHeader), sizeof(TransferHeader) - sizeof(uint32_t)); - // Begin SPI transfer + // Begin SPI transfe ExchangeHeader(); } -void DataTransfer::ResetTransfer() noexcept +void DataTransfer::ResetConnection(bool fullReset) noexcept { + // The Sbc interface is no longer connected... + disable_spi(); dataReceived = false; - if (state != SpiState::ExchangingHeader) - { - disable_spi(); - failedTransfers++; - transferReadyHigh = false; - ExchangeHeader(); - } -} -void DataTransfer::ResetConnection() noexcept -{ - if (lastTransferNumber != 0) - { - // The Linux interface is no longer connected... - disable_spi(); - dataReceived = false; - - // Reset the sequence numbers and clear the data to send - lastTransferNumber = 0; - rxHeader.sequenceNumber = 0; - txHeader.sequenceNumber = 0; - rxPointer = txPointer = 0; - packetId = 0; + // Reset the sequence numbers and clear the data to send + lastTransferNumber = 0; + rxHeader.sequenceNumber = 0; + txHeader.sequenceNumber = 0; + rxPointer = txPointer = 0; + packetId = 0; - // Kick off a new transfer + // Kick off a new transfer + if (fullReset) + { transferReadyHigh = false; - StartNextTransfer(); } + StartNextTransfer(); } bool DataTransfer::WriteObjectModel(OutputBuffer *data) noexcept @@ -1685,7 +1671,7 @@ bool DataTransfer::WriteReadFile(FileHandle handle, size_t bufferSize) noexcept // Write data header ReadFileHeader *header = WriteDataHeader<ReadFileHeader>(); header->handle = handle; - header->maxLength = min<uint32_t>(bufferSize, LinuxTransferBufferSize - sizeof(FileDataHeader)); + header->maxLength = min<uint32_t>(bufferSize, SbcTransferBufferSize - sizeof(FileDataHeader)); return true; } diff --git a/src/Linux/DataTransfer.h b/src/SBC/DataTransfer.h index 20b32f55..4882b703 100644 --- a/src/Linux/DataTransfer.h +++ b/src/SBC/DataTransfer.h @@ -5,16 +5,16 @@ * Author: Christian */ -#ifndef SRC_LINUX_DATATRANSFER_H_ -#define SRC_LINUX_DATATRANSFER_H_ +#ifndef SRC_SBC_DATATRANSFER_H_ +#define SRC_SBC_DATATRANSFER_H_ #include "RepRapFirmware.h" -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE #include <GCodes/GCodeFileInfo.h> #include <GCodes/GCodeChannel.h> -#include "LinuxMessageFormats.h" +#include "SbcMessageFormats.h" #include <RTOSIface/RTOSIface.h> class BinaryGCodeBuffer; @@ -25,6 +25,16 @@ class HeightMap; struct ExpressionValue; +enum class TransferState +{ + doingFullTransfer, + doingPartialTransfer, + finishingTransfer, + connectionTimeout, + connectionReset, + finished +}; + class DataTransfer { public: @@ -33,11 +43,9 @@ public: void InitFromTask() noexcept; void Diagnostics(MessageType mtype) noexcept; - bool IsConnected() const noexcept; // Check if the connection to DCS is live - bool IsReady() noexcept; // Returns true when data can be read + TransferState DoTransfer() noexcept; // Try to finish the current transfer void StartNextTransfer() noexcept; // Kick off the next transfer - void ResetConnection() noexcept; // Reset the connection after a longer timeout - bool LinuxHadReset() const noexcept; // Check if the remote end reset + void ResetConnection(bool fullReset) noexcept; // Reset the connection after a longer timeout size_t PacketsToRead() const noexcept; const PacketHeader *ReadPacket() noexcept; // Attempt to read the next packet header or return null. Advances the read pointer to the next packet or the packet's data @@ -85,7 +93,7 @@ public: bool WriteCloseFile(FileHandle handle) noexcept; private: - enum class SpiState + enum class InternalTransferState { ExchangingHeader, ExchangingHeaderResponse, @@ -96,12 +104,10 @@ private: } state; // Transfer properties - uint32_t lastTransferTime; uint16_t lastTransferNumber; unsigned int failedTransfers, checksumErrors; // Transfer buffers - #if SAME70 // SAME70 has a write-back cache, so these must be in non-cached memory because we DMA to/from them. // See http://ww1.microchip.com/downloads/en/DeviceDoc/Managing-Cache-Coherency-on-Cortex-M7-Based-MCUs-DS90003195A.pdf @@ -110,8 +116,8 @@ private: static __nocache TransferHeader txHeader; static __nocache uint32_t rxResponse; static __nocache uint32_t txResponse; - alignas(4) static __nocache char rxBuffer[LinuxTransferBufferSize]; - alignas(4) static __nocache char txBuffer[LinuxTransferBufferSize]; + alignas(4) static __nocache char rxBuffer[SbcTransferBufferSize]; + alignas(4) static __nocache char txBuffer[SbcTransferBufferSize]; #else // The other processors we support have write-through cache // Allocate the buffers in the object so that we can delete the object and recycle the memory if the SBC interface is not being used @@ -123,24 +129,23 @@ private: char *rxBuffer; // not allocated until we know we need it char *txBuffer; // not allocated until we know we need it #endif - size_t rxPointer, txPointer; // Packet properties uint16_t packetId; + bool IsConnectionReset() const noexcept; + void ExchangeHeader() noexcept; void ExchangeResponse(uint32_t response) noexcept; void ExchangeData() noexcept; - void ResetTransfer() noexcept; - void StatefulTransferReset(bool ownRequest) noexcept; + void ResetTransfer(bool ownRequest) noexcept; uint32_t CalcCRC32(const char *buffer, size_t length) const noexcept; template<typename T> const T *ReadDataHeader() noexcept; - // Always keep enough tx space to allow resend requests in case RRF runs out of - // resources and cannot process an incoming request right away - size_t FreeTxSpace() const noexcept { return LinuxTransferBufferSize - AddPadding(txPointer) - rxHeader.numPackets * sizeof(PacketHeader); } + // Always keep enough tx space to allow resend requests in case RRF runs out of resources and cannot process an incoming request right away + size_t FreeTxSpace() const noexcept { return SbcTransferBufferSize - AddPadding(txPointer) - rxHeader.numPackets * sizeof(PacketHeader); } bool CanWritePacket(size_t dataLength = 0) const noexcept; PacketHeader *WritePacketHeader(FirmwareRequest request, size_t dataLength = 0, uint16_t resendPacktId = 0) noexcept; @@ -150,12 +155,7 @@ private: size_t AddPadding(size_t length) const noexcept; }; -inline bool DataTransfer::IsConnected() const noexcept -{ - return lastTransferTime != 0 && (millis() - lastTransferTime < SpiConnectionTimeout); -} - -inline bool DataTransfer::LinuxHadReset() const noexcept +inline bool DataTransfer::IsConnectionReset() const noexcept { uint16_t nextTransferNumber = lastTransferNumber + 1; return lastTransferNumber != 0 && (nextTransferNumber != rxHeader.sequenceNumber); @@ -181,6 +181,6 @@ inline size_t DataTransfer::AddPadding(size_t length) const noexcept size_t extraBytes = (length & 3); return (extraBytes == 0) ? length : length + 4 - extraBytes; } -#endif // HAS_LINUX_INTERFACE +#endif // HAS_SBC_INTERFACE -#endif /* SRC_LINUX_DATATRANSFER_H_ */ +#endif /* SRC_SBC_DATATRANSFER_H_ */ diff --git a/src/SBC/SbcInterface.cpp b/src/SBC/SbcInterface.cpp new file mode 100644 index 00000000..73cfb885 --- /dev/null +++ b/src/SBC/SbcInterface.cpp @@ -0,0 +1,1785 @@ +/* + * SbcInterface.cpp + * + * Created on: 29 Mar 2019 + * Author: Christian + */ + +#include "SbcInterface.h" +#include "DataTransfer.h" + +#if HAS_SBC_INTERFACE + +#include <GCodes/GCodeBuffer/ExpressionParser.h> +#include <GCodes/GCodeBuffer/GCodeBuffer.h> +#include <Heating/Heat.h> +#include <Movement/Move.h> +#include <Platform/Platform.h> +#include <PrintMonitor/PrintMonitor.h> +#include <Tools/Filament.h> +#include <Platform/RepRap.h> +#include <RepRapFirmware.h> +#include <Platform/Tasks.h> +#include <Hardware/SoftwareReset.h> +#include <Hardware/ExceptionHandlers.h> +#include <Platform/TaskPriorities.h> + +extern char _estack; // defined by the linker + +volatile OutputStack SbcInterface::gcodeReply; +Mutex SbcInterface::gcodeReplyMutex; + +// The SBC task's stack size needs to be enough to support rr_model and expression evaluation +// In RRF 3.3beta3, 744 is only just enough for simple expression evaluation in a release build when using globals +// In 3.3beta3.1 we have saved ~151 bytes (37 words) of stack compared to 3.3beta3 +#ifdef __LPC17xx__ +constexpr size_t SBCTaskStackWords = 375; +#elif defined(DEBUG) +constexpr size_t SBCTaskStackWords = 1200; // debug builds use more stack +#else +constexpr size_t SBCTaskStackWords = 1000; // increased from 820 so that we can evaluate "abs(move.calibration.initial.deviation - move.calibration.final.deviation) < 0.000" +#endif + +constexpr uint32_t SbcYieldTimeout = 10; + +static Task<SBCTaskStackWords> *sbcTask; + +extern "C" [[noreturn]] void SBCTaskStart(void * pvParameters) noexcept +{ + reprap.GetSbcInterface().TaskLoop(); +} + +SbcInterface::SbcInterface() noexcept : isConnected(false), numDisconnects(0), numTimeouts(0), + maxDelayBetweenTransfers(SpiTransferDelay), maxFileOpenDelay(SpiFileOpenDelay), numMaxEvents(SpiEventsRequired), + delaying(false), numEvents(0), reportPause(false), reportPauseWritten(false), printAborted(false), + codeBuffer(nullptr), rxPointer(0), txPointer(0), txEnd(0), sendBufferUpdate(true), + waitingForFileChunk(false), fileMutex(), fileSemaphore(), fileOperation(FileOperation::none), fileOperationPending(false) +#ifdef TRACK_FILE_CODES + , fileCodesRead(0), fileCodesHandled(0), fileMacrosRunning(0), fileMacrosClosing(0) +#endif +{ +} + +void SbcInterface::Init() noexcept +{ + if (reprap.UsingSbcInterface()) + { + fileMutex.Create("SBCFile"); + gcodeReplyMutex.Create("SBCReply"); + codeBuffer = (char *)new uint32_t[(SpiCodeBufferSize + 3)/4]; + +#if defined(DUET_NG) + // Make sure that the Wifi module if present is disabled. The ESP Reset pin is already forced low in Platform::Init(); + pinMode(EspEnablePin, OUTPUT_LOW); +#endif + + transfer.Init(); + sbcTask = new Task<SBCTaskStackWords>(); + sbcTask->Create(SBCTaskStart, "SBC", nullptr, TaskPriority::SbcPriority); + iapRamAvailable = &_estack - Tasks::GetHeapTop(); + } + else + { + // Set up the data transfer to exchange the header + response code. No task is started to save memory + transfer.Init(); + } +} + +void SbcInterface::Spin() noexcept +{ + if (transfer.DoTransfer() != TransferState::finishingTransfer) + { + // Don't process anything, just kick off the next transfer to report we're operating in standalone mode + transfer.StartNextTransfer(); + } +} + +[[noreturn]] void SbcInterface::TaskLoop() noexcept +{ + transfer.InitFromTask(); + transfer.StartNextTransfer(); + + bool busy = false, transferComplete = false, hadTimeout = false, hadReset = false; + for (;;) + { + // Try to exchange data with the SBC + transferComplete = hadTimeout = hadReset = false; + do + { + busy = false; + state = transfer.DoTransfer(); + switch (state) + { + case TransferState::doingFullTransfer: + hadTimeout = !TaskBase::Take(isConnected ? SpiConnectionTimeout : TaskBase::TimeoutUnlimited); + break; + case TransferState::doingPartialTransfer: + hadTimeout = !TaskBase::Take(SpiTransferTimeout); + break; + case TransferState::finishingTransfer: + busy = true; + break; + case TransferState::connectionTimeout: + hadTimeout = true; + break; + case TransferState::connectionReset: + hadReset = true; + break; + case TransferState::finished: + transferComplete = true; + break; + } + } while (busy); + + // Handle connection errors + if (isConnected && (hadReset || hadTimeout)) + { + isConnected = false; + numDisconnects++; + if (hadTimeout) + { + numTimeouts++; + } + reprap.GetPlatform().Message(NetworkInfoMessage, "Lost connection to SBC\n"); + + // Invalidate local resources + InvalidateResources(); + if (hadReset) + { + // Let the main task invalidate resources before processing new data + TaskBase::Take(SbcYieldTimeout); + + // Reset the SPI connection again + transfer.ResetConnection(false); + } + } + + // Deal with received data + if (transferComplete) + { + if (!isConnected) + { + isConnected = true; + reprap.GetPlatform().Message(NetworkInfoMessage, "Connection to SBC established!\n"); + } + + // Handle exchanged data and kick off the next transfer + ExchangeData(); + transfer.StartNextTransfer(); + } + else if (hadTimeout) + { + // Reset the SPI connection if no data could be exchanged + transfer.ResetConnection(true); + } + } +} + +void SbcInterface::ExchangeData() noexcept +{ + // Process incoming packets + bool codeBufferAvailable = true; + for (size_t i = 0; i < transfer.PacketsToRead(); i++) + { + const PacketHeader * const packet = transfer.ReadPacket(); + if (packet == nullptr) + { + if (reprap.Debug(moduleSbcInterface)) + { + debugPrintf("Error trying to read next SPI packet\n"); + } + break; + } + + if (packet->request >= (uint16_t)SbcRequest::InvalidRequest) + { + REPORT_INTERNAL_ERROR; + break; + } + + bool packetAcknowledged = true; + switch ((SbcRequest)packet->request) + { + // Perform an emergency stop + case SbcRequest::EmergencyStop: + reprap.EmergencyStop(); + break; + + // Reset the controller + case SbcRequest::Reset: + SoftwareReset(SoftwareResetReason::user); + break; + + // Perform a G/M/T-code + case SbcRequest::Code: + { + // Read the next code + if (packet->length == 0) + { + reprap.GetPlatform().Message(WarningMessage, "Received empty binary code, discarding\n"); + break; + } + + const CodeHeader *code = reinterpret_cast<const CodeHeader*>(transfer.ReadData(packet->length)); + const GCodeChannel channel(code->channel); + GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); + if (gb->IsInvalidated()) + { + // Don't deal with codes that will be thrown away + break; + } + + // Check if a GB is waiting for a macro file to be started + if (gb->IsWaitingForMacro() && !gb->IsMacroRequestPending()) + { + gb->ResolveMacroRequest(false, false); +#ifdef TRACK_FILE_CODES + if (channel == GCodeChannel::File) + { + fileMacrosRunning++; + } +#endif + } + + // Don't process any more codes if we failed to store them last time... + if (!codeBufferAvailable) + { + packetAcknowledged = false; + break; + } + + TaskCriticalSectionLocker locker; + + // Make sure no existing codes are overwritten + uint16_t bufferedCodeSize = sizeof(BufferedCodeHeader) + packet->length; + if ((txEnd == 0 && bufferedCodeSize > max<uint16_t>(rxPointer, SpiCodeBufferSize - txPointer)) || + (txEnd != 0 && bufferedCodeSize > rxPointer - txPointer)) + { +#if false + // This isn't enabled because the debug call plus critical section would lead to software resets + debugPrintf("Failed to store code, RX/TX %d/%d-%d\n", rxPointer, txPointer, txEnd); +#endif + packetAcknowledged = codeBufferAvailable = false; + break; + } + + // Overlap if necessary + if (txPointer + bufferedCodeSize > SpiCodeBufferSize) + { + txEnd = txPointer; + txPointer = 0; + sendBufferUpdate = true; + } + + // Store the buffer header + BufferedCodeHeader *bufHeader = reinterpret_cast<BufferedCodeHeader *>(codeBuffer + txPointer); + bufHeader->isPending = true; + bufHeader->length = packet->length; + + // Store the corresponding code. Binary codes are always aligned on a 4-byte boundary + uint32_t *dst = reinterpret_cast<uint32_t *>(codeBuffer + txPointer + sizeof(BufferedCodeHeader)); + const uint32_t *src = reinterpret_cast<const uint32_t *>(code); + memcpyu32(dst, src, packet->length / sizeof(uint32_t)); + txPointer += bufferedCodeSize; + break; + } + + // Get the object model + case SbcRequest::GetObjectModel: + { + String<StringLength100> key; + String<StringLength20> flags; + transfer.ReadGetObjectModel(packet->length, key.GetRef(), flags.GetRef()); + + try + { + OutputBuffer *outBuf = reprap.GetModelResponse(key.c_str(), flags.c_str()); + if (outBuf == nullptr || !transfer.WriteObjectModel(outBuf)) + { + // Failed to write the whole object model, try again later + packetAcknowledged = false; + OutputBuffer::ReleaseAll(outBuf); + } + } + catch (const GCodeException& e) + { + // Get the error message and send it back to DSF + OutputBuffer *buf; + if (OutputBuffer::Allocate(buf)) + { + String<StringLength100> errorMessage; + e.GetMessage(errorMessage.GetRef(), nullptr); + buf->cat(errorMessage.c_str()); + if (!transfer.WriteObjectModel(buf)) + { + OutputBuffer::ReleaseAll(buf); + packetAcknowledged = false; + } + } + else + { + packetAcknowledged = false; + } + } + break; + } + + // Set value in the object model + case SbcRequest::SetObjectModel: + { + const size_t dataLength = packet->length; + const char * const data = transfer.ReadData(dataLength); + // TODO implement this + (void)data; + break; + } + + // Print is about to be started, set file print info + case SbcRequest::SetPrintFileInfo: + { + String<MaxFilenameLength> filename; + transfer.ReadPrintStartedInfo(packet->length, filename.GetRef(), fileInfo); + reprap.GetPrintMonitor().SetPrintingFileInfo(filename.c_str(), fileInfo); + break; + } + + // Print has been stopped + case SbcRequest::PrintStopped: + { + const PrintStoppedReason reason = transfer.ReadPrintStoppedInfo(); + if (reason == PrintStoppedReason::abort) + { + // Stop the print with the given reason + printAborted = true; + InvalidateBufferedCodes(GCodeChannel::File); + } + else + { + // Just mark the print file as finished + GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(GCodeChannel::File); + MutexLocker locker(gb->mutex, SbcYieldTimeout); + if (locker.IsAcquired()) + { + gb->SetPrintFinished(); + } + else + { + packetAcknowledged = false; + } + } + break; + } + + // Macro file has been finished + case SbcRequest::MacroCompleted: + { + bool error; + const GCodeChannel channel = transfer.ReadMacroCompleteInfo(error); + if (channel.IsValid()) + { + GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); + if (gb->IsWaitingForMacro() && !gb->IsMacroRequestPending()) + { + gb->ResolveMacroRequest(error, true); + if (reprap.Debug(moduleSbcInterface)) + { + debugPrintf("Waiting macro completed on channel %u\n", channel.ToBaseType()); + } + } + else + { + MutexLocker locker(gb->mutex, SbcYieldTimeout); + if (locker.IsAcquired()) + { + if (error) + { + gb->CurrentFileMachineState().CloseFile(); + gb->PopState(); + gb->Init(); + } + else + { +#ifdef TRACK_FILE_CODES + if (channel == GCodeChannel::File) + { + fileMacrosClosing++; + } +#endif + gb->SetFileFinished(); + } + + if (reprap.Debug(moduleSbcInterface)) + { + debugPrintf("Macro completed on channel %u\n", channel.ToBaseType()); + } + } + else + { + packetAcknowledged = false; + } + } + } + else + { + REPORT_INTERNAL_ERROR; + } + break; + } + + // Return heightmap as generated by G29 S0 + case SbcRequest::GetHeightMap: + { + ConditionalReadLocker locker(reprap.GetMove().heightMapLock); + if (locker.IsLocked()) + { + packetAcknowledged = transfer.WriteHeightMap(); + } + else + { + packetAcknowledged = false; + } + break; + } + + // Set heightmap via G29 S1 + case SbcRequest::SetHeightMap: + { + ConditionalWriteLocker locker(reprap.GetMove().heightMapLock); + if (locker.IsLocked()) + { + if (!transfer.ReadHeightMap()) + { + reprap.GetPlatform().Message(ErrorMessage, "Failed to set height map - bad data?\n"); + } + } + else + { + packetAcknowledged = false; + } + break; + } + + // Lock movement and wait for standstill + case SbcRequest::LockMovementAndWaitForStandstill: + { + const GCodeChannel channel = transfer.ReadCodeChannel(); + if (channel.IsValid()) + { + GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); + MutexLocker locker(gb->mutex, SbcYieldTimeout); + if (locker.IsAcquired() && reprap.GetGCodes().LockMovementAndWaitForStandstill(*gb)) + { + transfer.WriteLocked(channel); + } + else + { + packetAcknowledged = false; + } + } + else + { + REPORT_INTERNAL_ERROR; + } + break; + } + + // Unlock everything + case SbcRequest::Unlock: + { + const GCodeChannel channel = transfer.ReadCodeChannel(); + if (channel.IsValid()) + { + GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); + MutexLocker locker(gb->mutex, SbcYieldTimeout); + if (locker.IsAcquired()) + { + reprap.GetGCodes().UnlockAll(*gb); + } + else + { + packetAcknowledged = false; + } + } + else + { + REPORT_INTERNAL_ERROR; + } + break; + } + + // Write the first chunk of the IAP binary + case SbcRequest::WriteIap: + { + reprap.PrepareToLoadIap(); + ReceiveAndStartIap(transfer.ReadData(packet->length), packet->length); + break; + } + + // Assign filament (deprecated) + case SbcRequest::AssignFilament_deprecated: + (void)transfer.ReadData(packet->length); // skip the packet content + break; + + // Return a file chunk + case SbcRequest::FileChunk: + transfer.ReadFileChunk(requestedFileBuffer, requestedFileDataLength, requestedFileLength); + requestedFileSemaphore.Give(); + break; + + // Evaluate an expression + case SbcRequest::EvaluateExpression: + { + String<GCODE_LENGTH> expression; + const GCodeChannel channel = transfer.ReadEvaluateExpression(packet->length, expression.GetRef()); + if (channel.IsValid()) + { + GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); + + // If there is a macro file waiting, the first instruction must be conditional. Don't block any longer... + if (gb->IsWaitingForMacro()) + { + gb->ResolveMacroRequest(false, false); +#ifdef TRACK_FILE_CODES + if (channel == GCodeChannel::File) + { + fileMacrosRunning++; + } +#endif + } + + try + { + // Evaluate the expression and send the result to DSF + MutexLocker lock(gb->mutex, SbcYieldTimeout); + if (lock.IsAcquired()) + { + ExpressionParser parser(*gb, expression.c_str(), expression.c_str() + expression.strlen()); + const ExpressionValue val = parser.Parse(); + packetAcknowledged = transfer.WriteEvaluationResult(expression.c_str(), val); + } + else + { + packetAcknowledged = false; + } + } + catch (const GCodeException& e) + { + // Get the error message and send it back to DSF + String<StringLength100> errorMessage; + e.GetMessage(errorMessage.GetRef(), nullptr); + packetAcknowledged = transfer.WriteEvaluationError(expression.c_str(), errorMessage.c_str()); + } + } + else + { + REPORT_INTERNAL_ERROR; + } + break; + } + + // Send a firmware message, typically a response to a command that has been passed to DSF. + // These responses can get quite long (e.g. responses to M20) so receive it into an OutputBuffer. + case SbcRequest::Message: + { + OutputBuffer *buf; + if (OutputBuffer::Allocate(buf)) + { + MessageType type; + if (transfer.ReadMessage(type, buf)) + { + // FIXME Push flag is not supported yet + reprap.GetPlatform().Message(type, buf); + } + else + { + // Not enough memory for reading the whole message, try again later + OutputBuffer::ReleaseAll(buf); + packetAcknowledged = false; + } + } + break; + } + + // Macro file has been started + case SbcRequest::MacroStarted: + { + const GCodeChannel channel = transfer.ReadCodeChannel(); + if (channel.IsValid()) + { + GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); + if (gb->IsWaitingForMacro() && !gb->IsMacroRequestPending()) + { + // File exists and is open, but no code has arrived yet + gb->ResolveMacroRequest(false, false); +#ifdef TRACK_FILE_CODES + if (channel == GCodeChannel::File) + { + fileMacrosRunning++; + } +#endif + } + else if (channel != GCodeChannel::Daemon) + { + reprap.GetPlatform().MessageF(WarningMessage, "Macro file has been started on channel %s but none was requested\n", channel.ToString()); + } + else + { + // dameon.g is running, now the OM may report the file is being executed + reprap.InputsUpdated(); + } + } + else + { + REPORT_INTERNAL_ERROR; + } + break; + } + + // Invalidate all files and codes on a given channel + case SbcRequest::InvalidateChannel: + { + const GCodeChannel channel = transfer.ReadCodeChannel(); + if (channel.IsValid()) + { + GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); + if (gb->IsWaitingForMacro()) + { + gb->ResolveMacroRequest(true, false); + } + + MutexLocker locker(gb->mutex, SbcYieldTimeout); + if (locker.IsAcquired()) + { + // Note that we do not call StopPrint here or set any other variables; DSF already does that + gb->AbortFile(true, false); + InvalidateBufferedCodes(channel); + } + else + { + packetAcknowledged = false; + } + } + else + { + REPORT_INTERNAL_ERROR; + } + break; + } + + // Set the content of a variable + case SbcRequest::SetVariable: + { + bool createVariable; + String<MaxVariableNameLength> varName; + String<GCODE_LENGTH> expression; + const GCodeChannel channel = transfer.ReadSetVariable(createVariable, varName.GetRef(), expression.GetRef()); + + // Make sure we can access the gb safely... + if (!channel.IsValid()) + { + REPORT_INTERNAL_ERROR; + break; + } + + GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); + MutexLocker lock(gb->mutex, SbcYieldTimeout); + if (!lock.IsAcquired()) + { + packetAcknowledged = false; + break; + } + + // Get the variable set + const bool isGlobal = StringStartsWith(varName.c_str(), "global."); + if (!isGlobal && !StringStartsWith(varName.c_str(), "var.")) + { + packetAcknowledged = transfer.WriteSetVariableError(varName.c_str(), "expected a global or local variable"); + break; + } + WriteLockedPointer<VariableSet> vset = (isGlobal) ? reprap.GetGlobalVariablesForWriting() : WriteLockedPointer<VariableSet>(nullptr, &gb->GetVariables()); + + // Check if the variable is valid + const char *shortVarName = varName.c_str() + strlen(isGlobal ? "global." : "var."); + Variable * const v = vset->Lookup(shortVarName); + if (createVariable && v != nullptr) + { + // For now we don't allow an existing variable to be reassigned using a 'var' or 'global' statement. We may need to allow it for 'global' statements. + // Save memory by re-using 'expression' to capture the error message + expression.printf("variable '%s' already exists", varName.c_str()); + packetAcknowledged = transfer.WriteSetVariableError(varName.c_str(), expression.c_str()); + break; + } + if (!createVariable && v == nullptr) + { + // Save memory by re-using 'expression' to capture the error message + expression.printf("unknown variable '%s'", varName.c_str()); + packetAcknowledged = transfer.WriteSetVariableError(varName.c_str(), expression.c_str()); + break; + } + + // Evaluate the expression and assign it + try + { + ExpressionParser parser(*gb, expression.c_str(), expression.c_str() + expression.strlen()); + ExpressionValue ev = parser.Parse(); + if (v == nullptr) + { + // DSF doesn't provide indent values but instructs RRF to delete local variables when the current block ends + vset->InsertNew(shortVarName, ev, 0); + } + else + { + v->Assign(ev); + } + + transfer.WriteSetVariableResult(varName.c_str(), ev); + if (isGlobal) + { + reprap.GlobalUpdated(); + } + } + catch (const GCodeException& e) + { + // Get the error message and send it back to DSF + // Save memory by re-using 'expression' to capture the error message + e.GetMessage(expression.GetRef(), nullptr); + packetAcknowledged = transfer.WriteSetVariableError(varName.c_str(), expression.c_str()); + } + break; + } + + // Delete a local variable + case SbcRequest::DeleteLocalVariable: + { + String<MaxVariableNameLength> varName; + const GCodeChannel channel = transfer.ReadDeleteLocalVariable(varName.GetRef()); + + // Make sure we can access the gb safely... + if (!channel.IsValid()) + { + REPORT_INTERNAL_ERROR; + break; + } + + GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); + MutexLocker lock(gb->mutex, SbcYieldTimeout); + if (!lock.IsAcquired()) + { + packetAcknowledged = false; + break; + } + + // Try to delete the variable again + WriteLockedPointer<VariableSet> vset = WriteLockedPointer<VariableSet>(nullptr, &gb->GetVariables()); + vset.Ptr()->Delete(varName.c_str()); + break; + } + + // Result of a file exists check + case SbcRequest::CheckFileExistsResult: + if (fileOperation == FileOperation::checkFileExists) + { + fileSuccess = transfer.ReadBoolean(); + fileOperation = FileOperation::none; + fileSemaphore.Give(); + } + else + { + REPORT_INTERNAL_ERROR; + } + break; + + // Result of a deletion request + case SbcRequest::FileDeleteResult: + if (fileOperation == FileOperation::deleteFileOrDirectory) + { + fileSuccess = transfer.ReadBoolean(); + fileOperation = FileOperation::none; + fileSemaphore.Give(); + } + else + { + REPORT_INTERNAL_ERROR; + } + break; + + // Result of a file open request + case SbcRequest::OpenFileResult: + if (fileOperation == FileOperation::openRead || + fileOperation == FileOperation::openWrite || + fileOperation == FileOperation::openAppend) + { + fileHandle = transfer.ReadOpenFileResult(fileOffset); + fileSuccess = (fileHandle != noFileHandle); + fileOperation = FileOperation::none; + fileSemaphore.Give(); + } + else + { + REPORT_INTERNAL_ERROR; + } + break; + + // Result of a file read request + case SbcRequest::FileReadResult: + if (fileOperation == FileOperation::read) + { + int bytesRead = transfer.ReadFileData(fileReadBuffer, fileBufferLength); + fileSuccess = bytesRead >= 0; + fileOffset = fileSuccess ? bytesRead : 0; + fileOperation = FileOperation::none; + fileSemaphore.Give(); + } + else + { + REPORT_INTERNAL_ERROR; + } + break; + + // Result of a file write request + case SbcRequest::FileWriteResult: + if (fileOperation == FileOperation::write) + { + fileSuccess = transfer.ReadBoolean(); + if (!fileSuccess || fileBufferLength == 0) + { + fileOperationPending = false; + fileOperation = FileOperation::none; + fileSemaphore.Give(); + } + } + else + { + REPORT_INTERNAL_ERROR; + } + break; + + // Result of a file seek request + case SbcRequest::FileSeekResult: + if (fileOperation == FileOperation::seek) + { + fileSuccess = transfer.ReadBoolean(); + fileOperation = FileOperation::none; + fileSemaphore.Give(); + } + else + { + REPORT_INTERNAL_ERROR; + } + break; + + // Result of a file seek request + case SbcRequest::FileTruncateResult: + if (fileOperation == FileOperation::truncate) + { + fileSuccess = transfer.ReadBoolean(); + fileOperation = FileOperation::none; + fileSemaphore.Give(); + } + else + { + REPORT_INTERNAL_ERROR; + } + break; + + // Invalid request + default: + REPORT_INTERNAL_ERROR; + break; + } + + // Request the packet again if no response could be sent back + if (!packetAcknowledged) + { + transfer.ResendPacket(packet); + } + } + + // Check if we can wait a short moment to reduce CPU load on the SBC + if (!skipNextDelay && numEvents < numMaxEvents && !waitingForFileChunk && + !fileOperationPending && fileOperation == FileOperation::none) + { + delaying = true; + if (!TaskBase::Take(MassStorage::AnyFileOpen() ? maxFileOpenDelay : maxDelayBetweenTransfers)) + { + delaying = false; + } + } + numEvents = 0; + skipNextDelay = false; + + // Send code replies and generic messages + if (!gcodeReply.IsEmpty()) + { + MutexLocker lock(gcodeReplyMutex); + while (!gcodeReply.IsEmpty()) + { + const MessageType type = gcodeReply.GetFirstItemType(); + OutputBuffer *buffer = gcodeReply.GetFirstItem(); // this may be null + if (!transfer.WriteCodeReply(type, buffer)) // this handles the null case too + { + break; + } + gcodeReply.SetFirstItem(buffer); // this does a pop if buffer is null + } + } + + // Notify DSF about the available buffer space + if (!codeBufferAvailable || sendBufferUpdate) + { + TaskCriticalSectionLocker locker; + + const uint16_t bufferSpace = (txEnd == 0) ? max<uint16_t>(rxPointer, SpiCodeBufferSize - txPointer) : rxPointer - txPointer; + sendBufferUpdate = !transfer.WriteCodeBufferUpdate(bufferSpace); + } + + // Get another chunk of the file being requested + if (waitingForFileChunk && + !fileChunkRequestSent && transfer.WriteFileChunkRequest(requestedFileName.c_str(), requestedFileOffset, requestedFileLength)) + { + fileChunkRequestSent = true; + } + + // Perform the next file operation if requested + if (fileOperationPending) + { + switch (fileOperation) + { + case FileOperation::checkFileExists: + fileOperationPending = !transfer.WriteCheckFileExists(filePath); + break; + + case FileOperation::deleteFileOrDirectory: + fileOperationPending = !transfer.WriteDeleteFileOrDirectory(filePath); + break; + + case FileOperation::openRead: + case FileOperation::openWrite: + case FileOperation::openAppend: + fileOperationPending = !transfer.WriteOpenFile(filePath, fileOperation == FileOperation::openWrite || fileOperation == FileOperation::openAppend, fileOperation == FileOperation::openAppend, filePreAllocSize); + break; + + case FileOperation::read: + fileOperationPending = !transfer.WriteReadFile(fileHandle, fileBufferLength); + break; + + case FileOperation::write: + { + size_t bytesNotWritten = fileBufferLength; + if (transfer.WriteFileData(fileHandle, fileWriteBuffer, fileBufferLength)) + { + fileWriteBuffer += bytesNotWritten - fileBufferLength; + if (fileBufferLength == 0) + { + fileOperationPending = false; + } + } + break; + } + + case FileOperation::seek: + fileOperationPending = !transfer.WriteSeekFile(fileHandle, fileOffset); + break; + + case FileOperation::truncate: + fileOperationPending = !transfer.WriteTruncateFile(fileHandle); + break; + + case FileOperation::close: + fileOperationPending = !transfer.WriteCloseFile(fileHandle); + if (!fileOperationPending) + { + // Close requests don't get a result back, so they can be resolved as soon as they are sent to the SBC + fileOperation = FileOperation::none; + fileSemaphore.Give(); + } + break; + + default: + REPORT_INTERNAL_ERROR; + break; + } + } + + // Deal with code channel requests + for (size_t i = 0; i < NumGCodeChannels; i++) + { + const GCodeChannel channel(i); + GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); + + // Invalidate buffered codes if required + if (gb->IsInvalidated()) + { + InvalidateBufferedCodes(gb->GetChannel()); + gb->Invalidate(false); + } + + // Deal with macro files being closed + if (gb->IsMacroFileClosed() && transfer.WriteMacroFileClosed(channel)) + { + // Note this is only sent when a macro file has finished successfully + gb->MacroFileClosedSent(); + } + + // Handle blocking macro requests + if (gb->IsWaitingForMacro() && gb->IsMacroRequestPending()) + { + const char * const requestedMacroFile = gb->GetRequestedMacroFile(); + bool fromCode = gb->IsMacroStartedByCode(); + if (transfer.WriteMacroRequest(channel, requestedMacroFile, fromCode)) + { + if (reprap.Debug(moduleSbcInterface)) + { + debugPrintf("Requesting macro file '%s' (fromCode: %s)\n", requestedMacroFile, fromCode ? "true" : "false"); + } + gb->MacroRequestSent(); + gb->Invalidate(); + } + } + + // Deal with other requests unless we are still waiting in a semaphore + if (!gb->IsWaitingForMacro()) + { + MutexLocker gbLock(gb->mutex, SbcYieldTimeout); + if (gbLock.IsAcquired()) + { + if (gb->GetChannel() != GCodeChannel::Daemon) + { + skipNextDelay |= gb->IsMacroRequestPending() || gb->HasJustStartedMacro(); + } + + // Handle file abort requests + if (gb->IsAbortRequested() && transfer.WriteAbortFileRequest(channel, gb->IsAbortAllRequested())) + { +#ifdef TRACK_FILE_CODES + if (channel == GCodeChannel::File) + { + if (gb->IsAbortAllRequested()) + { + fileCodesRead = fileCodesHandled = fileMacrosRunning = fileMacrosClosing = 0; + } + else + { + fileMacrosClosing++; + } + } +#endif + gb->FileAbortSent(); + gb->Invalidate(); + } + + // Handle blocking messages and their results + if (gb->LatestMachineState().waitingForAcknowledgement && gb->IsMessagePromptPending() && + transfer.WriteWaitForAcknowledgement(channel)) + { + gb->MessagePromptSent(); + gb->Invalidate(); + } + else if (gb->IsMessageAcknowledged() && transfer.WriteMessageAcknowledged(channel)) + { + // Note this is only sent when a message was acknowledged in a regular way (i.e. by M292) + gb->MessageAcknowledgementSent(); + } + + // Handle non-blocking macro requests (e.g. daemon.g) + if (gb->IsMacroRequestPending()) + { + const char * const requestedMacroFile = gb->GetRequestedMacroFile(); + bool fromCode = gb->IsMacroStartedByCode(); + if (transfer.WriteMacroRequest(channel, requestedMacroFile, fromCode)) + { + if (reprap.Debug(moduleSbcInterface)) + { + debugPrintf("Requesting non-blocking macro file '%s' (fromCode: %s)\n", requestedMacroFile, fromCode ? "true" : "false"); + } + gb->MacroRequestSent(); + gb->Invalidate(); + } + } + + // Send pending firmware codes + if (gb->IsSendRequested() && transfer.WriteDoCode(channel, gb->DataStart(), gb->DataLength())) + { + gb->SetFinished(true); + } + } + } + } + + // Send pause notification on demand + if (reportPause && transfer.WritePrintPaused(pauseFilePosition, pauseReason)) + { + reportPause = false; + } +} + +[[noreturn]] void SbcInterface::ReceiveAndStartIap(const char *iapChunk, size_t length) noexcept +{ + char *iapWritePointer = reinterpret_cast<char *>(IAP_IMAGE_START); + for(;;) + { + // Write the next IAP chunk + if (iapChunk != nullptr) + { + uint32_t *dst = reinterpret_cast<uint32_t *>(iapWritePointer); + const uint32_t *src = reinterpret_cast<const uint32_t *>(iapChunk); + memcpyu32(dst, src, length / sizeof(uint32_t)); + iapWritePointer += length; + iapChunk = nullptr; + } + + // Get the next IAP chunk + transfer.StartNextTransfer(); + bool transferComplete = false; + do + { + switch (transfer.DoTransfer()) + { +#if SAME5x + case TransferState::connectionTimeout: +#endif + case TransferState::connectionReset: + // Perform a firmware reset, we're in an unsafe state to resume regular operation + SoftwareReset(SoftwareResetReason::user); + break; + case TransferState::finished: + transferComplete = true; + break; + default: + // do nothing + break; + } + } + while (!transferComplete); + + // Process only IAP-related packets + for (size_t i = 0; i < transfer.PacketsToRead(); i++) + { + const PacketHeader * const packet = transfer.ReadPacket(); + switch ((SbcRequest)packet->request) + { + case SbcRequest::WriteIap: // Write another IAP chunk. It's always bound on a 4-byte boundary + { + iapChunk = transfer.ReadData(packet->length); + length = packet->length; + break; + } + case SbcRequest::StartIap: // Start the IAP binary + reprap.StartIap(nullptr); + break; + default: // Other packet types are not supported while IAP is being written + // do nothing + break; + } + } + } +} + +void SbcInterface::InvalidateResources() noexcept +{ + rxPointer = txPointer = txEnd = 0; + sendBufferUpdate = true; + + if (!requestedFileName.IsEmpty()) + { + requestedFileDataLength = -1; + requestedFileSemaphore.Give(); + } + + if (fileOperation != FileOperation::none) + { + fileOperation = FileOperation::none; + fileSemaphore.Give(); + } + MassStorage::InvalidateAllFiles(); + + // Don't cache any messages if they cannot be sent + { + MutexLocker lock(gcodeReplyMutex); + gcodeReply.ReleaseAll(); + } + + // Close all open G-code files + for (size_t i = 0; i < NumGCodeChannels; i++) + { + GCodeBuffer *gb = reprap.GetGCodes().GetGCodeBuffer(GCodeChannel(i)); + if (gb->IsWaitingForMacro()) + { + gb->ResolveMacroRequest(true, false); + } + + MutexLocker locker(gb->mutex); + if (gb->IsMacroRequestPending()) + { + gb->MacroRequestSent(); + } + gb->AbortFile(true, false); + gb->MessageAcknowledged(true); + } + + // Abort the print (if applicable) + printAborted = true; + + // Turn off all the heaters + reprap.GetHeat().SwitchOffAll(true); +} + +void SbcInterface::Diagnostics(MessageType mtype) noexcept +{ + reprap.GetPlatform().Message(mtype, "=== SBC interface ===\n"); + transfer.Diagnostics(mtype); + reprap.GetPlatform().MessageF(mtype, "State: %d, disconnects: %" PRIu32 ", timeouts: %" PRIu32 ", IAP RAM available 0x%05" PRIx32 "\n", (int)state, numDisconnects, numTimeouts, iapRamAvailable); + reprap.GetPlatform().MessageF(mtype, "Buffer RX/TX: %d/%d-%d\n", (int)rxPointer, (int)txPointer, (int)txEnd); +#ifdef TRACK_FILE_CODES + reprap.GetPlatform().MessageF(mtype, "File codes read/handled: %d/%d, file macros open/closing: %d %d\n", (int)fileCodesRead, (int)fileCodesHandled, (int)fileMacrosRunning, (int)fileMacrosClosing); +#endif +} + +GCodeResult SbcInterface::HandleM576(GCodeBuffer& gb, const StringRef& reply) noexcept +{ + bool seen = false; + + if (gb.Seen('S')) + { + uint32_t sParam = gb.GetUIValue(); + if (sParam > SpiConnectionTimeout) + { + reply.printf("SPI transfer delay must not exceed %" PRIu32 "ms", SpiConnectionTimeout); + return GCodeResult::error; + } + maxDelayBetweenTransfers = sParam; + seen = true; + } + + if (gb.Seen('F')) + { + uint32_t fParam = gb.GetUIValue(); + if (fParam > SpiConnectionTimeout) + { + reply.printf("SPI transfer delay must not exceed %" PRIu32 "ms", SpiConnectionTimeout); + return GCodeResult::error; + } + maxFileOpenDelay = fParam; + seen = true; + } + + if (gb.Seen('P')) + { + numMaxEvents = gb.GetUIValue(); + seen = true; + } + + if (!seen) + { + reply.printf("Max transfer delay %" PRIu32 "ms, max number of events during delays: %" PRIu32, maxDelayBetweenTransfers, numMaxEvents); + } + return GCodeResult::ok; +} + +bool SbcInterface::FillBuffer(GCodeBuffer &gb) noexcept +{ + if (gb.IsInvalidated() || gb.IsMacroFileClosed() || gb.IsMessageAcknowledged() || + gb.IsAbortRequested() || (reportPause && gb.GetChannel() == GCodeChannel::File) || + (gb.LatestMachineState().waitingForAcknowledgement && gb.IsMessagePromptPending())) + { + // Don't process codes that are supposed to be suspended... + return false; + } + + bool gotCommand = false; + { + //TODO can we take the lock inside the loop body instead, if we re-read readPointer and writePointer after taking it? + TaskCriticalSectionLocker locker; + if (rxPointer != txPointer || txEnd != 0) + { + bool updateRxPointer = true; + uint16_t readPointer = rxPointer; + do + { + BufferedCodeHeader *bufHeader = reinterpret_cast<BufferedCodeHeader*>(codeBuffer + readPointer); + readPointer += sizeof(BufferedCodeHeader); + const CodeHeader *codeHeader = reinterpret_cast<const CodeHeader*>(codeBuffer + readPointer); + readPointer += bufHeader->length; + + RRF_ASSERT(bufHeader->length > 0); + RRF_ASSERT(readPointer <= SpiCodeBufferSize); + + if (bufHeader->isPending) + { + if (gb.GetChannel().RawValue() == codeHeader->channel) + { +#ifdef TRACK_FILE_CODES + if (gb.GetChannel() == GCodeChannel::File && gb.GetCommandLetter() != 'Q') + { + fileMacrosRunning -= fileMacrosClosing; + fileMacrosClosing = 0; + if (fileCodesRead > fileCodesHandled + fileMacrosRunning) + { + // Note that we cannot use MessageF here because the task scheduler is suspended + OutputBuffer *buf; + if (OutputBuffer::Allocate(buf)) + { + String<SHORT_GCODE_LENGTH> codeString; + gb.PrintCommand(codeString.GetRef()); + buf->printf("Code %s did not return a code result, delta %d, running macros %d\n", codeString.c_str(), fileCodesRead - fileCodesHandled - fileMacrosRunning, fileMacrosRunning); + gcodeReply.Push(buf, WarningMessage); + } + fileCodesRead = fileCodesHandled - fileMacrosRunning; + } + fileCodesRead++; + } +#endif + + // Process the next binary G-code + gb.PutBinary(reinterpret_cast<const uint32_t *>(codeHeader), bufHeader->length / sizeof(uint32_t)); + bufHeader->isPending = false; + + // Check if we can reset the ring buffer pointers + if (updateRxPointer) + { + sendBufferUpdate = true; + if (readPointer == txPointer && txEnd == 0) + { + // Buffer completely read, reset RX/TX pointers + rxPointer = txPointer = 0; + } + else if (readPointer == txEnd) + { + // Read last code before overlapping, restart from the beginning + rxPointer = txEnd = 0; + } + else + { + // Code has been read, move on to the next one + rxPointer = readPointer; + } + } + + gotCommand = true; + break; + } + updateRxPointer = false; + } + + if (readPointer == txEnd) + { + if (updateRxPointer) + { + // Skipped non-pending codes, restart from the beginning + rxPointer = txEnd = 0; + } + + // About to overlap, continue from the start + readPointer = 0; + } + } while (readPointer != txPointer); + } + } + + if (gotCommand) + { + gb.DecodeCommand(); + return true; + } + return false; +} + +bool SbcInterface::FileExists(const char *filename) noexcept +{ + // Don't do anything if the SBC is not connected + if (!IsConnected()) + { + return false; + } + + // Set up the request content + MutexLocker locker(fileMutex); + filePath = filename; + fileOperation = FileOperation::checkFileExists; + fileOperationPending = true; + + // Let the SBC task process this request as quickly as possible + if (delaying) + { + delaying = false; + sbcTask->Give(); + } + fileSemaphore.Take(); + + // Return the result + return fileSuccess; +} + +bool SbcInterface::DeleteFileOrDirectory(const char *fileOrDirectory) noexcept +{ + // Don't do anything if the SBC is not connected + if (!IsConnected()) + { + return false; + } + + // Set up the request content + MutexLocker locker(fileMutex); + filePath = fileOrDirectory; + fileOperation = FileOperation::deleteFileOrDirectory; + fileOperationPending = true; + + // Let the SBC task process this request as quickly as possible + if (delaying) + { + delaying = false; + sbcTask->Give(); + } + fileSemaphore.Take(); + + // Return the result + return fileSuccess; +} + +FileHandle SbcInterface::OpenFile(const char *filename, OpenMode mode, FilePosition& fileLength, uint32_t preAllocSize) noexcept +{ + // Don't do anything if the SBC is not connected + if (!IsConnected()) + { + return false; + } + + // Set up the request content + MutexLocker locker(fileMutex); + filePath = filename; + filePreAllocSize = preAllocSize; + switch (mode) + { + case OpenMode::read: + fileOperation = FileOperation::openRead; + break; + + case OpenMode::write: + case OpenMode::writeWithCrc: + fileOperation = FileOperation::openWrite; + break; + + case OpenMode::append: + fileOperation = FileOperation::openAppend; + break; + + default: + filePath = nullptr; + REPORT_INTERNAL_ERROR; + break; + } + fileOperationPending = true; + + // Let the SBC task process this request as quickly as possible + if (delaying) + { + delaying = false; + sbcTask->Give(); + } + fileSemaphore.Take(); + + // Update the file length and return the handle + fileLength = fileOffset; + return fileHandle; +} + +int SbcInterface::ReadFile(FileHandle handle, char *buffer, size_t bufferLength) noexcept +{ + // Don't do anything if the SBC is not connected + if (!IsConnected()) + { + return false; + } + + // Set up the request content + MutexLocker locker(fileMutex); + fileHandle = handle; + fileReadBuffer = buffer; + fileBufferLength = bufferLength; + fileOperation = FileOperation::read; + fileOperationPending = true; + + // Let the SBC task process this request as quickly as possible + if (delaying) + { + delaying = false; + sbcTask->Give(); + } + fileSemaphore.Take(); +; + + // Return the number of bytes read + return fileSuccess ? (int)fileOffset : -1; +} + +bool SbcInterface::WriteFile(FileHandle handle, const char *buffer, size_t bufferLength) noexcept +{ + // Don't do anything if the SBC is not connected + if (!IsConnected()) + { + return false; + } + + // Set up the request content + MutexLocker locker(fileMutex); + fileHandle = handle; + fileWriteBuffer = buffer; + fileBufferLength = bufferLength; + fileOperation = FileOperation::write; + fileOperationPending = true; + + // Let the SBC task process this request as quickly as possible + if (delaying) + { + delaying = false; + sbcTask->Give(); + } + fileSemaphore.Take(); + + // Return the result + return fileSuccess; +} + +bool SbcInterface::SeekFile(FileHandle handle, FilePosition offset) noexcept +{ + // Don't do anything if the SBC is not connected + if (!IsConnected()) + { + return false; + } + + // Set up the request content + MutexLocker locker(fileMutex); + fileHandle = handle; + fileOffset = offset; + fileOperation = FileOperation::seek; + fileOperationPending = true; + + // Let the SBC task process this request as quickly as possible + if (delaying) + { + delaying = false; + sbcTask->Give(); + } + fileSemaphore.Take(); + + // Return the result + return fileSuccess; +} + +bool SbcInterface::TruncateFile(FileHandle handle) noexcept +{ + // Don't do anything if the SBC is not connected + if (!IsConnected()) + { + return false; + } + + // Set up the request content + MutexLocker locker(fileMutex); + fileHandle = handle; + fileOperation = FileOperation::truncate; + fileOperationPending = true; + + // Let the SBC task process this request as quickly as possible + if (delaying) + { + delaying = false; + sbcTask->Give(); + } + fileSemaphore.Take(); + + // Return the result + return fileSuccess; +} + +void SbcInterface::CloseFile(FileHandle handle) noexcept +{ + // Don't do anything if the SBC is not connected + if (!IsConnected()) + { + return; + } + + // Set up the request content + MutexLocker locker(fileMutex); + fileHandle = handle; + fileOperation = FileOperation::close; + fileOperationPending = true; + + // Let the SBC task process this request as quickly as possible + if (delaying) + { + delaying = false; + sbcTask->Give(); + } + fileSemaphore.Take(); +} + +void SbcInterface::HandleGCodeReply(MessageType mt, const char *reply) noexcept +{ + if (!IsConnected()) + { + return; + } + +#ifdef TRACK_FILE_CODES + if ((mt & (1 << GCodeChannel::File)) != 0) + { + fileCodesHandled++; + } +#endif + + MutexLocker lock(gcodeReplyMutex); + OutputBuffer *buffer = gcodeReply.GetLastItem(); + if (buffer != nullptr && mt == gcodeReply.GetLastItemType() && (mt & PushFlag) != 0 && !buffer->IsReferenced()) + { + // Try to save some space by combining segments that have the Push flag set + buffer->cat(reply); + } + else if (reply[0] != 0 && OutputBuffer::Allocate(buffer)) + { + // Attempt to allocate one G-code buffer per non-empty output message + buffer->cat(reply); + gcodeReply.Push(buffer, mt); + } + else + { + // Store nullptr to indicate an empty response. This way many OutputBuffer references can be saved + gcodeReply.Push(nullptr, mt); + } + EventOccurred(); +} + +void SbcInterface::HandleGCodeReply(MessageType mt, OutputBuffer *buffer) noexcept +{ + if (!IsConnected()) + { + OutputBuffer::ReleaseAll(buffer); + return; + } + +#ifdef TRACK_FILE_CODES + if ((mt & (1 << GCodeChannel::File)) != 0) + { + fileCodesHandled++; + } +#endif + + MutexLocker lock(gcodeReplyMutex); + gcodeReply.Push(buffer, mt); + EventOccurred(); +} + +// Read a file chunk from the SBC. When a response has been received, the current task is woken up again. +// It changes bufferLength to the number of received bytes +// This method returns true on success and false if an error occurred (e.g. file not found) +bool SbcInterface::GetFileChunk(const char *filename, uint32_t offset, char *buffer, uint32_t& bufferLength, uint32_t& fileLength) noexcept +{ + if (waitingForFileChunk) + { + reprap.GetPlatform().Message(ErrorMessage, "Trying to request a file chunk from two independent tasks\n"); + bufferLength = fileLength = 0; + return false; + } + + fileChunkRequestSent = false; + requestedFileName.copy(filename); + requestedFileLength = bufferLength; + requestedFileOffset = offset; + requestedFileBuffer = buffer; + + waitingForFileChunk = true; + requestedFileSemaphore.Take(); + + waitingForFileChunk = false; + if (requestedFileDataLength < 0) + { + bufferLength = fileLength = 0; + return false; + } + bufferLength = requestedFileDataLength; + fileLength = requestedFileLength; + return true; +} + +void SbcInterface::EventOccurred(bool timeCritical) noexcept +{ + if (!IsConnected()) + { + return; + } + + // Increment the number of events + if (timeCritical) + { + numEvents = numMaxEvents; + } + else + { + numEvents++; + } + + // Stop delaying if the next transfer is time-critical + if (delaying && numEvents >= numMaxEvents) + { + delaying = false; + sbcTask->Give(); + } +} + +void SbcInterface::InvalidateBufferedCodes(GCodeChannel channel) noexcept +{ + TaskCriticalSectionLocker locker; + if (rxPointer != txPointer || txEnd != 0) + { + bool updateRxPointer = true; + uint16_t readPointer = rxPointer; + do + { + BufferedCodeHeader *bufHeader = reinterpret_cast<BufferedCodeHeader *>(codeBuffer + readPointer); + if (bufHeader->isPending) + { + const CodeHeader *codeHeader = reinterpret_cast<const CodeHeader*>(codeBuffer + readPointer + sizeof(BufferedCodeHeader)); + if (codeHeader->channel == channel.RawValue()) + { + bufHeader->isPending = false; + } + else + { + updateRxPointer = false; + } + } + readPointer += sizeof(BufferedCodeHeader) + bufHeader->length; + + if (updateRxPointer) + { + sendBufferUpdate = true; + if (readPointer == txPointer && txEnd == 0) + { + // Buffer is empty again, reset the pointers + rxPointer = txPointer = 0; + break; + } + else if (readPointer == txEnd) + { + // Invalidated last code before overlapping, continue from the beginning + readPointer = 0; + rxPointer = txEnd = 0; + } + else + { + // Invalidated next code + rxPointer = readPointer; + } + } + else if (readPointer == txEnd) + { + // About to overlap, continue from the start + readPointer = 0; + } + } while (readPointer != txPointer); + } +} + +#endif diff --git a/src/Linux/LinuxInterface.h b/src/SBC/SbcInterface.h index 6629de24..7e0c7805 100644 --- a/src/Linux/LinuxInterface.h +++ b/src/SBC/SbcInterface.h @@ -1,23 +1,23 @@ /* - * LinuxInterface.h + * SbcInterface.h * * Created on: 29 Mar 2019 * Authors: Christian */ -#ifndef SRC_LINUX_LINUXINTERFACE_H_ -#define SRC_LINUX_LINUXINTERFACE_H_ +#ifndef SRC_SBC_SBCINTERFACE_H_ +#define SRC_SBC_SBCINTERFACE_H_ #include <RepRapFirmware.h> -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE #include "RTOSIface/RTOSIface.h" #include "GCodes/GCodes.h" #include "GCodes/GCodeChannel.h" #include "GCodes/GCodeFileInfo.h" -#include "LinuxMessageFormats.h" +#include "SbcMessageFormats.h" #include "DataTransfer.h" class Platform; @@ -30,18 +30,17 @@ class OutputStack; //#define TRACK_FILE_CODES // Uncomment this to enable code <-> code reply tracking for the file G-code channel // G-Code input class for an SPI channel -class LinuxInterface +class SbcInterface { public: - LinuxInterface() noexcept; + SbcInterface() noexcept; - // The Init method must be called prior to calling any of the other methods. Use reprap.UsingLinuxInterface() to guard calls to other members. + // The Init method must be called prior to calling any of the other methods. Use reprap.UsingSbcInterface() to guard calls to other members. // OTOH, calling Init when we don't have a SBC connected may cause problems due to noise pickup on the SPI CS and clock inputs void Init() noexcept; void Spin() noexcept; // Only called in standalone mode by the main loop [[noreturn]] void TaskLoop() noexcept; void Diagnostics(MessageType mtype) noexcept; - bool IsWritingIap() const noexcept { return writingIap; } bool IsConnected() const noexcept { return isConnected; } void EventOccurred(bool timeCritical = false) noexcept; // Called when a new event has happened. It can optionally start off a new transfer immediately @@ -71,10 +70,12 @@ public: private: DataTransfer transfer; - bool isConnected; + volatile bool isConnected; + TransferState state; uint32_t numDisconnects, numTimeouts; uint32_t maxDelayBetweenTransfers, maxFileOpenDelay, numMaxEvents; + bool skipNextDelay; volatile bool delaying; volatile uint32_t numEvents; @@ -87,8 +88,6 @@ private: volatile uint16_t rxPointer, txPointer, txEnd; volatile bool sendBufferUpdate; - bool writingIap; - uint32_t iapWritePointer; uint32_t iapRamAvailable; // must be at least 32Kb otherwise the SPI IAP can't work // Data needed when a CAN expansion board requests a firmware file chunk @@ -130,16 +129,19 @@ private: FilePosition fileOffset; static volatile OutputStack gcodeReply; - static Mutex gcodeReplyMutex; // static so that the LinuxInterface is safe to delete even is the mutex is linked into the mutex chain or is in use + static Mutex gcodeReplyMutex; // static so that the SbcInterface is safe to delete even is the mutex is linked into the mutex chain or is in use #ifdef TRACK_FILE_CODES volatile size_t fileCodesRead, fileCodesHandled, fileMacrosRunning, fileMacrosClosing; #endif - void InvalidateBufferedCodes(GCodeChannel channel) noexcept; // Invalidate every buffered G-code of the corresponding channel from the buffer ring + void ExchangeData() noexcept; // Exchange data between RRF and the SBC + [[noreturn]] void ReceiveAndStartIap(const char *iapChunk, size_t length) noexcept; // Receive and start the IAP binary + void InvalidateResources() noexcept; // Invalidate local resources on connection errors + void InvalidateBufferedCodes(GCodeChannel channel) noexcept; // Invalidate every buffered G-code of the corresponding channel from the buffer ring }; -inline void LinuxInterface::SetPauseReason(FilePosition position, PrintPausedReason reason) noexcept +inline void SbcInterface::SetPauseReason(FilePosition position, PrintPausedReason reason) noexcept { TaskCriticalSectionLocker locker; pauseFilePosition = position; @@ -147,7 +149,7 @@ inline void LinuxInterface::SetPauseReason(FilePosition position, PrintPausedRea reportPauseWritten = false; } -inline void LinuxInterface::SetEmergencyPauseReason(FilePosition position, PrintPausedReason reason) noexcept +inline void SbcInterface::SetEmergencyPauseReason(FilePosition position, PrintPausedReason reason) noexcept { pauseFilePosition = position; pauseReason = reason; @@ -155,12 +157,12 @@ inline void LinuxInterface::SetEmergencyPauseReason(FilePosition position, Print reportPause = true; } -inline void LinuxInterface::ReportPause() noexcept +inline void SbcInterface::ReportPause() noexcept { reportPause = true; } -inline bool LinuxInterface::IsPrintAborted() noexcept +inline bool SbcInterface::IsPrintAborted() noexcept { TaskCriticalSectionLocker locker; if (printAborted) diff --git a/src/Linux/LinuxMessageFormats.h b/src/SBC/SbcMessageFormats.h index 725724f9..11991fb7 100644 --- a/src/Linux/LinuxMessageFormats.h +++ b/src/SBC/SbcMessageFormats.h @@ -1,14 +1,14 @@ /* - * MessageFormats.h + * SbcMessageFormats.h * * Created on: 29 Mar 2019 * Author: Christian */ -#ifndef SRC_LINUX_MESSAGEFORMATS_H_ -#define SRC_LINUX_MESSAGEFORMATS_H_ +#ifndef SRC_SBC_MESSAGEFORMATS_H_ +#define SRC_SBC_MESSAGEFORMATS_H_ -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE #include <cstddef> #include <cstdint> @@ -16,14 +16,14 @@ #include <RepRapFirmware.h> -constexpr uint8_t LinuxFormatCode = 0x5F; // standard format code for RRF SPI protocol -constexpr uint8_t LinuxFormatCodeStandalone = 0x60; // used to indicate that RRF is running in stand-alone mode +constexpr uint8_t SbcFormatCode = 0x5F; // standard format code for RRF SPI protocol +constexpr uint8_t SbcFormatCodeStandalone = 0x60; // used to indicate that RRF is running in stand-alone mode constexpr uint8_t InvalidFormatCode = 0xC9; // must be different from any other format code -constexpr uint16_t LinuxProtocolVersion = 6; +constexpr uint16_t SbcProtocolVersion = 6; -constexpr size_t LinuxTransferBufferSize = 8192; // maximum length of a data transfer. Must be a multiple of 4 and kept in sync with Duet Control Server! -static_assert(LinuxTransferBufferSize % sizeof(uint32_t) == 0, "LinuxTransferBufferSize must be a whole number of dwords"); +constexpr size_t SbcTransferBufferSize = 8192; // maximum length of a data transfer. Must be a multiple of 4 and kept in sync with Duet Control Server! +static_assert(SbcTransferBufferSize % sizeof(uint32_t) == 0, "SbcTransferBufferSize must be a whole number of dwords"); constexpr size_t MaxCodeBufferSize = 256; // maximum length of a G/M/T-code in binary encoding static_assert(MaxCodeBufferSize % sizeof(uint32_t) == 0, "MaxCodeBufferSize must be a whole number of dwords"); @@ -34,6 +34,7 @@ constexpr uint32_t SpiEventsRequired = 4; // number of events required to happ constexpr uint32_t SpiMacroRequestTimeout = 3000; // maximum time to wait a macro file constexpr uint32_t SpiTransferTimeout = 500; // maximum allowed delay between data exchanges during a full transfer (in ms) +constexpr uint32_t SpiMaxTransferTime = 50; // maximum allowed time for a single SPI transfer constexpr uint32_t SpiConnectionTimeout = 4000; // maximum time to wait for the next transfer (in ms) constexpr uint16_t SpiCodeBufferSize = 4096; // number of bytes available for G-code caching @@ -121,7 +122,7 @@ enum TransferResponse : uint32_t BadResponse = 0xFEFEFEFE }; -// RepRapFirmware to Linux +// RepRapFirmware to Sbc struct AbortFileHeader { uint8_t channel; @@ -245,8 +246,8 @@ struct PrintPausedHeader uint16_t paddingB; }; -// Linux to RepRapFirmware -enum class LinuxRequest : uint16_t +// Sbc to RepRapFirmware +enum class SbcRequest : uint16_t { EmergencyStop = 0, // Perform immediate emergency stop Reset = 1, // Reset the controller @@ -419,4 +420,4 @@ struct SetVariableHeader #endif -#endif /* SRC_LINUX_MESSAGEFORMATS_H_ */ +#endif /* SRC_SBC_MESSAGEFORMATS_H_ */ diff --git a/src/Storage/FileData.h b/src/Storage/FileData.h index 14e4c900..ca2a000f 100644 --- a/src/Storage/FileData.h +++ b/src/Storage/FileData.h @@ -79,7 +79,7 @@ public: return f->Read(buf, nBytes); } -# if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +# if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool Write(char b) noexcept { return f->Write(b); diff --git a/src/Storage/FileStore.cpp b/src/Storage/FileStore.cpp index a4a21c91..031d1716 100644 --- a/src/Storage/FileStore.cpp +++ b/src/Storage/FileStore.cpp @@ -2,7 +2,7 @@ #include "RepRapFirmware.h" -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES #include <Platform/RepRap.h> #include <Platform/Platform.h> @@ -18,12 +18,12 @@ # include <Movement/StepTimer.h> #endif -#if HAS_LINUX_INTERFACE -# include <Linux/LinuxInterface.h> +#if HAS_SBC_INTERFACE +# include <SBC/SbcInterface.h> #endif FileStore::FileStore() noexcept -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE : writeBuffer(nullptr) #endif { @@ -40,11 +40,11 @@ void FileStore::Init() noexcept #if HAS_EMBEDDED_FILES fileIndex = -1; #endif -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE handle = noFileHandle; length = 0; #endif -#if HAS_EMBEDDED_FILES || HAS_LINUX_INTERFACE +#if HAS_EMBEDDED_FILES || HAS_SBC_INTERFACE offset = 0; #endif } @@ -55,8 +55,8 @@ bool FileStore::Open(const char* filePath, OpenMode mode, uint32_t preAllocSize) { const bool writing = (mode == OpenMode::write || mode == OpenMode::writeWithCrc || mode == OpenMode::append); #if HAS_EMBEDDED_FILES -# if HAS_LINUX_INTERFACE - if (!reprap.UsingLinuxInterface()) +# if HAS_SBC_INTERFACE + if (!reprap.UsingSbcInterface()) # endif { if (!writing) @@ -81,7 +81,7 @@ bool FileStore::Open(const char* filePath, OpenMode mode, uint32_t preAllocSize) } #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE writeBuffer = nullptr; // Try to allocate a write buffer @@ -106,10 +106,10 @@ bool FileStore::Open(const char* filePath, OpenMode mode, uint32_t preAllocSize) // Attempt to open the file bool fileOpened = false; -# if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +# if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { - handle = reprap.GetLinuxInterface().OpenFile(filePath, mode, length, preAllocSize); + handle = reprap.GetSbcInterface().OpenFile(filePath, mode, length, preAllocSize); if (handle != noFileHandle) { offset = (mode == OpenMode::append) ? length : 0; @@ -180,7 +180,7 @@ bool FileStore::Open(const char* filePath, OpenMode mode, uint32_t preAllocSize) #endif } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES // This may be called from an ISR, in which case we need to defer the close bool FileStore::Close() noexcept @@ -245,10 +245,10 @@ bool FileStore::Seek(FilePosition pos) noexcept case FileUseMode::readOnly: case FileUseMode::readWrite: -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { - if (reprap.GetLinuxInterface().SeekFile(handle, pos)) + if (reprap.GetSbcInterface().SeekFile(handle, pos)) { offset = pos; return true; @@ -273,8 +273,8 @@ bool FileStore::Seek(FilePosition pos) noexcept FilePosition FileStore::Position() const noexcept { -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { return offset; } @@ -297,8 +297,8 @@ FilePosition FileStore::Length() const noexcept return 0; case FileUseMode::readOnly: -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { return length; } @@ -312,8 +312,8 @@ FilePosition FileStore::Length() const noexcept #endif case FileUseMode::readWrite: -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { return (writeBuffer != nullptr) ? length + writeBuffer->BytesStored() : length; } @@ -332,7 +332,7 @@ FilePosition FileStore::Length() const noexcept #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE // Truncate file at current file pointer bool FileStore::Truncate() noexcept @@ -349,11 +349,11 @@ bool FileStore::Truncate() noexcept { return false; } -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { length = offset; - return reprap.GetLinuxInterface().TruncateFile(handle); + return reprap.GetSbcInterface().TruncateFile(handle); } #endif #if HAS_MASS_STORAGE @@ -370,7 +370,7 @@ bool FileStore::Truncate() noexcept #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES // Returns the number of bytes read or -1 if the read process failed int FileStore::Read(char* extBuf, size_t nBytes) noexcept @@ -383,10 +383,10 @@ int FileStore::Read(char* extBuf, size_t nBytes) noexcept case FileUseMode::readOnly: case FileUseMode::readWrite: -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { - int bytesRead = reprap.GetLinuxInterface().ReadFile(handle, extBuf, nBytes); + int bytesRead = reprap.GetSbcInterface().ReadFile(handle, extBuf, nBytes); if (bytesRead > 0) { offset += bytesRead; @@ -461,7 +461,7 @@ int FileStore::ReadLine(char* buf, size_t nBytes) noexcept bool FileStore::ForceClose() noexcept { -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool ok = true; if (usageMode == FileUseMode::readWrite) { @@ -475,10 +475,10 @@ bool FileStore::ForceClose() noexcept } #endif -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { - reprap.GetLinuxInterface().CloseFile(handle); + reprap.GetSbcInterface().CloseFile(handle); handle = noFileHandle; offset = length = 0; usageMode = FileUseMode::free; @@ -530,7 +530,7 @@ void FileStore::Duplicate() noexcept #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool FileStore::Store(const char *s, size_t len, size_t *bytesWritten) noexcept { @@ -539,10 +539,10 @@ bool FileStore::Store(const char *s, size_t len, size_t *bytesWritten) noexcept crc.Update(s, len); } -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { - bool ok = (len > 0) ? reprap.GetLinuxInterface().WriteFile(handle, s, len) : true; + bool ok = (len > 0) ? reprap.GetSbcInterface().WriteFile(handle, s, len) : true; *bytesWritten = ok ? len : 0; offset += len; if (offset > length) @@ -658,8 +658,8 @@ bool FileStore::Flush() noexcept return writeOk && (bytesToWrite == bytesWritten); } } -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { return true; } @@ -674,7 +674,7 @@ bool FileStore::Flush() noexcept } } -#if HAS_LINUX_INTERFACE // these functions are only supported in SBC mode +#if HAS_SBC_INTERFACE // these functions are only supported in SBC mode // Invalidate the file void FileStore::Invalidate() noexcept @@ -770,7 +770,7 @@ bool FileStore::SetClusterMap(uint32_t tbl[]) noexcept #endif -#endif // HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#endif // HAS_MASS_STORAGE || HAS_SBC_INTERFACE #endif diff --git a/src/Storage/FileStore.h b/src/Storage/FileStore.h index 683ed914..2588180c 100644 --- a/src/Storage/FileStore.h +++ b/src/Storage/FileStore.h @@ -7,7 +7,7 @@ #if HAS_MASS_STORAGE # include "Libraries/Fatfs/ff.h" #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE # include "CRC32.h" #endif @@ -18,7 +18,7 @@ class FileWriteBuffer; typedef int32_t FileIndex; #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES enum class OpenMode : uint8_t { @@ -59,7 +59,7 @@ public: FilePosition Position() const noexcept; // Return the current position in the file, assuming we are reading the file void Duplicate() noexcept; // Create a second reference to this file -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE FileWriteBuffer *GetWriteBuffer() const noexcept; // Return a pointer to the remaining space for writing bool Write(char b) noexcept; // Write 1 byte bool Write(const char *s, size_t len) noexcept; // Write a block of len bytes @@ -70,7 +70,7 @@ public: uint32_t GetCRC32() const noexcept; #endif -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE void Invalidate() noexcept; // Invalidate the file #endif @@ -94,7 +94,7 @@ private: volatile unsigned int openCount; -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE FileWriteBuffer *writeBuffer; CRC32 crc; #endif @@ -104,7 +104,7 @@ private: static uint32_t longestWriteTime; #endif -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE FileHandle handle; FilePosition length; #endif @@ -113,19 +113,19 @@ private: FileIndex fileIndex; #endif -#if HAS_EMBEDDED_FILES || HAS_LINUX_INTERFACE +#if HAS_EMBEDDED_FILES || HAS_SBC_INTERFACE FilePosition offset; #endif volatile bool closeRequested; FileUseMode usageMode; -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool calcCrc; #endif }; -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE inline FileWriteBuffer *FileStore::GetWriteBuffer() const noexcept { return writeBuffer; } @@ -138,6 +138,6 @@ inline uint32_t FileStore::GetCRC32() const noexcept #endif -#endif // HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#endif // HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES #endif // #ifndef FILESTORE_H diff --git a/src/Storage/FileWriteBuffer.h b/src/Storage/FileWriteBuffer.h index 27fe9d5d..26f05fa4 100644 --- a/src/Storage/FileWriteBuffer.h +++ b/src/Storage/FileWriteBuffer.h @@ -13,23 +13,23 @@ #if SAM4E || SAM4S || SAME70 || SAME5x constexpr size_t NumFileWriteBuffers = 2; // Number of write buffers constexpr size_t FileWriteBufLen = 8192; // Size of each write buffer -constexpr size_t LinuxFileWriteBufLen = 4192; // Available size of each write buffer in SBC mode +constexpr size_t SbcFileWriteBufLen = 4192; // Available size of each write buffer in SBC mode #elif defined(__LPC17xx__) # if HAS_WIFI_NETWORKING constexpr size_t NumFileWriteBuffers = 1; constexpr size_t FileWriteBufLen = 1024; -constexpr size_t LinuxFileWriteBufLen = 768; +constexpr size_t SbcFileWriteBufLen = 768; # else constexpr size_t NumFileWriteBuffers = 1; constexpr size_t FileWriteBufLen = 512; -constexpr size_t LinuxFileWriteBufLen = 468; +constexpr size_t SbcFileWriteBufLen = 468; # endif #else constexpr size_t NumFileWriteBuffers = 1; constexpr size_t FileWriteBufLen = 4096; -constexpr size_t LinuxFileWriteBufLen = 3072; +constexpr size_t SbcFileWriteBufLen = 3072; #endif -static_assert(FileWriteBufLen >= LinuxFileWriteBufLen, "File write buffer must be at least as big as the configured Linux threshold"); +static_assert(FileWriteBufLen >= SbcFileWriteBufLen, "File write buffer must be at least as big as the configured SBC threshold"); // Class to cache data that is about to be written to the SD card. This is NOT a ring buffer, // instead it just provides simple interfaces to cache a certain amount of data so that fewer @@ -42,7 +42,7 @@ public: #else FileWriteBuffer(FileWriteBuffer *n) noexcept : next(n), index(0) { } #endif - static void UsingSbcMode() { fileWriteBufLen = LinuxFileWriteBufLen; } // only called by RepRap on startup + static void UsingSbcMode() { fileWriteBufLen = SbcFileWriteBufLen; } // only called by RepRap on startup FileWriteBuffer *Next() const noexcept { return next; } void SetNext(FileWriteBuffer *n) noexcept { next = n; } diff --git a/src/Storage/MassStorage.cpp b/src/Storage/MassStorage.cpp index c9705e07..4c95caa8 100644 --- a/src/Storage/MassStorage.cpp +++ b/src/Storage/MassStorage.cpp @@ -15,8 +15,8 @@ static_assert(FF_MAX_LFN >= MaxFilenameLength, "FF_MAX_LFN too small"); static_assert(SD_MMC_MEM_CNT == NumSdCards); #endif -#if HAS_LINUX_INTERFACE -# include <Linux/LinuxInterface.h> +#if HAS_SBC_INTERFACE +# include <SBC/SbcInterface.h> #endif // A note on using mutexes: @@ -126,11 +126,11 @@ static Mutex dirMutex; static FileInfoParser infoParser; #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE static FileWriteBuffer *freeWriteBuffers; #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES static Mutex fsMutex; static FileStore files[MAX_FILES]; #endif @@ -184,8 +184,8 @@ uint16_t MassStorage::GetVolumeSeq(unsigned int volume) noexcept static bool VolumeUpdated(const char *path) noexcept { if (!StringEndsWithIgnoreCase(path, ".part") -#if HAS_LINUX_INTERFACE - && !reprap.UsingLinuxInterface() +#if HAS_SBC_INTERFACE + && !reprap.UsingSbcInterface() #endif ) { @@ -275,7 +275,7 @@ static const char* TranslateCardError(sd_mmc_err_t err) noexcept #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES void MassStorage::Init() noexcept { @@ -285,7 +285,7 @@ void MassStorage::Init() noexcept dirMutex.Create("DirSearch"); #endif -# if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +# if HAS_MASS_STORAGE || HAS_SBC_INTERFACE freeWriteBuffers = nullptr; for (size_t i = 0; i < NumFileWriteBuffers; ++i) { @@ -470,7 +470,7 @@ bool MassStorage::DirectoryExists(const StringRef& path) noexcept #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE // Static helper functions size_t FileWriteBuffer::fileWriteBufLen = FileWriteBufLen; @@ -496,7 +496,7 @@ void MassStorage::ReleaseWriteBuffer(FileWriteBuffer *buffer) noexcept freeWriteBuffers = buffer; } -# if HAS_LINUX_INTERFACE +# if HAS_SBC_INTERFACE // Return true if any files are open on the file system bool MassStorage::AnyFileOpen() noexcept @@ -587,10 +587,10 @@ static bool InternalDelete(const char* filePath, bool messageIfFailed) noexcept // Delete a file or directory and update the volume sequence number returning true if successful bool MassStorage::Delete(const char* filePath, bool messageIfFailed) noexcept { -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { - if (reprap.GetLinuxInterface().DeleteFileOrDirectory(filePath)) + if (reprap.GetSbcInterface().DeleteFileOrDirectory(filePath)) { return true; } @@ -728,8 +728,8 @@ const char* MassStorage::GetMonthName(const uint8_t month) noexcept // Ensure that the path up to the last '/' (excluding trailing '/' characters) in filePath exists, returning true if successful bool MassStorage::EnsurePath(const char* filePath, bool messageIfFailed) noexcept { -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { // This isn't needed in SBC mode because DSF does it automatically return true; @@ -837,15 +837,15 @@ bool MassStorage::Rename(const char *oldFilename, const char *newFilename, bool } #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE // Check if the specified file exists bool MassStorage::FileExists(const char *filePath) noexcept { -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) +#if HAS_SBC_INTERFACE + if (reprap.UsingSbcInterface()) { - return reprap.GetLinuxInterface().FileExists(filePath); + return reprap.GetSbcInterface().FileExists(filePath); } #endif diff --git a/src/Storage/MassStorage.h b/src/Storage/MassStorage.h index 39cbd60d..3753923b 100644 --- a/src/Storage/MassStorage.h +++ b/src/Storage/MassStorage.h @@ -42,7 +42,7 @@ namespace MassStorage bool CombineName(const StringRef& outbuf, const char* directory, const char* fileName) noexcept; // returns false if error i.e. filename too long const char* GetMonthName(const uint8_t month) noexcept; -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE || HAS_EMBEDDED_FILES +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES void Init() noexcept; FileStore* OpenFile(const char* filePath, OpenMode mode, uint32_t preAllocSize) noexcept; bool FileExists(const char *filePath) noexcept; @@ -50,14 +50,14 @@ namespace MassStorage void Spin() noexcept; #endif -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE FileWriteBuffer *AllocateWriteBuffer() noexcept; size_t GetFileWriteBufferLength() noexcept; void ReleaseWriteBuffer(FileWriteBuffer *buffer) noexcept; bool Delete(const char* filePath, bool messageIfFailed) noexcept; #endif -#if HAS_LINUX_INTERFACE +#if HAS_SBC_INTERFACE bool AnyFileOpen() noexcept; // Return true if any files are open on the file system void InvalidateAllFiles() noexcept; #endif diff --git a/src/Tools/Filament.cpp b/src/Tools/Filament.cpp index 75c268a9..b2003ce7 100644 --- a/src/Tools/Filament.cpp +++ b/src/Tools/Filament.cpp @@ -42,7 +42,7 @@ void Filament::Unload() noexcept void Filament::LoadAssignment() noexcept { -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE FileStore * const file = reprap.GetPlatform().OpenSysFile(FilamentAssignmentFile, OpenMode::read); if (file == nullptr) { @@ -84,7 +84,7 @@ void Filament::LoadAssignment() noexcept // Update the OM when the filament has been changed reprap.MoveUpdated(); -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE FileStore * const file = reprap.GetPlatform().OpenSysFile(FilamentAssignmentFile, OpenMode::write); if (file == nullptr) { diff --git a/src/Tools/Tool.cpp b/src/Tools/Tool.cpp index 3c86af74..ed5b8cda 100644 --- a/src/Tools/Tool.cpp +++ b/src/Tools/Tool.cpp @@ -581,7 +581,7 @@ void Tool::DefineMix(const float m[]) noexcept reprap.ToolsUpdated(); } -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE // Write the tool's settings to file returning true if successful. The settings written leave the tool selected unless it is off. bool Tool::WriteSettings(FileStore *f) const noexcept diff --git a/src/Tools/Tool.h b/src/Tools/Tool.h index bcdccb98..5ff3da34 100644 --- a/src/Tools/Tool.h +++ b/src/Tools/Tool.h @@ -98,7 +98,7 @@ public: uint32_t GetSpindleRpm() const noexcept { return spindleRpm; } void SetSpindleRpm(uint32_t rpm) THROWS(GCodeException); -#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE +#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool WriteSettings(FileStore *f) const noexcept; // write the tool's settings to file #endif diff --git a/src/bossa/Flasher.cpp b/src/bossa/Flasher.cpp index 85f65f86..0a6ec978 100644 --- a/src/bossa/Flasher.cpp +++ b/src/bossa/Flasher.cpp @@ -31,8 +31,8 @@ #include <Platform/RepRap.h> #include <Platform/Platform.h> #include <General/Vector.hpp> -#if HAS_LINUX_INTERFACE -# include <Linux/LinuxInterface.h> +#if HAS_SBC_INTERFACE +# include <SBC/SbcInterface.h> #endif void Flasher::erase(uint32_t foffset) THROWS(GCodeException) |