From d7fd1866ffbfbb87229fa89ae2c7add48307cd8a Mon Sep 17 00:00:00 2001 From: Christian Hammacher Date: Thu, 29 Jul 2021 19:04:19 +0200 Subject: Further improvements Added support for expression lists (untested in standalone mode) M23/M32 are invoked again by DSF in SBC mode Increased SBC task priority Bug fix: CAN diagnostics output extra NL Bug fix: M999 P"ERASE" was not working on the Mini5+ series --- src/CAN/CanInterface.cpp | 2 +- src/Configuration.h | 1 + src/GCodes/GCodeBuffer/BinaryParser.cpp | 121 +++++++++++++++++++++++----- src/GCodes/GCodeBuffer/BinaryParser.h | 2 +- src/GCodes/GCodeBuffer/ExpressionParser.cpp | 6 +- src/GCodes/GCodeBuffer/ExpressionParser.h | 2 +- src/GCodes/GCodeBuffer/StringParser.cpp | 8 +- src/GCodes/GCodes.cpp | 12 +-- src/GCodes/GCodes2.cpp | 14 +++- src/GCodes/GCodes3.cpp | 8 +- src/Hardware/ExceptionHandlers.cpp | 9 ++- src/Linux/DataTransfer.cpp | 6 +- src/Linux/DataTransfer.h | 2 +- src/Linux/LinuxInterface.cpp | 45 ++++++----- src/Linux/LinuxInterface.h | 14 +--- src/Platform/TaskPriorities.h | 2 +- src/PrintMonitor/PrintMonitor.cpp | 2 +- 17 files changed, 171 insertions(+), 85 deletions(-) diff --git a/src/CAN/CanInterface.cpp b/src/CAN/CanInterface.cpp index 502fad4f..35ccc87e 100644 --- a/src/CAN/CanInterface.cpp +++ b/src/CAN/CanInterface.cpp @@ -1170,7 +1170,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 dd67344f..efdd6141 100644 --- a/src/Configuration.h +++ b/src/Configuration.h @@ -377,6 +377,7 @@ static_assert(MaxExpectedWebDirFilenameLength + strlen(WEB_DIR) + strlen(".gz") #define EOF_STRING "" // List defaults +constexpr char EXPRESSION_LIST_SEPARATOR = ','; constexpr char LIST_SEPARATOR = ':'; #endif diff --git a/src/GCodes/GCodeBuffer/BinaryParser.cpp b/src/GCodes/GCodeBuffer/BinaryParser.cpp index 78145ef1..de4b7b02 100644 --- a/src/GCodes/GCodeBuffer/BinaryParser.cpp +++ b/src/GCodes/GCodeBuffer/BinaryParser.cpp @@ -457,17 +457,17 @@ void BinaryParser::GetPossiblyQuotedString(const StringRef& str, bool allowEmpty void BinaryParser::GetFloatArray(float arr[], size_t& length, bool doPad) THROWS(GCodeException) { - GetArray(arr, length, doPad); + GetArray(arr, length, doPad, DataType::Float); } void BinaryParser::GetIntArray(int32_t arr[], size_t& length, bool doPad) THROWS(GCodeException) { - GetArray(arr, length, doPad); + GetArray(arr, length, doPad, DataType::Int); } void BinaryParser::GetUnsignedArray(uint32_t arr[], size_t& length, bool doPad) THROWS(GCodeException) { - GetArray(arr, length, doPad); + GetArray(arr, length, doPad, DataType::UInt); } // Get a :-separated list of drivers after a key letter @@ -498,6 +498,17 @@ void BinaryParser::GetDriverIdArray(DriverId arr[], size_t& length) THROWS(GCode length = seenParameter->intValue; break; + case DataType::Expression: + { + float temp[seenParameter->intValue]; + GetArray(temp, length, false, DataType::Float); + for (int i = 0; i < seenParameter->intValue; i++) + { + SetDriverIdFromBinary(arr[i], temp[i]); + } + break; + } + default: length = 0; return; @@ -562,7 +573,7 @@ void BinaryParser::AppendFullCommand(const StringRef &s) const noexcept } } -template void BinaryParser::GetArray(T arr[], size_t& length, bool doPad) THROWS(GCodeException) +template void BinaryParser::GetArray(T arr[], size_t& length, bool doPad, DataType type) THROWS(GCodeException) { if (seenParameter == nullptr) { @@ -617,34 +628,104 @@ template void BinaryParser::GetArray(T arr[], size_t& length, bool d break; case DataType::Expression: - //TODO need a way to pass multi-element array-valued expressions. For now we support only single-element expressions. + { + const char *pos = seenParameterValue, *endPos = seenParameterValue + seenParameter->intValue; + + // Check if the whole expression is encapsulated in curly braces and remove them if necessary + if (*pos == '{' && pos != endPos) { - ExpressionParser parser(gb, seenParameterValue, seenParameterValue + seenParameter->intValue, -1); - const ExpressionValue val = parser.Parse(); - switch ((TypeCode)val.type) + bool isEncapsulated = true, inQuotes = false; + size_t numBraces = 1; + for (const char *str = pos + 1; str < endPos; str++) + { + if (inQuotes) + { + inQuotes = (*str != '"'); + } + else if (*str == '"') + { + inQuotes = true; + } + else if (*str == '{') + { + numBraces++; + } + else if (*str == '}') + { + numBraces--; + if (numBraces == 0) + { + const char *curPos = str; + while (str != endPos && strchr("\t ", *++str) != nullptr) { } + if (str == endPos) + { + endPos = curPos + 1; + } + else + { + isEncapsulated = false; + } + break; + } + } + } + + if (isEncapsulated) { - case TypeCode::Int32: - arr[0] = (T)val.iVal; - lastIndex = 0; + pos++; + endPos--; + } + } + + // Read array expression + for (;;) + { + if (lastIndex >= (int)length) + { + throw ConstructParseException("array too long, max length = %u", (uint32_t)length); + } + + // Read the next expression value + ExpressionParser parser(gb, pos, endPos, -1); + switch (type) + { + case DataType::Int: + arr[++lastIndex] = (T)parser.ParseInteger(); break; - case TypeCode::Float: - arr[0] = (T)val.fVal; - lastIndex = 0; + case DataType::UInt: + arr[++lastIndex] = (T)parser.ParseUnsigned(); break; - case TypeCode::Uint32: - case TypeCode::DriverId: - arr[0] = (T)val.uVal; - lastIndex = 0; + case DataType::Float: + arr[++lastIndex] = (T)parser.ParseFloat(); break; default: - throw ConstructParseException("invalid expression type"); + throw ConstructParseException("Unsupported array data type"); + } + parser.CheckForExtraCharacters(true); + pos = parser.GetEndptr(); + + if (pos++ >= endPos) + { + break; + } + } + + if (doPad && lastIndex == 0) + { + for (size_t i = 1; i < length; i++) + { + arr[i] = arr[0]; } - parser.CheckForExtraCharacters(); + } + else + { + length = lastIndex + 1; } break; + } default: length = 0; diff --git a/src/GCodes/GCodeBuffer/BinaryParser.h b/src/GCodes/GCodeBuffer/BinaryParser.h index 5a4bcc38..3495d9c8 100644 --- a/src/GCodes/GCodeBuffer/BinaryParser.h +++ b/src/GCodes/GCodeBuffer/BinaryParser.h @@ -72,7 +72,7 @@ private: GCodeException ConstructParseException(const char *str, uint32_t param) const noexcept; size_t AddPadding(size_t bytesRead) const noexcept { return (bytesRead + 3u) & (~3u); } - template void GetArray(T arr[], size_t& length, bool doPad) THROWS(GCodeException) SPEED_CRITICAL; + template void GetArray(T arr[], size_t& length, bool doPad, DataType type) THROWS(GCodeException) SPEED_CRITICAL; void WriteParameters(const StringRef& s, bool quoteStrings) const noexcept; size_t bufferLength; diff --git a/src/GCodes/GCodeBuffer/ExpressionParser.cpp b/src/GCodes/GCodeBuffer/ExpressionParser.cpp index 133ed763..0e3ac432 100644 --- a/src/GCodes/GCodeBuffer/ExpressionParser.cpp +++ b/src/GCodes/GCodeBuffer/ExpressionParser.cpp @@ -713,10 +713,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 fc8dc1b3..bfd4de4e 100644 --- a/src/GCodes/GCodeBuffer/ExpressionParser.h +++ b/src/GCodes/GCodeBuffer/ExpressionParser.h @@ -26,7 +26,7 @@ public: uint32_t ParseUnsigned() 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/GCodeBuffer/StringParser.cpp b/src/GCodes/GCodeBuffer/StringParser.cpp index 691be0ac..9247c577 100644 --- a/src/GCodes/GCodeBuffer/StringParser.cpp +++ b/src/GCodes/GCodeBuffer/StringParser.cpp @@ -1086,7 +1086,7 @@ void StringParser::GetFloatArray(float arr[], size_t& returnedLength, bool doPad { CheckArrayLength(length, returnedLength); arr[length++] = ReadFloatValue(); - if (gb.buffer[readPointer] != LIST_SEPARATOR) + if (gb.buffer[readPointer] != EXPRESSION_LIST_SEPARATOR && gb.buffer[readPointer] != LIST_SEPARATOR) { break; } @@ -1123,7 +1123,7 @@ void StringParser::GetIntArray(int32_t arr[], size_t& returnedLength, bool doPad CheckArrayLength(length, returnedLength); arr[length] = ReadIValue(); length++; - if (gb.buffer[readPointer] != LIST_SEPARATOR) + if (gb.buffer[readPointer] != EXPRESSION_LIST_SEPARATOR && gb.buffer[readPointer] != LIST_SEPARATOR) { break; } @@ -1159,7 +1159,7 @@ void StringParser::GetUnsignedArray(uint32_t arr[], size_t& returnedLength, bool CheckArrayLength(length, returnedLength); arr[length] = ReadUIValue(); length++; - if (gb.buffer[readPointer] != LIST_SEPARATOR) + if (gb.buffer[readPointer] != EXPRESSION_LIST_SEPARATOR && gb.buffer[readPointer] != LIST_SEPARATOR) { break; } @@ -1196,7 +1196,7 @@ void StringParser::GetDriverIdArray(DriverId arr[], size_t& returnedLength) THRO CheckArrayLength(length, returnedLength); arr[length] = ReadDriverIdValue(); length++; - if (gb.buffer[readPointer] != LIST_SEPARATOR) + if (gb.buffer[readPointer] != EXPRESSION_LIST_SEPARATOR && gb.buffer[readPointer] != LIST_SEPARATOR) { break; } diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp index 1a932bd0..9c716f3b 100644 --- a/src/GCodes/GCodes.cpp +++ b/src/GCodes/GCodes.cpp @@ -478,16 +478,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 894630b0..d5dc4af4 100644 --- a/src/GCodes/GCodes2.cpp +++ b/src/GCodes/GCodes2.cpp @@ -831,7 +831,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. @@ -849,7 +851,17 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx { String 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 3f991bf0..5bed126e 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 #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 *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 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(); -- cgit v1.2.3