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

SoftwareReset.h « src - github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 29c47d913babac7ac730c14035a02d62838ec553 (plain)
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
85
86
87
88
89
90
/*
 * 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,

	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.
// The SAM3X and SAM4E don't have EEPROM so we save the data to flash. This unfortunately means that it gets cleared
// every time we reprogram the firmware via bossa, but it can be retained when firmware updates are performed
// via the web interface. That's why it's a good idea to implement versioning here - increase these values
// whenever the fields of the following structs have changed.
//
// The SAM4E has a large page erase size (8K). For this reason we store the software reset data in the 512-byte user signature area
// instead, which doesn't get cleared when the Erase button is pressed. The SoftareResetData struct must have at least one 32-bit
// field to guarantee that values of this type will be 32-bit aligned. It must have no virtual members because it is read/written
// directly from/to flash memory.
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
	uint32_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
	uint32_t stack[23];							// stack when the exception occurred, with the program counter at the bottom

	bool isVacant() const;						// return true if this struct can be written without erasing it first
	void Populate(uint16_t reason, uint32_t time, const uint32_t *stk);

	static const uint16_t versionValue = 8;		// increment this whenever this struct changes
	static const uint16_t magicValue = 0x7D00 | versionValue;	// value we use to recognise that all the flash data has been written
	static const size_t numberOfSlots = 4;		// number of storage slots used to implement wear levelling - must fit in 512 bytes
#if SAM3XA
	static const uint32_t nvAddress = 0;		// must be 4-byte aligned
#endif

	static const char *const ReasonText[];
	static uint8_t extraDebugInfo;				// extra info for debugging can be stored here
};

#if SAM4E || SAM4S || SAME70
static_assert(SoftwareResetData::numberOfSlots * sizeof(SoftwareResetData) <= 512, "Can't fit software reset data in user signature area");
#else
static_assert(SoftwareResetData::numberOfSlots * sizeof(SoftwareResetData) <= FLASH_DATA_LENGTH, "NVData too large");
#endif

#endif /* SRC_SOFTWARERESET_H_ */