diff options
author | David Crocker <dcrocker@eschertech.com> | 2021-07-30 10:17:45 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2021-07-30 10:17:45 +0300 |
commit | 7c5ef6000bdeebfa8d51c0ead656ea554f1eb882 (patch) | |
tree | 170bd0a4bc3f8282d6a97f16498b356a64b2f925 | |
parent | 7b0dde7831f35450b6c5c077b00821b118eb9570 (diff) | |
parent | d7fd1866ffbfbb87229fa89ae2c7add48307cd8a (diff) |
Merge branch 'v3-chrishamm' into 3.4-input-shaping
-rw-r--r-- | src/CAN/CanInterface.cpp | 2 | ||||
-rw-r--r-- | src/Configuration.h | 1 | ||||
-rw-r--r-- | src/GCodes/GCodeBuffer/ExpressionParser.cpp | 6 | ||||
-rw-r--r-- | src/GCodes/GCodeBuffer/ExpressionParser.h | 2 | ||||
-rw-r--r-- | src/GCodes/GCodes.cpp | 12 | ||||
-rw-r--r-- | src/GCodes/GCodes2.cpp | 14 | ||||
-rw-r--r-- | src/GCodes/GCodes3.cpp | 8 | ||||
-rw-r--r-- | src/Hardware/ExceptionHandlers.cpp | 9 | ||||
-rw-r--r-- | src/Linux/DataTransfer.cpp | 6 | ||||
-rw-r--r-- | src/Linux/DataTransfer.h | 2 | ||||
-rw-r--r-- | src/Linux/LinuxInterface.cpp | 45 | ||||
-rw-r--r-- | src/Linux/LinuxInterface.h | 14 | ||||
-rw-r--r-- | src/Platform/TaskPriorities.h | 2 | ||||
-rw-r--r-- | src/PrintMonitor/PrintMonitor.cpp | 2 |
14 files changed, 65 insertions, 60 deletions
diff --git a/src/CAN/CanInterface.cpp b/src/CAN/CanInterface.cpp index 9b42ab44..d7d93946 100644 --- a/src/CAN/CanInterface.cpp +++ b/src/CAN/CanInterface.cpp @@ -1191,7 +1191,7 @@ void CanInterface::Diagnostics(MessageType mtype) noexcept CanId id; id.SetReceivedId(lastCancelledId); lastCancelledId = 0; - str.catf(" last cancelled message type %u dest %u\n", (unsigned int)id.MsgType(), id.Dst()); + str.catf(" last cancelled message type %u dest %u", (unsigned int)id.MsgType(), id.Dst()); } reprap.GetPlatform().MessageF(mtype, "Tx timeouts%s\n", str.c_str()); diff --git a/src/Configuration.h b/src/Configuration.h index 14878668..89765445 100644 --- a/src/Configuration.h +++ b/src/Configuration.h @@ -383,6 +383,7 @@ static_assert(MaxExpectedWebDirFilenameLength + strlen(WEB_DIR) + strlen(".gz") #define EOF_STRING "<!-- **EoF** -->" // List defaults +constexpr char EXPRESSION_LIST_SEPARATOR = ','; constexpr char LIST_SEPARATOR = ':'; #endif diff --git a/src/GCodes/GCodeBuffer/ExpressionParser.cpp b/src/GCodes/GCodeBuffer/ExpressionParser.cpp index 60d5db79..0c65a39c 100644 --- a/src/GCodes/GCodeBuffer/ExpressionParser.cpp +++ b/src/GCodes/GCodeBuffer/ExpressionParser.cpp @@ -812,10 +812,12 @@ void ExpressionParser::SkipWhiteSpace() noexcept } } -void ExpressionParser::CheckForExtraCharacters() THROWS(GCodeException) +void ExpressionParser::CheckForExtraCharacters(bool isArrayExpression) THROWS(GCodeException) { SkipWhiteSpace(); - if (CurrentCharacter() != 0) + + char c = CurrentCharacter(); + if (c != 0 && (!isArrayExpression || (c != EXPRESSION_LIST_SEPARATOR && c != LIST_SEPARATOR))) { ThrowParseException("Unexpected characters after expression"); } diff --git a/src/GCodes/GCodeBuffer/ExpressionParser.h b/src/GCodes/GCodeBuffer/ExpressionParser.h index 25ad7470..adfff7c7 100644 --- a/src/GCodes/GCodeBuffer/ExpressionParser.h +++ b/src/GCodes/GCodeBuffer/ExpressionParser.h @@ -33,7 +33,7 @@ public: void ParseDriverIdArray(DriverId arr[], size_t& length) THROWS(GCodeException); void SkipWhiteSpace() noexcept; - void CheckForExtraCharacters() THROWS(GCodeException); + void CheckForExtraCharacters(bool isArrayExpression = false) THROWS(GCodeException); const char *GetEndptr() const noexcept { return currentp; } private: diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp index a4c36491..85e88c33 100644 --- a/src/GCodes/GCodes.cpp +++ b/src/GCodes/GCodes.cpp @@ -479,16 +479,10 @@ void GCodes::Spin() noexcept #if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) + // Need to check if the print has been stopped by the SBC + if (reprap.UsingLinuxInterface() && reprap.GetLinuxInterface().HasPrintStopped()) { - if (reprap.GetLinuxInterface().HasPrintStarted()) - { - StartPrinting(true); - } - else if (reprap.GetLinuxInterface().HasPrintStopped()) - { - StopPrint(reprap.GetLinuxInterface().GetPrintStopReason()); - } + StopPrint(reprap.GetLinuxInterface().GetPrintStopReason()); } #endif diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp index 84cee85f..ee50c201 100644 --- a/src/GCodes/GCodes2.cpp +++ b/src/GCodes/GCodes2.cpp @@ -829,7 +829,9 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx result = MassStorage::Unmount(card, reply); } break; +#endif +#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE 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. @@ -847,7 +849,17 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx { String<MaxFilenameLength> filename; gb.GetUnprecedentedString(filename.GetRef()); - if (QueueFileToPrint(filename.c_str(), reply)) + if ( +#if HAS_LINUX_INTERFACE + reprap.UsingLinuxInterface() +# if HAS_MASS_STORAGE + || +# endif +#endif +#if HAS_MASS_STORAGE + QueueFileToPrint(filename.c_str(), reply) +#endif + ) { reprap.GetPrintMonitor().StartingPrint(filename.c_str()); if (gb.LatestMachineState().compatibility == Compatibility::Marlin) diff --git a/src/GCodes/GCodes3.cpp b/src/GCodes/GCodes3.cpp index 74ba76a9..42388844 100644 --- a/src/GCodes/GCodes3.cpp +++ b/src/GCodes/GCodes3.cpp @@ -432,13 +432,7 @@ GCodeResult GCodes::SimulateFile(GCodeBuffer& gb, const StringRef &reply, const simulationMode = 1; reprap.GetMove().Simulate(simulationMode); reprap.GetPrintMonitor().StartingPrint(file.c_str()); -# if HAS_LINUX_INTERFACE - if (!reprap.UsingLinuxInterface()) -# endif - { - // If using a SBC, this is already called when the print file info is set - StartPrinting(true); - } + StartPrinting(true); reply.printf("Simulating print of file %s", file.c_str()); return GCodeResult::ok; } diff --git a/src/Hardware/ExceptionHandlers.cpp b/src/Hardware/ExceptionHandlers.cpp index 640c0a41..1413108d 100644 --- a/src/Hardware/ExceptionHandlers.cpp +++ b/src/Hardware/ExceptionHandlers.cpp @@ -15,6 +15,12 @@ # include <Reset.h> #endif +#if SAME5x +// Magic address and value to launch the uf2 bootloader on failure, see inc/uf2.h in uf2-samdx1 repository +# define DBL_TAP_PTR ((volatile uint32_t *)(HSRAM_ADDR + HSRAM_SIZE - 4)) +# define DBL_TAP_MAGIC 0xf01669ef // Randomly selected, adjusted to have first and last bit set +#endif + // Perform a software reset. 'stk' points to the exception stack (r0 r1 r2 r3 r12 lr pc xPSR) if the cause is an exception, otherwise it is nullptr. [[noreturn]] void SoftwareReset(SoftwareResetReason initialReason, const uint32_t *stk) noexcept { @@ -31,7 +37,8 @@ if (initialReason == SoftwareResetReason::erase) { #if SAME5x - //TODO invalidate flash so the USB bootloader runs + // Start from uf2 bootloader next time. This pretends the reset button has been pressed twice in short succession + *DBL_TAP_PTR = DBL_TAP_MAGIC; #else EraseAndReset(); #endif diff --git a/src/Linux/DataTransfer.cpp b/src/Linux/DataTransfer.cpp index 69c09cd9..bd1312fa 100644 --- a/src/Linux/DataTransfer.cpp +++ b/src/Linux/DataTransfer.cpp @@ -304,7 +304,7 @@ pre(bytesToTransfer <= inBuffer.limit; bytesToTransfer <= outBuffer.limit) // Enable SPI and notify the SBC we are ready #if SAME5x - SbcSpiSercom->SPI.INTFLAG.reg = 0xFF; // clear any pending interrupts + SbcSpiSercom->SPI.INTFLAG.reg = 0xFF; // clear any pending interrupts SbcSpiSercom->SPI.INTENSET.reg = SERCOM_SPI_INTENSET_SSL; // enable the start of transfer (SS low) interrupt SbcSpiSercom->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_ENABLE; while (SbcSpiSercom->SPI.SYNCBUSY.reg & (SERCOM_SPI_SYNCBUSY_SWRST | SERCOM_SPI_SYNCBUSY_ENABLE)) { }; @@ -494,9 +494,9 @@ void DataTransfer::Init() noexcept } } -void DataTransfer::SetSBCTask(TaskHandle handle) noexcept +void DataTransfer::InitFromTask() noexcept { - linuxTaskHandle = handle; + linuxTaskHandle = TaskBase::GetCallerTaskHandle(); } void DataTransfer::Diagnostics(MessageType mtype) noexcept diff --git a/src/Linux/DataTransfer.h b/src/Linux/DataTransfer.h index cf1d47d6..c7f9fa2d 100644 --- a/src/Linux/DataTransfer.h +++ b/src/Linux/DataTransfer.h @@ -30,7 +30,7 @@ class DataTransfer public: DataTransfer() noexcept; void Init() noexcept; - void SetSBCTask(TaskHandle handle) noexcept; + void InitFromTask() noexcept; void Diagnostics(MessageType mtype) noexcept; bool IsConnected() const noexcept; // Check if the connection to DCS is live diff --git a/src/Linux/LinuxInterface.cpp b/src/Linux/LinuxInterface.cpp index c442ffa5..9469c139 100644 --- a/src/Linux/LinuxInterface.cpp +++ b/src/Linux/LinuxInterface.cpp @@ -39,6 +39,7 @@ constexpr size_t SBCTaskStackWords = 1000; // debug builds use more stack #else constexpr size_t SBCTaskStackWords = 820; #endif +constexpr uint32_t LinuxYieldTimeout = 10; static Task<SBCTaskStackWords> *sbcTask; @@ -49,7 +50,7 @@ extern "C" [[noreturn]] void SBCTaskStart(void * pvParameters) noexcept LinuxInterface::LinuxInterface() noexcept : isConnected(false), numDisconnects(0), numTimeouts(0), maxDelayBetweenTransfers(SpiTransferDelay), numMaxEvents(SpiEventsRequired), delaying(false), numEvents(0), - reportPause(false), reportPauseWritten(false), printStarted(false), printStopped(false), + reportPause(false), reportPauseWritten(false), printStopped(false), codeBuffer(nullptr), rxPointer(0), txPointer(0), txEnd(0), sendBufferUpdate(true), iapWritePointer(IAP_IMAGE_START), waitingForFileChunk(false), fileMutex(), fileSemaphore(), fileOperation(FileOperation::none), fileOperationPending(false) #ifdef TRACK_FILE_CODES @@ -94,12 +95,12 @@ void LinuxInterface::Spin() noexcept [[noreturn]] void LinuxInterface::TaskLoop() noexcept { - transfer.SetSBCTask(sbcTask); + transfer.InitFromTask(); transfer.StartNextTransfer(); - bool writingIap = false, hadReset = false, skipNextDelay = false; + + bool writingIap = false, isReady = false, hadReset = false, skipNextDelay = false; for (;;) { - bool isReady = false; if (hadReset) { isReady = true; @@ -110,6 +111,10 @@ void LinuxInterface::Spin() noexcept isReady = true; hadReset = isConnected && transfer.LinuxHadReset(); } + else + { + isReady = false; + } if (isReady && !hadReset) { @@ -280,7 +285,6 @@ void LinuxInterface::Spin() noexcept String<MaxFilenameLength> filename; transfer.ReadPrintStartedInfo(packet->length, filename.GetRef(), fileInfo); reprap.GetPrintMonitor().SetPrintingFileInfo(filename.c_str(), fileInfo); - printStarted = true; break; } @@ -292,7 +296,7 @@ void LinuxInterface::Spin() noexcept { // Just mark the print file as finished GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(GCodeChannel::File); - MutexLocker locker(gb->mutex, 10); + MutexLocker locker(gb->mutex, LinuxYieldTimeout); if (locker) { gb->SetPrintFinished(); @@ -330,7 +334,7 @@ void LinuxInterface::Spin() noexcept } else { - MutexLocker locker(gb->mutex, 10); + MutexLocker locker(gb->mutex, LinuxYieldTimeout); if (locker) { if (error) @@ -408,7 +412,7 @@ void LinuxInterface::Spin() noexcept if (channel.IsValid()) { GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); - MutexLocker locker(gb->mutex, 10); + MutexLocker locker(gb->mutex, LinuxYieldTimeout); if (locker && reprap.GetGCodes().LockMovementAndWaitForStandstill(*gb)) { transfer.WriteLocked(channel); @@ -432,7 +436,7 @@ void LinuxInterface::Spin() noexcept if (channel.IsValid()) { GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); - MutexLocker locker(gb->mutex, 10); + MutexLocker locker(gb->mutex, LinuxYieldTimeout); if (locker) { reprap.GetGCodes().UnlockAll(*gb); @@ -523,7 +527,7 @@ void LinuxInterface::Spin() noexcept try { // Evaluate the expression and send the result to DSF - MutexLocker lock(gb->mutex, 10); + MutexLocker lock(gb->mutex, LinuxYieldTimeout); if (lock) { ExpressionParser parser(*gb, expression.c_str(), expression.c_str() + expression.strlen()); @@ -620,7 +624,7 @@ void LinuxInterface::Spin() noexcept gb->ResolveMacroRequest(true, false); } - MutexLocker locker(gb->mutex, 10); + MutexLocker locker(gb->mutex, LinuxYieldTimeout); if (locker) { // Note that we do not call StopPrint here or set any other variables; DSF already does that @@ -654,7 +658,7 @@ void LinuxInterface::Spin() noexcept } GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); - MutexLocker lock(gb->mutex, 10); + MutexLocker lock(gb->mutex, LinuxYieldTimeout); if (!lock) { packetAcknowledged = false; @@ -734,7 +738,7 @@ void LinuxInterface::Spin() noexcept } GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); - MutexLocker lock(gb->mutex, 10); + MutexLocker lock(gb->mutex, LinuxYieldTimeout); if (!lock) { packetAcknowledged = false; @@ -865,8 +869,6 @@ void LinuxInterface::Spin() noexcept if (!writingIap && !skipNextDelay && numEvents < numMaxEvents && !waitingForFileChunk && !fileOperationPending && (fileOperation != FileOperation::write || numFileWriteRequests == 0)) { - TaskBase::ClearNotifyCount(); - delaying = true; if (!TaskBase::Take(maxDelayBetweenTransfers)) { @@ -901,7 +903,7 @@ void LinuxInterface::Spin() noexcept sendBufferUpdate = !transfer.WriteCodeBufferUpdate(bufferSpace); } - if (!writingIap) // it's not safe to access GCodes once we have started writing the IAP + if (!writingIap) // it's not safe to access other resources once we have started writing the IAP { // Get another chunk of the file being requested if (waitingForFileChunk && @@ -1010,7 +1012,7 @@ void LinuxInterface::Spin() noexcept // Deal with other requests unless we are still waiting in a semaphore if (!gb->IsWaitingForMacro()) { - MutexLocker gbLock(gb->mutex, 10); + MutexLocker gbLock(gb->mutex, LinuxYieldTimeout); if (gbLock) { if (gb->GetChannel() != GCodeChannel::Daemon) @@ -1080,7 +1082,7 @@ void LinuxInterface::Spin() noexcept if (reportPause) { GCodeBuffer * const fileGCode = reprap.GetGCodes().GetGCodeBuffer(GCodeChannel::File); - MutexLocker locker(fileGCode->mutex, 10); + MutexLocker locker(fileGCode->mutex, LinuxYieldTimeout); if (locker && transfer.WritePrintPaused(pauseFilePosition, pauseReason)) { fileGCode->Invalidate(); @@ -1157,7 +1159,7 @@ void LinuxInterface::Spin() noexcept if (hadReset) { // Let the main task invalidate resources - RTOSIface::Yield(); + TaskBase::Take(LinuxYieldTimeout); } else { @@ -1168,6 +1170,11 @@ void LinuxInterface::Spin() noexcept else if (!writingIap) { // A transfer is being performed but it has not finished yet + TaskBase::Take(LinuxYieldTimeout); + } + else + { + // IAP binary is being written, only keep equal or higher priority tasks running RTOSIface::Yield(); } } diff --git a/src/Linux/LinuxInterface.h b/src/Linux/LinuxInterface.h index b28d88d2..74936723 100644 --- a/src/Linux/LinuxInterface.h +++ b/src/Linux/LinuxInterface.h @@ -46,7 +46,6 @@ public: void EventOccurred(bool timeCritical = false) noexcept; // Called when a new event has happened. It can optionally start off a new transfer immediately GCodeResult HandleM576(GCodeBuffer& gb, const StringRef& reply) noexcept; // Set the SPI communication parameters - bool HasPrintStarted(); bool HasPrintStopped(); StopPrintReason GetPrintStopReason() const { return printStopReason; } bool FillBuffer(GCodeBuffer &gb) noexcept; // Try to fill up the G-code buffer with the next available G-code @@ -80,7 +79,7 @@ private: GCodeFileInfo fileInfo; FilePosition pauseFilePosition; PrintPausedReason pauseReason; - bool reportPause, reportPauseWritten, printStarted, printStopped; + bool reportPause, reportPauseWritten, printStopped; StopPrintReason printStopReason; char *codeBuffer; @@ -147,17 +146,6 @@ inline void LinuxInterface::SetPauseReason(FilePosition position, PrintPausedRea reportPause = true; } -inline bool LinuxInterface::HasPrintStarted() -{ - TaskCriticalSectionLocker locker; - if (printStarted) - { - printStarted = false; - return true; - } - return false; -} - inline bool LinuxInterface::HasPrintStopped() { TaskCriticalSectionLocker locker; diff --git a/src/Platform/TaskPriorities.h b/src/Platform/TaskPriorities.h index 36545a55..a30743c0 100644 --- a/src/Platform/TaskPriorities.h +++ b/src/Platform/TaskPriorities.h @@ -14,7 +14,7 @@ namespace TaskPriority constexpr int IdlePriority = 0; constexpr int SpinPriority = 1; // priority for tasks that rarely block #if HAS_LINUX_INTERFACE - constexpr int SbcPriority = 1; // priority for SBC task. TODO increase this when we are certain that it never spins. + constexpr int SbcPriority = 2; // priority for SBC task #endif #if defined(LPC_NETWORKING) constexpr int TcpPriority = 2; diff --git a/src/PrintMonitor/PrintMonitor.cpp b/src/PrintMonitor/PrintMonitor.cpp index 925897fd..07a4dae3 100644 --- a/src/PrintMonitor/PrintMonitor.cpp +++ b/src/PrintMonitor/PrintMonitor.cpp @@ -292,11 +292,11 @@ void PrintMonitor::StartingPrint(const char* filename) noexcept #if HAS_MASS_STORAGE WriteLocker locker(printMonitorLock); MassStorage::CombineName(filenameBeingPrinted.GetRef(), platform.GetGCodeDir(), filename); - printingFileParsed = false; # if HAS_LINUX_INTERFACE if (!reprap.UsingLinuxInterface()) # endif { + printingFileParsed = false; if (MassStorage::GetFileInfo(filenameBeingPrinted.c_str(), printingFileInfo, false) != GCodeResult::notFinished) { UpdatePrintingFileInfo(); |