diff options
-rw-r--r-- | core/cortex-m/panic.c | 40 | ||||
-rw-r--r-- | include/config.h | 3 | ||||
-rw-r--r-- | include/panic.h | 38 |
3 files changed, 75 insertions, 6 deletions
diff --git a/core/cortex-m/panic.c b/core/cortex-m/panic.c index acd806b761..da6900b1b9 100644 --- a/core/cortex-m/panic.c +++ b/core/cortex-m/panic.c @@ -312,8 +312,19 @@ void __keep report_panic(void) sp <= CONFIG_RAM_BASE + CONFIG_RAM_SIZE - 8 * sizeof(uint32_t)) { const uint32_t *sregs = (const uint32_t *)sp; int i; - for (i = 0; i < 8; i++) + + /* Skip r0-r3 and r12 registers if necessary */ + for (i = CORTEX_PANIC_FRAME_REGISTER_R0; + i <= CORTEX_PANIC_FRAME_REGISTER_R12; i++) + if (IS_ENABLED(CONFIG_PANIC_STRIP_GPR)) + pdata->cm.frame[i] = 0; + else + pdata->cm.frame[i] = sregs[i]; + + for (i = CORTEX_PANIC_FRAME_REGISTER_LR; + i < NUM_CORTEX_PANIC_FRAME_REGISTERS; i++) pdata->cm.frame[i] = sregs[i]; + pdata->flags |= PANIC_DATA_FLAG_FRAME_VALID; } @@ -357,6 +368,33 @@ void exception_panic(void) "mrs r1, psp\n" "mrs r2, ipsr\n" "mov r3, sp\n" +#ifdef CONFIG_PANIC_STRIP_GPR + /* + * Check if we are in exception. This is similar to + * in_interrupt_context(). Exception bits are 9 LSB, so + * we can perform left shift for 23 bits and check if result + * is 0 (lsls instruction is setting appropriate flags). + */ + "lsls r6, r2, #23\n" + /* + * If this is software panic (shift result == 0) then register + * r4 and r5 contain additional info about panic. + * Clear r6-r11 always and r4, r5 only if this is exception + * panic. To clear r4 and r5, 'movne' conditional instruction + * is used. It works only when flags contain information that + * result was != 0. Itt is pseudo instruction which is used + * to make sure we are using correct conditional instructions. + */ + "itt ne\n" + "movne r4, #0\n" + "movne r5, #0\n" + "mov r6, #0\n" + "mov r7, #0\n" + "mov r8, #0\n" + "mov r9, #0\n" + "mov r10, #0\n" + "mov r11, #0\n" +#endif "stmia r0, {r1-r11, lr}\n" "mov sp, %[pstack]\n" "bl report_panic\n" : : diff --git a/include/config.h b/include/config.h index e555b8a78e..f74c9f82c9 100644 --- a/include/config.h +++ b/include/config.h @@ -1501,6 +1501,9 @@ */ #undef CONFIG_CHIP_PANIC_BACKUP +/* Don't save General Purpose Registers during panic */ +#undef CONFIG_PANIC_STRIP_GPR + /* * Provide the default GPIO abstraction layer. * You want this unless you are doing a really tiny firmware. diff --git a/include/panic.h b/include/panic.h index 4160454ce2..577e592e32 100644 --- a/include/panic.h +++ b/include/panic.h @@ -19,13 +19,41 @@ extern "C" { #endif +enum cortex_panic_frame_registers { + CORTEX_PANIC_FRAME_REGISTER_R0 = 0, + CORTEX_PANIC_FRAME_REGISTER_R1, + CORTEX_PANIC_FRAME_REGISTER_R2, + CORTEX_PANIC_FRAME_REGISTER_R3, + CORTEX_PANIC_FRAME_REGISTER_R12, + CORTEX_PANIC_FRAME_REGISTER_LR, + CORTEX_PANIC_FRAME_REGISTER_PC, + CORTEX_PANIC_FRAME_REGISTER_PSR, + NUM_CORTEX_PANIC_FRAME_REGISTERS +}; + +enum cortex_panic_registers { + CORTEX_PANIC_REGISTER_PSP = 0, + CORTEX_PANIC_REGISTER_IPSR, + CORTEX_PANIC_REGISTER_MSP, + CORTEX_PANIC_REGISTER_R4, + CORTEX_PANIC_REGISTER_R5, + CORTEX_PANIC_REGISTER_R6, + CORTEX_PANIC_REGISTER_R7, + CORTEX_PANIC_REGISTER_R8, + CORTEX_PANIC_REGISTER_R9, + CORTEX_PANIC_REGISTER_R10, + CORTEX_PANIC_REGISTER_R11, + CORTEX_PANIC_REGISTER_LR, + NUM_CORTEX_PANIC_REGISTERS +}; + /* ARM Cortex-Mx registers saved on panic */ struct cortex_panic_data { - uint32_t regs[12]; /* psp, ipsr, msp, r4-r11, lr(=exc_return). - * In version 1, that was uint32_t regs[11] = - * psp, ipsr, lr, r4-r11 - */ - uint32_t frame[8]; /* r0-r3, r12, lr, pc, xPSR */ + /* See cortex_panic_registers enum for information about registers */ + uint32_t regs[NUM_CORTEX_PANIC_REGISTERS]; + + /* See cortex_panic_frame_registers enum for more information */ + uint32_t frame[NUM_CORTEX_PANIC_FRAME_REGISTERS]; uint32_t cfsr; uint32_t bfar; |