Skip to content

Instantly share code, notes, and snippets.

@kylemanna
Last active December 29, 2016 22:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kylemanna/fc4748ed7fe2f718c737b30416382d4b to your computer and use it in GitHub Desktop.
Save kylemanna/fc4748ed7fe2f718c737b30416382d4b to your computer and use it in GitHub Desktop.
diff --git a/devices/MKL27Z4/gcc/startup_MKL27Z4.S b/devices/MKL27Z4/gcc/startup_MKL27Z4.S
index 961af8d..b249b4b 100644
--- a/devices/MKL27Z4/gcc/startup_MKL27Z4.S
+++ b/devices/MKL27Z4/gcc/startup_MKL27Z4.S
@@ -47,7 +47,7 @@ __isr_vector:
.long __StackTop /* Top of Stack */
.long Reset_Handler /* Reset Handler */
.long NMI_Handler /* NMI Handler*/
- .long HardFault_Handler /* Hard Fault Handler*/
+ .long HardFault_HandlerAsm /* Hard Fault Handler*/
.long 0 /* Reserved*/
.long 0 /* Reserved*/
.long 0 /* Reserved*/
diff --git a/source/main.c b/source/main.c
index 3282694..8ab5c8d 100644
--- a/source/main.c
+++ b/source/main.c
@@ -107,3 +107,78 @@ int main(void)
/* something to use as a breakpoint stop while looping */
}
}
+
+__attribute__((naked))
+void HardFault_HandlerAsm(void){
+ /*
+ * Get the appropriate stack pointer, depending on our mode,
+ * and use it as the parameter to the C handler. This function
+ * will never return
+ */
+
+ __asm( ".syntax unified\n"
+ "MOVS R0, #4 \n"
+ "MOV R1, LR \n"
+ "TST R0, R1 \n"
+ "BEQ _MSP \n"
+ "MRS R0, PSP \n"
+ "B HardFault_HandlerC \n"
+ "_MSP: \n"
+ "MRS R0, MSP \n"
+ "B HardFault_HandlerC \n"
+ ".syntax divided\n") ;
+}
+
+/**
+* HardFaultHandler_C:
+* This is called from the HardFault_HandlerAsm with a pointer the Fault stack
+* as the parameter. We can then read the values from the stack and place them
+* into local variables for ease of reading.
+* We then read the various Fault Status and Address Registers to help decode
+* cause of the fault.
+* The function ends with a BKPT instruction to force control back into the debugger
+*/
+void HardFault_HandlerC(unsigned long *hardfault_args){
+ volatile unsigned long stacked_r0 = ((unsigned long)hardfault_args[0]);
+ volatile unsigned long stacked_r1 = ((unsigned long)hardfault_args[1]);
+ volatile unsigned long stacked_r2 = ((unsigned long)hardfault_args[2]);
+ volatile unsigned long stacked_r3 = ((unsigned long)hardfault_args[3]);
+ volatile unsigned long stacked_r12 = ((unsigned long)hardfault_args[4]);
+ volatile unsigned long stacked_lr = ((unsigned long)hardfault_args[5]);
+ volatile unsigned long stacked_pc = ((unsigned long)hardfault_args[6]);
+ volatile unsigned long stacked_psr = ((unsigned long)hardfault_args[7]);
+
+ // Configurable Fault Status Register
+ // Consists of MMSR, BFSR and UFSR
+ volatile unsigned long _CFSR = (*((volatile unsigned long *)(0xE000ED28)));
+ // Hard Fault Status Register
+ volatile unsigned long _HFSR = (*((volatile unsigned long *)(0xE000ED2C)));
+ // Debug Fault Status Register
+ volatile unsigned long _DFSR = (*((volatile unsigned long *)(0xE000ED30)));
+ // Auxiliary Fault Status Register
+ volatile unsigned long _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
+ volatile unsigned long _MMAR = (*((volatile unsigned long *)(0xE000ED34)));
+ // Bus Fault Address Register
+ volatile unsigned long _BFAR = (*((volatile unsigned long *)(0xE000ED38)));
+
+ /* Silence unused variable warnings */
+ (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;
+
+ __asm("BKPT #0\n") ; // Break into the debugger
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment