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

github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Crocker <dcrocker@eschertech.com>2018-04-06 00:38:19 +0300
committerDavid Crocker <dcrocker@eschertech.com>2018-04-06 00:38:19 +0300
commitd4b10780d217244008dee464a45823cf3416f53b (patch)
tree857f3dbabd03c35ee297e33b38dc0debf581f692
parenta2ecb67c8a8c08f1d5fcb455378e000066957ff2 (diff)
More RTOS work again
Increased Heat task stack to avoid crash when tuning a heater Protected vsnprintf etc. from reentrancy Use scheduler suspension instead of disabling interrupts for most critical sections
-rw-r--r--EdgeRelease/Duet2CombinedFirmware.binbin371924 -> 372172 bytes
-rw-r--r--src/BugList.txt5
-rw-r--r--src/GCodes/GCodeBuffer.cpp2
-rw-r--r--src/Heating/Heat.cpp2
-rw-r--r--src/Libraries/General/IP4String.cpp6
-rw-r--r--src/Libraries/General/StringRef.cpp46
-rw-r--r--src/Libraries/General/StringRef.h5
-rw-r--r--src/Libraries/General/strtod.cpp5
-rw-r--r--src/Memory usage.odsbin17473 -> 18704 bytes
-rw-r--r--src/Movement/BedProbing/Grid.cpp4
-rw-r--r--src/Movement/DDA.h2
-rw-r--r--src/Networking/HttpResponder.cpp4
-rw-r--r--src/Networking/HttpResponder.h4
-rw-r--r--src/Networking/NetworkResponder.h2
-rw-r--r--src/OutputMemory.cpp44
-rw-r--r--src/OutputMemory.h33
-rw-r--r--src/Platform.h6
-rw-r--r--src/RTOS work pending.txt6
-rw-r--r--src/RTOSIface.h48
-rw-r--r--src/Tasks.cpp7
-rw-r--r--src/Tools/Tool.cpp4
-rw-r--r--src/Version.h2
22 files changed, 153 insertions, 84 deletions
diff --git a/EdgeRelease/Duet2CombinedFirmware.bin b/EdgeRelease/Duet2CombinedFirmware.bin
index 4eb54bf8..e2153bb6 100644
--- a/EdgeRelease/Duet2CombinedFirmware.bin
+++ b/EdgeRelease/Duet2CombinedFirmware.bin
Binary files differ
diff --git a/src/BugList.txt b/src/BugList.txt
index ee25f57a..9b77d7cc 100644
--- a/src/BugList.txt
+++ b/src/BugList.txt
@@ -111,6 +111,7 @@ Remaining:
- [done in 2.0, test] Allow Z jerk down to 0.2mm/sec
- [done in 2.0, ok] BUG: no call to HttpResponder::CheckSessions
- BUG: G29 height map is way below bed. Happened on Ormerod. When probing the bed with simple G30 and compensation is applied, correct for the height map offset
+- Motor stall detection Z probe. Run deploy/retract macros before/after each probe, as for bltouch, or not?
- Unexpected heaters off/tool selection behaviour, https://www.duet3d.com/forum/thread.php?pid=43059#p43059
- warn when using : where ; was probably meant
- check out G30 H parameter, https://www.duet3d.com/forum/thread.php?pid=42322#p42322
@@ -131,6 +132,8 @@ Remaining:
- apostrophe in quoted filename
- looks like we get a Pop underflow message when you send DWC jog commands and axes are not homed
- Add warning message when print exceeds bounds
+- Does bltouch need a default recovery time?
+- Should bltouch use digital probe mode? Some users having problems with P25 in G31 command.
- How should we lift X on a CoreXZ printer before homing?
- if a homing command in an SD print file is aborted due to e.g. G1 Z5 in the homing file, error message should be written to both DWC and PanelDue
@@ -203,5 +206,3 @@ Later versions:
- Add T parameter to M207
- look at supporting SIZE in FTP
- Make mp.delta.hmz0sK, hmz0scK and dsk 64-bit in SAM4E versions, to increase movement limit - also increase K2?
-
-- SAME7 boot loader - could base on SAM-BA, see http://hobbygenius.co.uk/blog/1633
diff --git a/src/GCodes/GCodeBuffer.cpp b/src/GCodes/GCodeBuffer.cpp
index cdef1518..8877a83a 100644
--- a/src/GCodes/GCodeBuffer.cpp
+++ b/src/GCodes/GCodeBuffer.cpp
@@ -262,7 +262,7 @@ bool GCodeBuffer::LineFinished()
{
if (hadLineNumber)
{
- snprintf(gcodeBuffer, ARRAY_SIZE(gcodeBuffer), "M998 P%u", lineNumber); // request resend
+ SafeSnprintf(gcodeBuffer, ARRAY_SIZE(gcodeBuffer), "M998 P%u", lineNumber); // request resend
}
else
{
diff --git a/src/Heating/Heat.cpp b/src/Heating/Heat.cpp
index d1e345c0..9db52383 100644
--- a/src/Heating/Heat.cpp
+++ b/src/Heating/Heat.cpp
@@ -33,7 +33,7 @@ Licence: GPL
# include "Tasks.h"
-constexpr uint32_t HeaterTaskStackWords = 128; // task stack size in dwords
+constexpr uint32_t HeaterTaskStackWords = 400; // task stack size in dwords, must be large enough for auto tuning
static Task<HeaterTaskStackWords> heaterTask;
extern "C" void HeaterTask(void * pvParameters)
diff --git a/src/Libraries/General/IP4String.cpp b/src/Libraries/General/IP4String.cpp
index 7f03e836..722e5fa2 100644
--- a/src/Libraries/General/IP4String.cpp
+++ b/src/Libraries/General/IP4String.cpp
@@ -6,16 +6,16 @@
*/
#include "IP4String.h"
-#include <cstdio>
+#include "StringRef.h"
IP4String::IP4String(const uint8_t ip[4])
{
- snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
+ SafeSnprintf(buf, sizeof(buf)/sizeof(buf[0]), "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
}
IP4String::IP4String(uint32_t ip)
{
- snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%u.%u.%u.%u",
+ SafeSnprintf(buf, sizeof(buf)/sizeof(buf[0]), "%u.%u.%u.%u",
(unsigned int)(ip & 0xFFu), (unsigned int)((ip >> 8) & 0xFFu), (unsigned int)((ip >> 16) & 0xFFu), (unsigned int)((ip >> 24) & 0xFFu));
}
diff --git a/src/Libraries/General/StringRef.cpp b/src/Libraries/General/StringRef.cpp
index a469cec1..5f9c99fe 100644
--- a/src/Libraries/General/StringRef.cpp
+++ b/src/Libraries/General/StringRef.cpp
@@ -10,6 +10,10 @@
#include <cstdio>
#include "WMath.h"
+#ifdef RTOS
+# include "RTOSIface.h"
+#endif
+
// Need to define strnlen here because it isn't ISO standard
size_t strnlen(const char *s, size_t n)
{
@@ -21,6 +25,36 @@ size_t strnlen(const char *s, size_t n)
return rslt;
}
+// Thread safe version of vsnprintf. The standard one uses a buffer in the _reent structure.
+extern "C" int SafeVsnprintf(char* buffer, size_t buf_size, const char* format, va_list vlist)
+{
+#ifdef RTOS
+ TaskCriticalSectionLocker lock;
+#endif
+ return vsnprintf(buffer, buf_size, format, vlist);
+}
+
+extern "C" int SafeSnprintf(char* buffer, size_t buf_size, const char* format, ...)
+{
+ va_list vargs;
+ va_start(vargs, format);
+ const int ret = SafeVsnprintf(buffer, buf_size, format, vargs);
+ va_end(vargs);
+ return ret;
+}
+
+extern "C" int SafeSscanf(const char* s, const char* format, ...)
+{
+ va_list vargs;
+ va_start(vargs, format);
+#ifdef RTOS
+ TaskCriticalSectionLocker lock;
+#endif
+ const int ret = vsscanf(s, format, vargs);
+ va_end(vargs);
+ return ret;
+}
+
//*************************************************************************************************
// StringRef class member implementations
@@ -33,14 +67,14 @@ int StringRef::printf(const char *fmt, ...) const
{
va_list vargs;
va_start(vargs, fmt);
- const int ret = vsnprintf(p, len, fmt, vargs);
+ const int ret = SafeVsnprintf(p, len, fmt, vargs);
va_end(vargs);
return ret;
}
int StringRef::vprintf(const char *fmt, va_list vargs) const
{
- return vsnprintf(p, len, fmt, vargs);
+ return SafeVsnprintf(p, len, fmt, vargs);
}
int StringRef::catf(const char *fmt, ...) const
@@ -50,7 +84,7 @@ int StringRef::catf(const char *fmt, ...) const
{
va_list vargs;
va_start(vargs, fmt);
- const int ret = vsnprintf(p + n, len - n, fmt, vargs);
+ const int ret = SafeVsnprintf(p + n, len - n, fmt, vargs);
va_end(vargs);
return ret + n;
}
@@ -62,7 +96,7 @@ int StringRef::vcatf(const char *fmt, va_list vargs) const
const size_t n = strlen();
if (n + 1 < len) // if room for at least 1 more character and a null
{
- return vsnprintf(p + n, len - n, fmt, vargs) + n;
+ return SafeVsnprintf(p + n, len - n, fmt, vargs) + n;
}
return 0;
}
@@ -129,7 +163,3 @@ bool StringRef::Prepend(const char *src) const
}
// End
-
-
-
-
diff --git a/src/Libraries/General/StringRef.h b/src/Libraries/General/StringRef.h
index 6c74fd71..c8800aaa 100644
--- a/src/Libraries/General/StringRef.h
+++ b/src/Libraries/General/StringRef.h
@@ -15,6 +15,11 @@
// Need to declare strnlen here because it isn't ISO standard
size_t strnlen(const char *s, size_t n);
+// Thread safe versions of vsnprintf etc.
+extern "C" int SafeVsnprintf(char* buffer, size_t buf_size, const char* format, va_list vlist);
+extern "C" int SafeSnprintf(char* buffer, size_t buf_size, const char* format, ...) __attribute__ ((format (printf, 3, 4)));
+extern "C" int SafeSscanf(const char* s, const char* format, ...) __attribute__ ((format (scanf, 2, 3)));
+
// Class to describe a string buffer, including its length. This saves passing buffer lengths around everywhere.
class StringRef
{
diff --git a/src/Libraries/General/strtod.cpp b/src/Libraries/General/strtod.cpp
index cc7ef924..8cc7b963 100644
--- a/src/Libraries/General/strtod.cpp
+++ b/src/Libraries/General/strtod.cpp
@@ -9,9 +9,8 @@
* 2. It allocates and releases heap memory, which is not nice.
*
* Limitations of this version
- * 1. Rounding to nearest float may not always be correct.
- * 2. Doesn't handle more than 9 digits (excluding any leading zeros) before the decimal point. Numbers greater than 2^64-1 or less then -2^64-1
- * will be incorrectly converted unless expressed in scientific notation.
+ * 1. Rounding to nearest double may not always be correct.
+ * 2. May not handle overflow for stupidly large numbers correctly.
*/
#include <cstdlib> // to pull in the standard declarations of strtod etc.
diff --git a/src/Memory usage.ods b/src/Memory usage.ods
index 84f8b90e..5a24f973 100644
--- a/src/Memory usage.ods
+++ b/src/Memory usage.ods
Binary files differ
diff --git a/src/Movement/BedProbing/Grid.cpp b/src/Movement/BedProbing/Grid.cpp
index c994699a..31e39218 100644
--- a/src/Movement/BedProbing/Grid.cpp
+++ b/src/Movement/BedProbing/Grid.cpp
@@ -105,11 +105,11 @@ bool GridDefinition::ReadParameters(const StringRef& s, int version)
switch (version)
{
case 1:
- ok = (sscanf(s.c_str(), "%f,%f,%f,%f,%f,%f,%f,%lu,%lu", &xMin, &xMax, &yMin, &yMax, &radius, &xSpacing, &ySpacing, &numX, &numY) == 9);
+ ok = (SafeSscanf(s.c_str(), "%f,%f,%f,%f,%f,%f,%f,%lu,%lu", &xMin, &xMax, &yMin, &yMax, &radius, &xSpacing, &ySpacing, &numX, &numY) == 9);
break;
case 0:
- ok = (sscanf(s.c_str(), "%f,%f,%f,%f,%f,%f,%lu,%lu", &xMin, &xMax, &yMin, &yMax, &radius, &xSpacing, &numX, &numY) == 8);
+ ok = (SafeSscanf(s.c_str(), "%f,%f,%f,%f,%f,%f,%lu,%lu", &xMin, &xMax, &yMin, &yMax, &radius, &xSpacing, &numX, &numY) == 8);
if (ok)
{
ySpacing = xSpacing;
diff --git a/src/Movement/DDA.h b/src/Movement/DDA.h
index 72124b30..e1c2e2f5 100644
--- a/src/Movement/DDA.h
+++ b/src/Movement/DDA.h
@@ -206,7 +206,7 @@ private:
// These are calculated from the above and used in the ISR, so they are set up by Prepare()
uint32_t clocksNeeded; // in clocks
uint32_t moveStartTime; // clock count at which the move was started
- uint32_t startSpeedTimesCdivA; // the number of clocks it would have taken t reach the start speed form rest
+ uint32_t startSpeedTimesCdivA; // the number of clocks it would have taken to reach the start speed from rest
uint32_t topSpeedTimesCdivAPlusDecelStartClocks;
int32_t extraAccelerationClocks; // the additional number of clocks needed because we started the move at less than topSpeed. Negative after ReduceHomingSpeed has been called.
diff --git a/src/Networking/HttpResponder.cpp b/src/Networking/HttpResponder.cpp
index 6b2d9e90..d29b8008 100644
--- a/src/Networking/HttpResponder.cpp
+++ b/src/Networking/HttpResponder.cpp
@@ -1287,8 +1287,8 @@ HttpResponder::HttpSession HttpResponder::sessions[MaxHttpSessions];
unsigned int HttpResponder::numSessions = 0;
unsigned int HttpResponder::clientsServed = 0;
-uint32_t HttpResponder::seq = 0;
-OutputStack HttpResponder::gcodeReply;
+volatile uint32_t HttpResponder::seq = 0;
+volatile OutputStack HttpResponder::gcodeReply;
Mutex HttpResponder::gcodeReplyMutex;
// End
diff --git a/src/Networking/HttpResponder.h b/src/Networking/HttpResponder.h
index 939beca4..3b39a1cb 100644
--- a/src/Networking/HttpResponder.h
+++ b/src/Networking/HttpResponder.h
@@ -112,8 +112,8 @@ private:
static unsigned int clientsServed;
// Responses from GCodes class
- static uint32_t seq; // Sequence number for G-Code replies
- static OutputStack gcodeReply;
+ static volatile uint32_t seq; // Sequence number for G-Code replies
+ static volatile OutputStack gcodeReply;
static Mutex gcodeReplyMutex;
};
diff --git a/src/Networking/NetworkResponder.h b/src/Networking/NetworkResponder.h
index 6c03980c..6bda80e3 100644
--- a/src/Networking/NetworkResponder.h
+++ b/src/Networking/NetworkResponder.h
@@ -76,7 +76,7 @@ protected:
// Buffers for sending responses
OutputBuffer *outBuf;
- OutputStack outStack;
+ OutputStack outStack; // not volatile because only one task accesses it
FileStore *fileBeingSent;
NetworkBuffer *fileBuffer;
diff --git a/src/OutputMemory.cpp b/src/OutputMemory.cpp
index 5c2486ab..766ea98d 100644
--- a/src/OutputMemory.cpp
+++ b/src/OutputMemory.cpp
@@ -34,6 +34,8 @@ void OutputBuffer::IncreaseReferences(size_t refs)
{
if (refs > 0)
{
+ TaskCriticalSectionLocker lock;
+
for(OutputBuffer *item = this; item != nullptr; item = item->Next())
{
item->references += refs;
@@ -92,7 +94,7 @@ size_t OutputBuffer::printf(const char *fmt, ...)
char formatBuffer[FORMAT_STRING_LENGTH];
va_list vargs;
va_start(vargs, fmt);
- vsnprintf(formatBuffer, ARRAY_SIZE(formatBuffer), fmt, vargs);
+ SafeVsnprintf(formatBuffer, ARRAY_SIZE(formatBuffer), fmt, vargs);
va_end(vargs);
return copy(formatBuffer);
@@ -101,7 +103,7 @@ size_t OutputBuffer::printf(const char *fmt, ...)
size_t OutputBuffer::vprintf(const char *fmt, va_list vargs)
{
char formatBuffer[FORMAT_STRING_LENGTH];
- vsnprintf(formatBuffer, ARRAY_SIZE(formatBuffer), fmt, vargs);
+ SafeVsnprintf(formatBuffer, ARRAY_SIZE(formatBuffer), fmt, vargs);
return cat(formatBuffer);
}
@@ -111,7 +113,7 @@ size_t OutputBuffer::catf(const char *fmt, ...)
char formatBuffer[FORMAT_STRING_LENGTH];
va_list vargs;
va_start(vargs, fmt);
- vsnprintf(formatBuffer, ARRAY_SIZE(formatBuffer), fmt, vargs);
+ SafeVsnprintf(formatBuffer, ARRAY_SIZE(formatBuffer), fmt, vargs);
va_end(vargs);
formatBuffer[ARRAY_UPB(formatBuffer)] = 0;
@@ -342,11 +344,11 @@ bool OutputBuffer::WriteToFile(FileData& f) const
}
}
-// Allocates an output buffer instance which can be used for (large) string outputs. This must be thread safe.
+// Allocates an output buffer instance which can be used for (large) string outputs. This must be thread safe. Not safe to call from interrupts!
/*static*/ bool OutputBuffer::Allocate(OutputBuffer *&buf)
{
{
- CriticalSectionLocker lock;
+ TaskCriticalSectionLocker lock;
buf = freeOutputBuffers;
if (buf != nullptr)
@@ -439,7 +441,7 @@ bool OutputBuffer::WriteToFile(FileData& f) const
// Releases an output buffer instance and returns the next entry from the chain
/*static */ OutputBuffer *OutputBuffer::Release(OutputBuffer *buf)
{
- CriticalSectionLocker lock;
+ TaskCriticalSectionLocker lock;
OutputBuffer * const nextBuffer = buf->next;
// If this one is reused by another piece of code, don't free it up
@@ -476,7 +478,7 @@ bool OutputBuffer::WriteToFile(FileData& f) const
// OutputStack class implementation
// Push an OutputBuffer chain to the stack
-void OutputStack::Push(OutputBuffer *buffer)
+void OutputStack::Push(OutputBuffer *buffer) volatile
{
if (count == OUTPUT_STACK_DEPTH)
{
@@ -488,20 +490,20 @@ void OutputStack::Push(OutputBuffer *buffer)
if (buffer != nullptr)
{
buffer->whenQueued = millis();
- CriticalSectionLocker lock;
+ TaskCriticalSectionLocker lock;
items[count++] = buffer;
}
}
-// Pop an OutputBuffer chain or return NULL if none is available
-OutputBuffer *OutputStack::Pop()
+// Pop an OutputBuffer chain or return nullptr if none is available
+OutputBuffer *OutputStack::Pop() volatile
{
if (count == 0)
{
return nullptr;
}
- CriticalSectionLocker lock;
+ TaskCriticalSectionLocker lock;
OutputBuffer *item = items[0];
for(size_t i = 1; i < count; i++)
{
@@ -513,7 +515,7 @@ OutputBuffer *OutputStack::Pop()
}
// Returns the first item from the stack or NULL if none is available
-OutputBuffer *OutputStack::GetFirstItem() const
+OutputBuffer *OutputStack::GetFirstItem() const volatile
{
if (count == 0)
{
@@ -523,9 +525,9 @@ OutputBuffer *OutputStack::GetFirstItem() const
}
// Set the first item of the stack. If it's NULL, then the first item will be removed
-void OutputStack::SetFirstItem(OutputBuffer *buffer)
+void OutputStack::SetFirstItem(OutputBuffer *buffer) volatile
{
- CriticalSectionLocker lock;
+ TaskCriticalSectionLocker lock;
if (buffer == nullptr)
{
// If buffer is NULL, then the first item is removed from the stack
@@ -544,7 +546,7 @@ void OutputStack::SetFirstItem(OutputBuffer *buffer)
}
// Returns the last item from the stack or NULL if none is available
-OutputBuffer *OutputStack::GetLastItem() const
+OutputBuffer *OutputStack::GetLastItem() const volatile
{
if (count == 0)
{
@@ -554,11 +556,11 @@ OutputBuffer *OutputStack::GetLastItem() const
}
// Get the total length of all queued buffers
-size_t OutputStack::DataLength() const
+size_t OutputStack::DataLength() const volatile
{
size_t totalLength = 0;
- CriticalSectionLocker lock;
+ TaskCriticalSectionLocker lock;
for(size_t i = 0; i < count; i++)
{
totalLength += items[i]->Length();
@@ -569,7 +571,7 @@ size_t OutputStack::DataLength() const
// Append another OutputStack to this instance. If no more space is available,
// all OutputBuffers that can't be added are automatically released
-void OutputStack::Append(OutputStack& stack)
+void OutputStack::Append(volatile OutputStack& stack) volatile
{
for(size_t i = 0; i < stack.count; i++)
{
@@ -586,9 +588,9 @@ void OutputStack::Append(OutputStack& stack)
}
// Increase the number of references for each OutputBuffer on the stack
-void OutputStack::IncreaseReferences(size_t num)
+void OutputStack::IncreaseReferences(size_t num) volatile
{
- CriticalSectionLocker lock;
+ TaskCriticalSectionLocker lock;
for(size_t i = 0; i < count; i++)
{
items[i]->IncreaseReferences(num);
@@ -596,7 +598,7 @@ void OutputStack::IncreaseReferences(size_t num)
}
// Release all buffers and clean up
-void OutputStack::ReleaseAll()
+void OutputStack::ReleaseAll() volatile
{
for(size_t i = 0; i < count; i++)
{
diff --git a/src/OutputMemory.h b/src/OutputMemory.h
index d38ab645..d060ff4e 100644
--- a/src/OutputMemory.h
+++ b/src/OutputMemory.h
@@ -94,9 +94,9 @@ class OutputBuffer
size_t dataLength, bytesRead;
bool isReferenced;
- size_t references;
+ volatile size_t references;
- static OutputBuffer * volatile freeOutputBuffers; // Messages may also be sent by ISRs,
+ static OutputBuffer * volatile freeOutputBuffers; // Messages may be sent by multiple tasks
static volatile size_t usedOutputBuffers; // so make these volatile.
static volatile size_t maxUsedOutputBuffers;
};
@@ -106,49 +106,50 @@ inline uint32_t OutputBuffer::GetAge() const
return millis() - whenQueued;
}
-// This class is used to manage references to OutputBuffer chains for all output destinations
+// This class is used to manage references to OutputBuffer chains for all output destinations.
+// Note that OutputStack objects should normally be declared volatile.
class OutputStack
{
public:
OutputStack() : count(0) { }
// Is there anything on this stack?
- bool IsEmpty() const { return count == 0; }
+ bool IsEmpty() const volatile { return count == 0; }
// Clear the reference list
- void Clear() { count = 0; }
+ void Clear() volatile { count = 0; }
// Push an OutputBuffer chain
- void Push(OutputBuffer *buffer);
+ void Push(OutputBuffer *buffer) volatile;
// Pop an OutputBuffer chain or return NULL if none is available
- OutputBuffer *Pop();
+ OutputBuffer *Pop() volatile;
// Returns the first item from the stack or NULL if none is available
- OutputBuffer *GetFirstItem() const;
+ OutputBuffer *GetFirstItem() const volatile;
// Set the first item of the stack. If it's NULL, then the first item will be removed
- void SetFirstItem(OutputBuffer *buffer);
+ void SetFirstItem(OutputBuffer *buffer) volatile;
// Returns the last item from the stack or NULL if none is available
- OutputBuffer *GetLastItem() const;
+ OutputBuffer *GetLastItem() const volatile;
// Get the total length of all queued buffers
- size_t DataLength() const;
+ size_t DataLength() const volatile;
// Append another OutputStack to this instance. If no more space is available,
// all OutputBuffers that can't be added are automatically released
- void Append(OutputStack& stack);
+ void Append(volatile OutputStack& stack) volatile;
// Increase the number of references for each OutputBuffer on the stack
- void IncreaseReferences(size_t num);
+ void IncreaseReferences(size_t num) volatile;
// Release all buffers and clean up
- void ReleaseAll();
+ void ReleaseAll() volatile;
private:
- volatile size_t count;
- OutputBuffer * volatile items[OUTPUT_STACK_DEPTH];
+ size_t count;
+ OutputBuffer * items[OUTPUT_STACK_DEPTH];
};
#endif /* OUTPUTMEMORY_H_ */
diff --git a/src/Platform.h b/src/Platform.h
index b70c875d..2cd061e4 100644
--- a/src/Platform.h
+++ b/src/Platform.h
@@ -821,18 +821,18 @@ private:
uint32_t baudRates[NUM_SERIAL_CHANNELS];
uint8_t commsParams[NUM_SERIAL_CHANNELS];
- OutputStack auxOutput;
+ volatile OutputStack auxOutput;
Mutex auxMutex;
OutputBuffer *auxGCodeReply; // G-Code reply for AUX devices (special one because it is actually encapsulated before sending)
uint32_t auxSeq; // Sequence number for AUX devices
bool auxDetected; // Have we processed at least one G-Code from an AUX device?
#ifdef SERIAL_AUX2_DEVICE
- OutputStack aux2Output;
+ volatile OutputStack aux2Output;
Mutex aux2Mutex;
#endif
- OutputStack usbOutput;
+ volatile OutputStack usbOutput;
Mutex usbMutex;
// Files
diff --git a/src/RTOS work pending.txt b/src/RTOS work pending.txt
index ed8a5eae..3eccaf98 100644
--- a/src/RTOS work pending.txt
+++ b/src/RTOS work pending.txt
@@ -28,15 +28,19 @@ Run all network responders as separate tasks? Would need mutex on network interf
Bugs
[done] IAP fails to update firmware
-M122 output is too big for the available buffers, unless the Network task reads the output fast enough
+[done I think] M122 output is too big for the available buffers, unless the Network task reads the output fast enough
[probably related to above] Duet WiFi gets into a state in which it returns empty JSON messages after sending M122 from DWC. Output buffer starvation?
[done] Disconnects when getting file info forCandyBowlx8comments.gcode when running RTOS build
[seems better now] File upload speed is a little lower when using RTOS - may be fixed when network is a separate task
[seems ok now, was probably main stack overslow] Report that Pause works, but then hangs
+[done] Heater tuning crashes the firmware
+[believed fixed] DWC disconnects randomly with JSON parse errors
Deferred work
+Use our own vsnprintf, and stop using sscanf. Should save a significant amount of stack space.
+Check whether we use any time conversion functoins that use _reent
SAME70 uses a different memory model i.e. not strongly-ordered. Does this have any consequences for the code so far?
Are there any aspects of Platform that are not thread-safe? e.g. GCodes setting multiple interdependent variables while network reports on them?
Use a mutex to protect HSMCI from reentrant calls (only needed if/when we support more than one HSMCI volume, which is unlikely but possoible on the SAME70)
diff --git a/src/RTOSIface.h b/src/RTOSIface.h
index a9658beb..0e7d5afd 100644
--- a/src/RTOSIface.h
+++ b/src/RTOSIface.h
@@ -118,32 +118,55 @@ namespace RTOSIface
TaskHandle GetCurrentTask();
#ifndef RTOS
- static volatile unsigned int criticalSectionNesting = 0;
+ static volatile unsigned int interruptCriticalSectionNesting = 0;
#endif
- inline void EnterCriticalSection()
+ // Enter a critical section, where modificatio0n to variables by interrupts (and perhaps also other tasks) must be avoided
+ inline void EnterInterruptCriticalSection()
{
#ifdef RTOS
taskENTER_CRITICAL();
#else
cpu_irq_disable();
- ++criticalSectionNesting;
+ ++interruptCriticalSectionNesting;
#endif
}
- inline void LeaveCriticalSection()
+ // Leave an interrupt-critical section
+ inline void LeaveInterruptCriticalSection()
{
#ifdef RTOS
taskEXIT_CRITICAL();
#else
- --criticalSectionNesting;
- if (criticalSectionNesting == 0)
+ --interruptCriticalSectionNesting;
+ if (interruptCriticalSectionNesting == 0)
{
cpu_irq_enable();
}
#endif
}
+ // Enter a task-critical region. Used to protect concurrent access to variable form different tasks, where the variable are ont used/modified by interrupts.
+ inline void EnterTaskCriticalSection()
+ {
+#ifdef RTOS
+ vTaskSuspendAll();
+#else
+ // nothing to do here because there is on task preemption
+#endif
+ }
+
+ // Exit a task-critical region, returning true if a task switch occurred
+ inline bool LeaveTaskCriticalSection()
+ {
+#ifdef RTOS
+ return xTaskResumeAll() == pdTRUE;;
+#else
+ // nothing to do here because there is on task preemption
+ return false;
+#endif
+ }
+
inline void Yield()
{
#ifdef RTOS
@@ -152,11 +175,18 @@ namespace RTOSIface
}
}
-class CriticalSectionLocker
+class InterruptCriticalSectionLocker
+{
+public:
+ InterruptCriticalSectionLocker() { RTOSIface::EnterInterruptCriticalSection(); }
+ ~InterruptCriticalSectionLocker() { (void)RTOSIface::LeaveInterruptCriticalSection(); }
+};
+
+class TaskCriticalSectionLocker
{
public:
- CriticalSectionLocker() { RTOSIface::EnterCriticalSection(); }
- ~CriticalSectionLocker() { RTOSIface::LeaveCriticalSection(); }
+ TaskCriticalSectionLocker() { RTOSIface::EnterTaskCriticalSection(); }
+ ~TaskCriticalSectionLocker() { RTOSIface::LeaveTaskCriticalSection(); }
};
#endif /* SRC_RTOSIFACE_H_ */
diff --git a/src/Tasks.cpp b/src/Tasks.cpp
index c0cc45d4..d70de1f2 100644
--- a/src/Tasks.cpp
+++ b/src/Tasks.cpp
@@ -28,7 +28,6 @@ constexpr unsigned int MainTaskStackWords = 2100;
static Task<MainTaskStackWords> mainTask;
static Mutex spiMutex;
static Mutex mallocMutex;
-static bool rtosRunning = false;
extern "C" void MainTask(void * pvParameters);
@@ -36,7 +35,7 @@ extern "C" void MainTask(void * pvParameters);
// We must use a recursive mutex for it.
extern "C" void __malloc_lock ( struct _reent *_r )
{
- if (rtosRunning)
+ if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) // don't take mutex if scheduler not started or suspended
{
mallocMutex.Take();
}
@@ -44,7 +43,7 @@ extern "C" void __malloc_lock ( struct _reent *_r )
extern "C" void __malloc_unlock ( struct _reent *_r )
{
- if (rtosRunning)
+ if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) // don't release mutex if scheduler not started or suspended
{
mallocMutex.Release();
}
@@ -93,8 +92,6 @@ extern "C" void AppMain()
extern "C" void MainTask(void *pvParameters)
{
mallocMutex.Create();
- rtosRunning = true;
-
spiMutex.Create();
#endif
reprap.Init();
diff --git a/src/Tools/Tool.cpp b/src/Tools/Tool.cpp
index ab3649c2..f340d4f8 100644
--- a/src/Tools/Tool.cpp
+++ b/src/Tools/Tool.cpp
@@ -69,7 +69,7 @@ Tool * Tool::freelist = nullptr;
Tool *t;
{
- CriticalSectionLocker lock;
+ TaskCriticalSectionLocker lock;
t = freelist;
if (t != nullptr)
{
@@ -151,7 +151,7 @@ Tool * Tool::freelist = nullptr;
t->name = nullptr;
t->filament = nullptr;
- CriticalSectionLocker lock;
+ TaskCriticalSectionLocker lock;
t->next = freelist;
freelist = t;
}
diff --git a/src/Version.h b/src/Version.h
index 49452175..e9fafac7 100644
--- a/src/Version.h
+++ b/src/Version.h
@@ -19,7 +19,7 @@
#endif
#ifndef DATE
-# define DATE "2018-04-04b3"
+# define DATE "2018-04-05b2"
#endif
#define AUTHORS "reprappro, dc42, chrishamm, t3p3, dnewman"