1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
/*
* SoftwareReset.h
*
* Created on: 15 Nov 2019
* Author: David
*/
#ifndef SRC_SOFTWARERESET_H_
#define SRC_SOFTWARERESET_H_
#include <RepRapFirmware.h>
#if SAM3XA
# include <DueFlashStorage.h>
#endif
// Enumeration describing the reasons for a software reset.
// The spin state gets or'ed into this, so keep the lower 5 bits unused.
// IMPORTANT! When changing this, also update table SoftwareResetReasonText
enum class SoftwareResetReason : uint16_t
{
user = 0u, // M999 command
erase = 1u << 5, // special M999 command to erase firmware and reset
NMI = 2u << 5,
hardFault = 3u << 5, // most exceptions get escalated to a hard fault
stuckInSpin = 4u << 5, // we got stuck in a Spin() function in the Main task for too long
wdtFault = 5u << 5, // secondary watchdog
usageFault = 6u << 5,
otherFault = 7u << 5,
stackOverflow = 8u << 5, // FreeRTOS detected stack overflow
assertCalled = 9u << 5, // FreeRTOS assertion failure
heaterWatchdog = 10u << 5, // the Heat task didn't kick the watchdog often enough
memFault = 11u << 5, // the MPU raised a fault
terminateCalled = 12u << 5, // std::terminate was called
pureOrDeletedVirtual = 13u << 5,
outOfMemory = 14u << 5,
//unused = 15u << 5,
mainReasonMask = 0x0F << 5, // mask to pick out the main reason in a uint16_t
// Bits that are or'ed in
unusedBit = 0x0200, // spare bit
unused2 = 0x0400, // spare bit
inAuxOutput = 0x0800, // this bit is or'ed in if we were in aux output at the time
unused_was_inLwipSpin = 0x2000, // no longer used
inUsbOutput = 0x4000, // this bit is or'ed in if we were in USB output at the time
deliberate = 0x8000 // this but it or'ed in if we deliberately caused a fault
};
// These are the structures used to hold our non-volatile data.
// We store the software reset data in the 512-byte user signature area of the SAM4E, SAM4S and SAME70 processors.
// It must be a multiple of 4 bytes long.
struct SoftwareResetData
{
uint16_t magic; // the magic number, including the version
uint16_t resetReason; // this records why we did a software reset, for diagnostic purposes
int32_t neverUsedRam; // the amount of never used RAM at the last abnormal software reset
uint32_t hfsr; // hard fault status register
uint32_t cfsr; // configurable fault status register
uint32_t icsr; // interrupt control and state register
uint32_t bfar; // bus fault address register
uint32_t sp; // stack pointer
uint32_t when; // value of the RTC when the software reset occurred
uint32_t taskName; // first 4 bytes of the task name, or 'none'
uint32_t stackOffset; // how many spare words of stack the running task has
uint32_t stackMarkerValid : 1, // true if the stack low marker wasn't overwritten
spare : 31; // unused at present
// The stack length is set to 27 words because that is the most we can print in a single message using our 256-byte format buffer
uint32_t stack[27]; // stack when the exception occurred, with the link register and program counter at the bottom
bool IsVacant() const noexcept; // return true if this struct can be written without erasing it first
bool IsValid() const noexcept { return magic == magicValue; }
void Clear() noexcept;
void Populate(uint16_t reason, const uint32_t *stk) noexcept;
void Print(MessageType mtype, unsigned int slot) const noexcept;
static constexpr uint16_t versionValue = 9; // increment this whenever this struct changes
static constexpr uint16_t magicValue = 0x7D00 | versionValue; // value we use to recognise that all the flash data has been written
static const char *const ReasonText[];
static uint8_t extraDebugInfo; // 3 bits of extra info for debugging can be stored here
};
#endif /* SRC_SOFTWARERESET_H_ */
|