summaryrefslogtreecommitdiff
path: root/core/cortex-m/panic.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/cortex-m/panic.c')
-rw-r--r--core/cortex-m/panic.c220
1 files changed, 33 insertions, 187 deletions
diff --git a/core/cortex-m/panic.c b/core/cortex-m/panic.c
index 95344bbb07..d63a5e3d9a 100644
--- a/core/cortex-m/panic.c
+++ b/core/cortex-m/panic.c
@@ -19,70 +19,15 @@
/* Whether bus fault is ignored */
static int bus_fault_ignored;
-/*
- * Panic data goes at the end of RAM. This is safe because we don't context
- * switch away from the panic handler before rebooting, and stacks and data
- * start at the beginning of RAM.
- */
-static struct panic_data * const pdata_ptr =
- (struct panic_data *)(CONFIG_RAM_BASE + CONFIG_RAM_SIZE
- - sizeof(struct panic_data));
+
+/* Panic data goes at the end of RAM. */
+static struct panic_data * const pdata_ptr = PANIC_DATA_PTR;
/* Preceded by stack, rounded down to nearest 64-bit-aligned boundary */
static const uint32_t pstack_addr = (CONFIG_RAM_BASE + CONFIG_RAM_SIZE
- sizeof(struct panic_data)) & ~7;
/**
- * Add a character directly to the UART buffer.
- *
- * @param context Context; ignored.
- * @param c Character to write.
- * @return 0 if the character was transmitted, 1 if it was dropped.
- */
-static int panic_txchar(void *context, int c)
-{
- if (c == '\n')
- panic_txchar(context, '\r');
-
- /* Wait for space in transmit FIFO */
- while (!uart_tx_ready())
- ;
-
- /* Write the character directly to the transmit FIFO */
- uart_write_char(c);
-
- return 0;
-}
-
-void panic_puts(const char *outstr)
-{
- /* Flush the output buffer */
- uart_flush_output();
-
- /* Put all characters in the output buffer */
- while (*outstr)
- panic_txchar(NULL, *outstr++);
-
- /* Flush the transmit FIFO */
- uart_tx_flush();
-}
-
-void panic_printf(const char *format, ...)
-{
- va_list args;
-
- /* Flush the output buffer */
- uart_flush_output();
-
- va_start(args, format);
- vfnprintf(panic_txchar, NULL, format, args);
- va_end(args);
-
- /* Flush the transmit FIFO */
- uart_tx_flush();
-}
-
-/**
* Print the name and value of a register
*
* This is a convenient helper function for displaying a register value.
@@ -253,13 +198,13 @@ static uint32_t get_exception_frame_size(const struct panic_data *pdata)
/* CPU uses xPSR[9] to indicate whether it padded the stack for
* alignment or not. */
- if (pdata->frame[7] & (1 << 9))
+ if (pdata->cm.frame[7] & (1 << 9))
frame_size += sizeof(uint32_t);
#ifdef CONFIG_FPU
/* CPU uses EXC_RETURN[4] to indicate whether it stored extended
* frame for FPU or not. */
- if (!(pdata->regs[11] & (1 << 4)))
+ if (!(pdata->cm.regs[11] & (1 << 4)))
frame_size += 18 * sizeof(uint32_t);
#endif
@@ -273,9 +218,9 @@ static uint32_t get_exception_frame_size(const struct panic_data *pdata)
*/
static uint32_t get_process_stack_position(const struct panic_data *pdata)
{
- uint32_t psp = pdata->regs[0];
+ uint32_t psp = pdata->cm.regs[0];
- if (!is_frame_in_handler_stack(pdata->regs[11]))
+ if (!is_frame_in_handler_stack(pdata->cm.regs[11]))
psp += get_exception_frame_size(pdata);
return psp;
@@ -289,15 +234,15 @@ static uint32_t get_process_stack_position(const struct panic_data *pdata)
*/
static void panic_show_extra(const struct panic_data *pdata)
{
- show_fault(pdata->mmfs, pdata->hfsr, pdata->dfsr);
- if (pdata->mmfs & CPU_NVIC_MMFS_BFARVALID)
- panic_printf(", bfar = %x", pdata->bfar);
- if (pdata->mmfs & CPU_NVIC_MMFS_MFARVALID)
- panic_printf(", mfar = %x", pdata->mfar);
- panic_printf("\nmmfs = %x, ", pdata->mmfs);
- panic_printf("shcsr = %x, ", pdata->shcsr);
- panic_printf("hfsr = %x, ", pdata->hfsr);
- panic_printf("dfsr = %x\n", pdata->dfsr);
+ show_fault(pdata->cm.mmfs, pdata->cm.hfsr, pdata->cm.dfsr);
+ if (pdata->cm.mmfs & CPU_NVIC_MMFS_BFARVALID)
+ panic_printf(", bfar = %x", pdata->cm.bfar);
+ if (pdata->cm.mmfs & CPU_NVIC_MMFS_MFARVALID)
+ panic_printf(", mfar = %x", pdata->cm.mfar);
+ panic_printf("\nmmfs = %x, ", pdata->cm.mmfs);
+ panic_printf("shcsr = %x, ", pdata->cm.shcsr);
+ panic_printf("hfsr = %x, ", pdata->cm.hfsr);
+ panic_printf("dfsr = %x\n", pdata->cm.dfsr);
}
/*
@@ -324,27 +269,19 @@ static void panic_show_process_stack(const struct panic_data *pdata)
}
#endif /* CONFIG_DEBUG_EXCEPTIONS */
-/**
- * Display a message and reboot
- */
-void panic_reboot(void)
-{
- panic_puts("\n\nRebooting...\n");
- system_reset(0);
-}
-
/*
* Print panic data
*/
-static void panic_print(const struct panic_data *pdata)
+void panic_data_print(const struct panic_data *pdata)
{
- const uint32_t *lregs = pdata->regs;
+ const uint32_t *lregs = pdata->cm.regs;
const uint32_t *sregs = NULL;
- const int32_t in_handler = is_frame_in_handler_stack(pdata->regs[11]);
+ const int32_t in_handler =
+ is_frame_in_handler_stack(pdata->cm.regs[11]);
int i;
if (pdata->flags & PANIC_DATA_FLAG_FRAME_VALID)
- sregs = pdata->frame;
+ sregs = pdata->cm.frame;
panic_printf("\n=== %s EXCEPTION: %02x ====== xPSR: %08x ===\n",
in_handler ? "HANDLER" : "PROCESS",
@@ -378,8 +315,8 @@ void report_panic(void)
pdata->reserved = 0;
/* Choose the right sp (psp or msp) based on EXC_RETURN value */
- sp = is_frame_in_handler_stack(pdata->regs[11])
- ? pdata->regs[2] : pdata->regs[0];
+ sp = is_frame_in_handler_stack(pdata->cm.regs[11])
+ ? pdata->cm.regs[2] : pdata->cm.regs[0];
/* If stack is valid, copy exception frame to pdata */
if ((sp & 3) == 0 &&
sp >= CONFIG_RAM_BASE &&
@@ -387,19 +324,19 @@ void report_panic(void)
const uint32_t *sregs = (const uint32_t *)sp;
int i;
for (i = 0; i < 8; i++)
- pdata->frame[i] = sregs[i];
+ pdata->cm.frame[i] = sregs[i];
pdata->flags |= PANIC_DATA_FLAG_FRAME_VALID;
}
/* Save extra information */
- pdata->mmfs = CPU_NVIC_MMFS;
- pdata->bfar = CPU_NVIC_BFAR;
- pdata->mfar = CPU_NVIC_MFAR;
- pdata->shcsr = CPU_NVIC_SHCSR;
- pdata->hfsr = CPU_NVIC_HFSR;
- pdata->dfsr = CPU_NVIC_DFSR;
-
- panic_print(pdata);
+ pdata->cm.mmfs = CPU_NVIC_MMFS;
+ pdata->cm.bfar = CPU_NVIC_BFAR;
+ pdata->cm.mfar = CPU_NVIC_MFAR;
+ pdata->cm.shcsr = CPU_NVIC_SHCSR;
+ pdata->cm.hfsr = CPU_NVIC_HFSR;
+ pdata->cm.dfsr = CPU_NVIC_DFSR;
+
+ panic_data_print(pdata);
#ifdef CONFIG_DEBUG_EXCEPTIONS
panic_show_process_stack(pdata);
/*
@@ -427,7 +364,7 @@ void exception_panic(void)
"stmia r0, {r1-r11, lr}\n"
"mov sp, %[pstack]\n"
"b report_panic\n" : :
- [pregs] "r" (pdata_ptr->regs),
+ [pregs] "r" (pdata_ptr->cm.regs),
[pstack] "r" (pstack_addr) :
/* Constraints protecting these from being clobbered.
* Gcc should be using r0 & r12 for pregs and pstack. */
@@ -446,94 +383,3 @@ void ignore_bus_fault(int ignored)
{
bus_fault_ignored = ignored;
}
-
-#ifdef CONFIG_DEBUG_ASSERT_REBOOTS
-void panic_assert_fail(const char *msg, const char *func, const char *fname,
- int linenum)
-{
- panic_printf("\nASSERTION FAILURE '%s' in %s() at %s:%d\n",
- msg, func, fname, linenum);
-
- panic_reboot();
-}
-#endif
-
-void panic(const char *msg)
-{
- panic_printf("\n** PANIC: %s\n", msg);
- panic_reboot();
-}
-
-struct panic_data *panic_get_data(void)
-{
- return pdata_ptr->magic == PANIC_DATA_MAGIC ? pdata_ptr : NULL;
-}
-
-/*****************************************************************************/
-/* Console commands */
-
-static int command_crash(int argc, char **argv)
-{
- if (argc < 2)
- return EC_ERROR_PARAM1;
-
- if (!strcasecmp(argv[1], "divzero")) {
- int a = 1, b = 0;
-
- cflush();
- ccprintf("%08x", a / b);
- } else if (!strcasecmp(argv[1], "unaligned")) {
- cflush();
- ccprintf("%08x", *(int *)0xcdef);
- } else {
- return EC_ERROR_PARAM1;
- }
-
- /* Everything crashes, so shouldn't get back here */
- return EC_ERROR_UNKNOWN;
-}
-DECLARE_CONSOLE_COMMAND(crash, command_crash,
- "[divzero | unaligned]",
- "Crash the system (for testing)",
- NULL);
-
-static int command_panicinfo(int argc, char **argv)
-{
- if (pdata_ptr->magic == PANIC_DATA_MAGIC) {
- ccprintf("Saved panic data:%s\n",
- (pdata_ptr->flags & PANIC_DATA_FLAG_OLD_CONSOLE ?
- "" : " (NEW)"));
-
- panic_print(pdata_ptr);
-
- /* Data has now been printed */
- pdata_ptr->flags |= PANIC_DATA_FLAG_OLD_CONSOLE;
- } else {
- ccprintf("No saved panic data available.\n");
- }
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(panicinfo, command_panicinfo,
- NULL,
- "Print info from a previous panic",
- NULL);
-
-/*****************************************************************************/
-/* Host commands */
-
-int host_command_panic_info(struct host_cmd_handler_args *args)
-{
- if (pdata_ptr->magic == PANIC_DATA_MAGIC) {
- ASSERT(pdata_ptr->struct_size <= args->response_max);
- memcpy(args->response, pdata_ptr, pdata_ptr->struct_size);
- args->response_size = pdata_ptr->struct_size;
-
- /* Data has now been returned */
- pdata_ptr->flags |= PANIC_DATA_FLAG_OLD_HOSTCMD;
- }
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_GET_PANIC_INFO,
- host_command_panic_info,
- EC_VER_MASK(0));