Skip to content

Commit

Permalink
Handles double faults in the default hard_fault handler. (#636)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
balazsracz authored Aug 9, 2022
1 parent f2a7567 commit 11f37ff
Showing 1 changed file with 42 additions and 30 deletions.
72 changes: 42 additions & 30 deletions boards/armv7m/default_handlers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 11f37ff

Please sign in to comment.