summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chip/lm4/system.c40
-rw-r--r--chip/stm32/system.c39
-rw-r--r--common/system.c2
-rw-r--r--core/cortex-m/panic.c29
-rw-r--r--core/cortex-m/task.c2
-rw-r--r--core/cortex-m0/panic.c29
-rw-r--r--core/cortex-m0/task.c2
-rw-r--r--include/panic.h13
8 files changed, 136 insertions, 20 deletions
diff --git a/chip/lm4/system.c b/chip/lm4/system.c
index 78db1b38a3..38cde27e1c 100644
--- a/chip/lm4/system.c
+++ b/chip/lm4/system.c
@@ -10,6 +10,7 @@
#include "console.h"
#include "cpu.h"
#include "host_command.h"
+#include "panic.h"
#include "registers.h"
#include "system.h"
#include "task.h"
@@ -18,9 +19,14 @@
/* Indices for hibernate data registers */
enum hibdata_index {
- HIBDATA_INDEX_SCRATCHPAD, /* General-purpose scratchpad */
- HIBDATA_INDEX_WAKE, /* Wake reasons for hibernate */
- HIBDATA_INDEX_SAVED_RESET_FLAGS /* Saved reset flags */
+ HIBDATA_INDEX_SCRATCHPAD, /* General-purpose scratchpad */
+ HIBDATA_INDEX_WAKE, /* Wake reasons for hibernate */
+ HIBDATA_INDEX_SAVED_RESET_FLAGS, /* Saved reset flags */
+#ifdef CONFIG_SOFTWARE_PANIC
+ HIBDATA_INDEX_SAVED_PANIC_REASON, /* Saved panic reason */
+ HIBDATA_INDEX_SAVED_PANIC_INFO, /* Saved panic data */
+ HIBDATA_INDEX_SAVED_PANIC_EXCEPTION /* Saved panic exception code */
+#endif
};
/* Flags for HIBDATA_INDEX_WAKE */
@@ -385,6 +391,10 @@ void system_hibernate(uint32_t seconds, uint32_t microseconds)
void system_pre_init(void)
{
uint32_t hibctl;
+#ifdef CONFIG_SOFTWARE_PANIC
+ uint32_t reason, info;
+ uint8_t exception;
+#endif
/*
* Enable clocks to the hibernation module in run, sleep,
@@ -441,6 +451,19 @@ void system_pre_init(void)
check_reset_cause();
+#ifdef CONFIG_SOFTWARE_PANIC
+ /* Restore then clear saved panic reason */
+ reason = hibdata_read(HIBDATA_INDEX_SAVED_PANIC_REASON);
+ info = hibdata_read(HIBDATA_INDEX_SAVED_PANIC_INFO);
+ exception = hibdata_read(HIBDATA_INDEX_SAVED_PANIC_EXCEPTION);
+ if (reason || info || exception) {
+ panic_set_reason(reason, info, exception);
+ hibdata_write(HIBDATA_INDEX_SAVED_PANIC_REASON, 0);
+ hibdata_write(HIBDATA_INDEX_SAVED_PANIC_INFO, 0);
+ hibdata_write(HIBDATA_INDEX_SAVED_PANIC_EXCEPTION, 0);
+ }
+#endif
+
/* Initialize bootcfg if needed */
if (LM4_SYSTEM_BOOTCFG != CONFIG_BOOTCFG_VALUE) {
/* read-modify-write */
@@ -473,6 +496,17 @@ void system_reset(int flags)
hibdata_write(HIBDATA_INDEX_SAVED_RESET_FLAGS, save_flags);
if (flags & SYSTEM_RESET_HARD) {
+#ifdef CONFIG_SOFTWARE_PANIC
+ uint32_t reason, info;
+ uint8_t exception;
+
+ /* Panic data will be wiped by hard reset, so save it */
+ panic_get_reason(&reason, &info, &exception);
+ hibdata_write(HIBDATA_INDEX_SAVED_PANIC_REASON, reason);
+ hibdata_write(HIBDATA_INDEX_SAVED_PANIC_INFO, info);
+ hibdata_write(HIBDATA_INDEX_SAVED_PANIC_EXCEPTION, exception);
+#endif
+
/*
* Bounce through hibernate to trigger a hard reboot. Do
* not wake on wake pin, since we need the full duration.
diff --git a/chip/stm32/system.c b/chip/stm32/system.c
index 890c704924..0030e1a305 100644
--- a/chip/stm32/system.c
+++ b/chip/stm32/system.c
@@ -10,6 +10,7 @@
#include "cpu.h"
#include "flash.h"
#include "registers.h"
+#include "panic.h"
#include "system.h"
#include "task.h"
#include "util.h"
@@ -19,8 +20,8 @@
#define CONSOLE_BIT_MASK 0x8000
enum bkpdata_index {
- BKPDATA_INDEX_SCRATCHPAD, /* General-purpose scratchpad */
- BKPDATA_INDEX_SAVED_RESET_FLAGS,/* Saved reset flags */
+ BKPDATA_INDEX_SCRATCHPAD, /* General-purpose scratchpad */
+ BKPDATA_INDEX_SAVED_RESET_FLAGS, /* Saved reset flags */
BKPDATA_INDEX_VBNV_CONTEXT0,
BKPDATA_INDEX_VBNV_CONTEXT1,
BKPDATA_INDEX_VBNV_CONTEXT2,
@@ -29,6 +30,11 @@ enum bkpdata_index {
BKPDATA_INDEX_VBNV_CONTEXT5,
BKPDATA_INDEX_VBNV_CONTEXT6,
BKPDATA_INDEX_VBNV_CONTEXT7,
+#ifdef CONFIG_SOFTWARE_PANIC
+ BKPDATA_INDEX_SAVED_PANIC_REASON, /* Saved panic reason */
+ BKPDATA_INDEX_SAVED_PANIC_INFO, /* Saved panic data */
+ BKPDATA_INDEX_SAVED_PANIC_EXCEPTION, /* Saved panic exception code */
+#endif
};
/**
@@ -162,6 +168,11 @@ static void check_reset_cause(void)
void system_pre_init(void)
{
+#ifdef CONFIG_SOFTWARE_PANIC
+ uint16_t reason, info;
+ uint8_t exception;
+#endif
+
/* enable clock on Power module */
STM32_RCC_APB1ENR |= 1 << 28;
/* enable backup registers */
@@ -197,6 +208,19 @@ void system_pre_init(void)
#endif
check_reset_cause();
+
+#ifdef CONFIG_SOFTWARE_PANIC
+ /* Restore then clear saved panic reason */
+ reason = bkpdata_read(BKPDATA_INDEX_SAVED_PANIC_REASON);
+ info = bkpdata_read(BKPDATA_INDEX_SAVED_PANIC_INFO);
+ exception = bkpdata_read(BKPDATA_INDEX_SAVED_PANIC_EXCEPTION);
+ if (reason || info || exception) {
+ panic_set_reason(reason, info, exception);
+ bkpdata_write(BKPDATA_INDEX_SAVED_PANIC_REASON, 0);
+ bkpdata_write(BKPDATA_INDEX_SAVED_PANIC_INFO, 0);
+ bkpdata_write(BKPDATA_INDEX_SAVED_PANIC_EXCEPTION, 0);
+ }
+#endif
}
void system_reset(int flags)
@@ -223,6 +247,17 @@ void system_reset(int flags)
bkpdata_write(BKPDATA_INDEX_SAVED_RESET_FLAGS, save_flags | console_en);
if (flags & SYSTEM_RESET_HARD) {
+#ifdef CONFIG_SOFTWARE_PANIC
+ uint32_t reason, info;
+ uint8_t exception;
+
+ /* Panic data will be wiped by hard reset, so save it */
+ panic_get_reason(&reason, &info, &exception);
+ /* 16 bits stored - upper 16 bits of reason / info are lost */
+ bkpdata_write(BKPDATA_INDEX_SAVED_PANIC_REASON, reason);
+ bkpdata_write(BKPDATA_INDEX_SAVED_PANIC_INFO, info);
+ bkpdata_write(BKPDATA_INDEX_SAVED_PANIC_EXCEPTION, exception);
+#endif
#ifdef CHIP_FAMILY_STM32L
/*
diff --git a/common/system.c b/common/system.c
index d57b1ce9ab..4bd70400d0 100644
--- a/common/system.c
+++ b/common/system.c
@@ -582,7 +582,7 @@ void system_common_pre_init(void)
* because it might change panic pointer.
*/
if (system_get_reset_flags() & RESET_FLAG_WATCHDOG)
- panic_log_watchdog();
+ panic_set_reason(PANIC_SW_WATCHDOG, 0, 0);
#endif
/*
diff --git a/core/cortex-m/panic.c b/core/cortex-m/panic.c
index 64fd5b8db1..6b81e8c484 100644
--- a/core/cortex-m/panic.c
+++ b/core/cortex-m/panic.c
@@ -373,28 +373,47 @@ void exception_panic(void)
);
}
-void software_panic(uint32_t panic_reason, uint32_t panic_info)
+#ifdef CONFIG_SOFTWARE_PANIC
+void software_panic(uint32_t reason, uint32_t info)
{
__asm__("mov " STRINGIFY(SOFTWARE_PANIC_INFO_REG) ", %0\n"
"mov " STRINGIFY(SOFTWARE_PANIC_REASON_REG) ", %1\n"
"bl exception_panic\n"
- : : "r"(panic_info), "r"(panic_reason));
+ : : "r"(info), "r"(reason));
}
-void panic_log_watchdog(void)
+void panic_set_reason(uint32_t reason, uint32_t info, uint8_t exception)
{
uint32_t *lregs = pdata_ptr->cm.regs;
- /* Watchdog reset, log panic cause */
+ /* Setup panic data structure */
memset(pdata_ptr, 0, sizeof(*pdata_ptr));
pdata_ptr->magic = PANIC_DATA_MAGIC;
pdata_ptr->struct_size = sizeof(*pdata_ptr);
pdata_ptr->struct_version = 2;
pdata_ptr->arch = PANIC_ARCH_CORTEX_M;
- lregs[3] = PANIC_SW_WATCHDOG;
+ /* Log panic cause */
+ lregs[1] = exception;
+ lregs[3] = reason;
+ lregs[4] = info;
}
+void panic_get_reason(uint32_t *reason, uint32_t *info, uint8_t *exception)
+{
+ uint32_t *lregs = pdata_ptr->cm.regs;
+
+ if (pdata_ptr->magic == PANIC_DATA_MAGIC &&
+ pdata_ptr->struct_version == 2) {
+ *exception = lregs[1];
+ *reason = lregs[3];
+ *info = lregs[4];
+ } else {
+ *exception = *reason = *info = 0;
+ }
+}
+#endif
+
void bus_fault_handler(void)
{
if (!bus_fault_ignored)
diff --git a/core/cortex-m/task.c b/core/cortex-m/task.c
index f7fda67374..69b92d5de8 100644
--- a/core/cortex-m/task.c
+++ b/core/cortex-m/task.c
@@ -226,7 +226,9 @@ void svc_handler(int desched, task_id_t resched)
if (*current->stack != STACK_UNUSED_VALUE) {
panic_printf("\n\nStack overflow in %s task!\n",
task_names[current - tasks]);
+#ifdef CONFIG_SOFTWARE_PANIC
software_panic(PANIC_SW_STACK_OVERFLOW, current - tasks);
+#endif
}
#endif
diff --git a/core/cortex-m0/panic.c b/core/cortex-m0/panic.c
index 2b17a1bd73..2ba22c6998 100644
--- a/core/cortex-m0/panic.c
+++ b/core/cortex-m0/panic.c
@@ -166,28 +166,47 @@ void exception_panic(void)
);
}
-void software_panic(uint32_t panic_reason, uint32_t panic_info)
+#ifdef CONFIG_SOFTWARE_PANIC
+void software_panic(uint32_t reason, uint32_t info)
{
__asm__("mov " STRINGIFY(SOFTWARE_PANIC_INFO_REG) ", %0\n"
"mov " STRINGIFY(SOFTWARE_PANIC_REASON_REG) ", %1\n"
"bl exception_panic\n"
- : : "r"(panic_info), "r"(panic_reason));
+ : : "r"(info), "r"(reason));
}
-void panic_log_watchdog(void)
+void panic_set_reason(uint32_t reason, uint32_t info, uint8_t exception)
{
uint32_t *lregs = pdata_ptr->cm.regs;
- /* Watchdog reset, log panic cause */
+ /* Setup panic data structure */
memset(pdata_ptr, 0, sizeof(*pdata_ptr));
pdata_ptr->magic = PANIC_DATA_MAGIC;
pdata_ptr->struct_size = sizeof(*pdata_ptr);
pdata_ptr->struct_version = 2;
pdata_ptr->arch = PANIC_ARCH_CORTEX_M;
- lregs[3] = PANIC_SW_WATCHDOG;
+ /* Log panic cause */
+ lregs[1] = exception;
+ lregs[3] = reason;
+ lregs[4] = info;
}
+void panic_get_reason(uint32_t *reason, uint32_t *info, uint8_t *exception)
+{
+ uint32_t *lregs = pdata_ptr->cm.regs;
+
+ if (pdata_ptr->magic == PANIC_DATA_MAGIC &&
+ pdata_ptr->struct_version == 2) {
+ *exception = lregs[1];
+ *reason = lregs[3];
+ *info = lregs[4];
+ } else {
+ *exception = *reason = *info = 0;
+ }
+}
+#endif
+
void bus_fault_handler(void)
{
if (!bus_fault_ignored)
diff --git a/core/cortex-m0/task.c b/core/cortex-m0/task.c
index 86fb7071d5..ffdbe49595 100644
--- a/core/cortex-m0/task.c
+++ b/core/cortex-m0/task.c
@@ -210,7 +210,9 @@ task_ *__svc_handler(int desched, task_id_t resched)
if (*current->stack != STACK_UNUSED_VALUE) {
panic_printf("\n\nStack overflow in %s task!\n",
task_names[current - tasks]);
+#ifdef CONFIG_SOFTWARE_PANIC
software_panic(PANIC_SW_STACK_OVERFLOW, current - tasks);
+#endif
}
#endif
diff --git a/include/panic.h b/include/panic.h
index 122f0c317c..ea7a40f7b0 100644
--- a/include/panic.h
+++ b/include/panic.h
@@ -129,13 +129,18 @@ void panic_reboot(void);
* Store a panic log and halt the system for a software-related reason, such as
* stack overflow or assertion failure.
*/
-void software_panic(uint32_t panic_reason, uint32_t panic_info);
+void software_panic(uint32_t reason, uint32_t info);
/**
- * Log a watchdog panic in the panic log. Called on the subsequent reboot after
- * the watchdog fires.
+ * Log a panic in the panic log, but don't halt the system. Normally
+ * called on the subsequent reboot after panic detection.
*/
-void panic_log_watchdog(void);
+void panic_set_reason(uint32_t reason, uint32_t info, uint8_t exception);
+
+/**
+ * Retrieve the currently stored panic reason + info.
+ */
+void panic_get_reason(uint32_t *reason, uint32_t *info, uint8_t *exception);
#endif
/**