diff options
author | David Crocker <dcrocker@eschertech.com> | 2021-05-23 21:39:55 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2021-05-23 21:39:55 +0300 |
commit | 214d486c4c9fe3639f2f861605c89d1b0dc56a8f (patch) | |
tree | be75195ae98c77698a5951af7df71e386a342d92 | |
parent | f055e129c4047bdba729db1c6ace6eb0a0a76698 (diff) |
Bug fix to crash handler (still 3.3RC3 candidate)
Tyhe crash handler was allocating the buffer for reading/writing flash
memory on the stack. When the crash handler was called in-process (e.g.
due to an assertion failure or a memory allocation failure), this
typically corrupted the task details.
-rw-r--r-- | src/Hardware/ExceptionHandlers.cpp | 7 | ||||
-rw-r--r-- | src/Platform/Tasks.cpp | 26 | ||||
-rw-r--r-- | src/Platform/Tasks.h | 1 |
3 files changed, 31 insertions, 3 deletions
diff --git a/src/Hardware/ExceptionHandlers.cpp b/src/Hardware/ExceptionHandlers.cpp index 7253f5cf..640c0a41 100644 --- a/src/Hardware/ExceptionHandlers.cpp +++ b/src/Hardware/ExceptionHandlers.cpp @@ -8,6 +8,7 @@ #include "ExceptionHandlers.h" #include <Platform/RepRap.h> #include <Platform/Platform.h> +#include <Platform/Tasks.h> #include <Hardware/NonVolatileMemory.h> #include <Cache.h> #if SAME70 || SAM4S || SAM4E @@ -62,10 +63,10 @@ } // Record the reason for the software reset - NonVolatileMemory mem; - SoftwareResetData * const srd = mem.AllocateResetDataSlot(); + NonVolatileMemory * const mem = new(Tasks::GetNVMBuffer(stk)) NonVolatileMemory; + SoftwareResetData * const srd = mem->AllocateResetDataSlot(); srd->Populate(fullReason, stk); - mem.EnsureWritten(); + mem->EnsureWritten(); } #if defined(__LPC17xx__) diff --git a/src/Platform/Tasks.cpp b/src/Platform/Tasks.cpp index e5b1331c..e433b8d8 100644 --- a/src/Platform/Tasks.cpp +++ b/src/Platform/Tasks.cpp @@ -11,6 +11,7 @@ #include <Cache.h> #include <Platform/TaskPriorities.h> #include <Hardware/SoftwareReset.h> +#include <Hardware/NonVolatileMemory.h> #include <Storage/CRC32.h> #include <Movement/StepTimer.h> @@ -102,6 +103,31 @@ extern "C" void ReleaseMallocMutex() noexcept } } +// Get a 4-byte aligned NonVolatileMemory buffer suitable for the crash handler to use for reading/writing flash memory. +// We don't want to use a static buffer because that is wasteful of RAM, given that only the crash handler uses it, we have interrupts disabled while we use it, +// and we reset immediately afterwards. +// Instead we use either the bottom or top of the main task stack. +// Parameter 'stk' is the stack we are interested in, which we must not overwrite. The caller is either using the same stack a little lower, or the exception stack. +void *Tasks::GetNVMBuffer(const uint32_t *stk) noexcept +{ + constexpr size_t stackAllowance = 128; + static_assert((sizeof(NonVolatileMemory) & 3) == 0); + static_assert(MainTaskStackWords * 4 >= 2 * sizeof(NonVolatileMemory) + stackAllowance + 4); + const char * const cStack = reinterpret_cast<const char*>(stk); + + // See if we can use the bottom of the main task stack + char *ret = (char *)&mainTask + sizeof(TaskBase); + if (cStack > ret + (sizeof(NonVolatileMemory) + stackAllowance + 4)) // allow space for the buffer + 128b in case we are on that stack + { + ret += 4; // the +4 is so that we leave the stack marker alone in case the main task raised the exception + } + else + { + ret += (MainTaskStackWords * 4) - sizeof(NonVolatileMemory); // use the top area instead + } + return ret; +} + // Application entry point [[noreturn]] void AppMain() noexcept { diff --git a/src/Platform/Tasks.h b/src/Platform/Tasks.h index aff42e38..f3f8b878 100644 --- a/src/Platform/Tasks.h +++ b/src/Platform/Tasks.h @@ -21,6 +21,7 @@ namespace Tasks const char* GetHeapTop() noexcept; Mutex *GetI2CMutex() noexcept; Mutex *GetFilamentsMutex() noexcept; + void *GetNVMBuffer(const uint32_t *stk) noexcept; } #if SUPPORT_CAN_EXPANSION |