Created
July 24, 2015 03:18
-
-
Save doceme/5c15b84a3e8fa9cf3fbf to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Fault handlers, stolen from FreeRTOS web (www.FreeRTOS.org) | |
* | |
* 2009-2010 Michal Demin | |
* | |
*/ | |
#ifdef USE_HF_DEBUG | |
void HardFault_Handler(void) __attribute__ ((naked)); | |
struct stack_t { | |
unsigned long r0; | |
unsigned long r1; | |
unsigned long r2; | |
unsigned long r3; | |
unsigned long r12; | |
unsigned long lr; | |
unsigned long pc; | |
unsigned long psr; | |
}; | |
#define assert_break() do { __asm volatile("bkpt 0"); while(1); } while (0) | |
void assert_failed(unsigned char *function, unsigned int line) | |
{ | |
(void)function; | |
(void)line; | |
assert_break(); | |
} | |
static void fault_halt(unsigned long *hardfault_args) | |
{ | |
//(void)stack; | |
volatile unsigned long stacked_r0; | |
volatile unsigned long stacked_r1; | |
volatile unsigned long stacked_r2; | |
volatile unsigned long stacked_r3; | |
volatile unsigned long stacked_r12; | |
volatile unsigned long stacked_lr; | |
volatile unsigned long stacked_pc; | |
volatile unsigned long stacked_psr; | |
volatile unsigned long _CFSR; | |
volatile unsigned long _HFSR; | |
volatile unsigned long _DFSR; | |
volatile unsigned long _AFSR; | |
volatile unsigned long _BFAR; | |
volatile unsigned long _MMAR; | |
stacked_r0 = ((unsigned long)hardfault_args[0]); | |
stacked_r1 = ((unsigned long)hardfault_args[1]); | |
stacked_r2 = ((unsigned long)hardfault_args[2]); | |
stacked_r3 = ((unsigned long)hardfault_args[3]); | |
stacked_r12 = ((unsigned long)hardfault_args[4]); | |
stacked_lr = ((unsigned long)hardfault_args[5]); | |
stacked_pc = ((unsigned long)hardfault_args[6]); | |
stacked_psr = ((unsigned long)hardfault_args[7]); | |
/* Configurable Fault Status Register */ | |
/* Consists of MMSR, BFSR and UFSR */ | |
_CFSR = (*((volatile unsigned long *)(0xE000ED28))); | |
/* Hard Fault Status Register */ | |
_HFSR = (*((volatile unsigned long *)(0xE000ED2C))); | |
/* Debug Fault Status Register */ | |
_DFSR = (*((volatile unsigned long *)(0xE000ED30))); | |
/* Auxiliary Fault Status Register */ | |
_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 | |
*/ | |
_MMAR = (*((volatile unsigned long *)(0xE000ED34))); | |
/* Bus Fault Address Register */ | |
_BFAR = (*((volatile unsigned long *)(0xE000ED38))); | |
/* suppress warnings about unused variables */ | |
(void)stacked_r0; | |
(void)stacked_r1; | |
(void)stacked_r2; | |
(void)stacked_r3; | |
(void)stacked_r12; | |
(void)stacked_lr; | |
(void)stacked_pc; | |
(void)stacked_psr; | |
(void)_CFSR; | |
(void)_HFSR; | |
(void)_DFSR; | |
(void)_AFSR; | |
(void)_BFAR; | |
(void)_MMAR; | |
/* Inspect stack->pc to locate the offending instruction. */ | |
assert_break(); | |
} | |
void HardFault_Handler(void) | |
{ | |
register unsigned long *stack_pointer asm("r0"); | |
__asm volatile ( | |
" movs r0,#4 \n" /* load bit mask into R0 */ | |
" movs r1, lr \n" /* load link register into R1 */ | |
" tst r0, r1 \n" /* compare with bitmask */ | |
" beq _MSP \n" /* if bitmask is set: stack pointer is in PSP. Otherwise in MSP */ | |
" mrs r0, psp \n" /* otherwise: stack pointer is in PSP */ | |
" b _GetPC \n" /* go to part which loads the PC */ | |
"_MSP: \n" /* stack pointer is in MSP register */ | |
" mrs r0, msp \n" /* load stack pointer into R0 */ | |
"_GetPC: \n" /* find out where the hard fault happened */ | |
" ldr r1,[r0,#20] \n" /* load program counter into R1. R1 contains address of the next instruction where the hard fault happened */ | |
); | |
fault_halt(stack_pointer); | |
assert_break(); | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Fault handling for Cortex-M0. Removed the branch to fault_halt inside the inline asm (and created an proper function call) so that GCC's linker won't complain. Without this, the compiler isn't smart enough when link time optimization (-flto) is enabled and compiling anything greater than -O0.