From 11f37ffb4578cc0129d2ac3f53e6190c0f1910e8 Mon Sep 17 00:00:00 2001 From: Balazs Racz Date: Tue, 9 Aug 2022 17:26:07 +0200 Subject: [PATCH] Handles double faults in the default hard_fault handler. (#636) When we encounter a double fault, that typically means that our smarts in handling the first fault have failed us. We just halt everything in this case. --- boards/armv7m/default_handlers.h | 72 +++++++++++++++++++------------- 1 file changed, 42 insertions(+), 30 deletions(-) diff --git a/boards/armv7m/default_handlers.h b/boards/armv7m/default_handlers.h index db67288c2..ccd2c25e8 100644 --- a/boards/armv7m/default_handlers.h +++ b/boards/armv7m/default_handlers.h @@ -200,40 +200,53 @@ typedef struct fault_information /** Global instance so that it can be added to the watch expressions */ volatile FaultInformation faultInfo; +static uint8_t seenFault = 0; __attribute__((optimize("-O0"),unused)) void hard_fault_handler_step_2(unsigned long *hardfault_args) { /* force a reference in the local variables for debug */ volatile FaultInformation *fault_info = &faultInfo; - - fault_info->stacked_r0 = ((unsigned long)hardfault_args[0]) ; - fault_info->stacked_r1 = ((unsigned long)hardfault_args[1]) ; - fault_info->stacked_r2 = ((unsigned long)hardfault_args[2]) ; - fault_info->stacked_r3 = ((unsigned long)hardfault_args[3]) ; - fault_info->stacked_r12 = ((unsigned long)hardfault_args[4]) ; - fault_info->stacked_lr = ((unsigned long)hardfault_args[5]) ; - fault_info->stacked_pc = ((unsigned long)hardfault_args[6]) ; - fault_info->stacked_psr = ((unsigned long)hardfault_args[7]) ; - - // Configurable Fault Status Register - // Consists of MMSR, BFSR and UFSR - fault_info->_CFSR = (*((volatile unsigned long *)(0xE000ED28))) ; - - // Hard Fault Status Register - fault_info->_HFSR = (*((volatile unsigned long *)(0xE000ED2C))) ; - - // Debug Fault Status Register - fault_info->_DFSR = (*((volatile unsigned long *)(0xE000ED30))) ; - - // Auxiliary Fault Status Register - fault_info->_AFSR = (*((volatile unsigned long *)(0xE000ED3C))) ; - - // Read the Fault Address Registers. These may not contain valid values. - // Check BFARVALID/MMARVALID to see if they are valid values - // MemManage Fault Address Register - fault_info->_MMAR = (*((volatile unsigned long *)(0xE000ED34))) ; - // Bus Fault Address Register - fault_info->_BFAR = (*((volatile unsigned long *)(0xE000ED38))) ; + if (!seenFault) + { + seenFault = 1; + fault_info->stacked_r0 = ((unsigned long)hardfault_args[0]); + fault_info->stacked_r1 = ((unsigned long)hardfault_args[1]); + fault_info->stacked_r2 = ((unsigned long)hardfault_args[2]); + fault_info->stacked_r3 = ((unsigned long)hardfault_args[3]); + fault_info->stacked_r12 = ((unsigned long)hardfault_args[4]); + fault_info->stacked_lr = ((unsigned long)hardfault_args[5]); + fault_info->stacked_pc = ((unsigned long)hardfault_args[6]); + fault_info->stacked_psr = ((unsigned long)hardfault_args[7]); + + // Configurable Fault Status Register + // Consists of MMSR, BFSR and UFSR + fault_info->_CFSR = (*((volatile unsigned long *)(0xE000ED28))); + + // Hard Fault Status Register + fault_info->_HFSR = (*((volatile unsigned long *)(0xE000ED2C))); + + // Debug Fault Status Register + fault_info->_DFSR = (*((volatile unsigned long *)(0xE000ED30))); + + // Auxiliary Fault Status Register + fault_info->_AFSR = (*((volatile unsigned long *)(0xE000ED3C))); + + // Read the Fault Address Registers. These may not contain valid values. + // Check BFARVALID/MMARVALID to see if they are valid values + // MemManage Fault Address Register + fault_info->_MMAR = (*((volatile unsigned long *)(0xE000ED34))); + // Bus Fault Address Register + fault_info->_BFAR = (*((volatile unsigned long *)(0xE000ED38))); + } + else + { + // Double fault. Let's not try doing anything smart anymore, just halt. + while (1) + { + extern void wait_with_blinker(void); + wait_with_blinker(); + } + } hw_set_to_safe(); __asm volatile ("cpsid i\n"); @@ -262,7 +275,6 @@ void wait_with_blinker(void) // noop } - void hard_fault_handler_step_3(void) { const uint32_t C_DEBUGEN = 0x00000001; uint32_t debugreg = *(volatile uint32_t*)0xE000EDF0;