From 5cd91bc784e70052fcd75efab68c91776adf4da8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= <joakim.nohlgard@eistec.se>
Date: Fri, 15 Jul 2016 21:54:54 +0200
Subject: [PATCH] cortexm: Hard fault: Try to output as much as possible even
 with corrupt stack

---
 cpu/cortexm_common/vectors_cortexm.c | 70 +++++++++++++++-------------
 1 file changed, 38 insertions(+), 32 deletions(-)

diff --git a/cpu/cortexm_common/vectors_cortexm.c b/cpu/cortexm_common/vectors_cortexm.c
index e29024be29..b72de99405 100644
--- a/cpu/cortexm_common/vectors_cortexm.c
+++ b/cpu/cortexm_common/vectors_cortexm.c
@@ -194,38 +194,41 @@ __attribute__((naked)) void hard_fault_default(void)
 
 __attribute__((used)) void hard_fault_handler(uint32_t* sp, uint32_t corrupted, uint32_t exc_return, uint32_t* r4_to_r11_stack)
 {
+#if CPU_HAS_EXTENDED_FAULT_REGISTERS
+    /* Copy status register contents to local stack storage, this must be
+     * done before any calls to other functions to avoid corrupting the
+     * register contents. */
+    uint32_t bfar  = SCB->BFAR;
+    uint32_t mmfar = SCB->MMFAR;
+    uint32_t cfsr  = SCB->CFSR;
+    uint32_t hfsr  = SCB->HFSR;
+    uint32_t dfsr  = SCB->DFSR;
+    uint32_t afsr  = SCB->AFSR;
+#endif
+    uint32_t pc;
+    uint32_t* orig_sp;
+
     /* Check if the ISR stack overflowed previously. Not possible to detect
      * after output may also have overflowed it. */
     if(*(&_sstack) != STACK_CANARY_WORD) {
         puts("\nISR stack overflowed");
     }
     /* Sanity check stack pointer and give additional feedback about hard fault */
-    if( corrupted ) {
+    if(corrupted) {
         puts("Stack pointer corrupted, reset to top of stack");
-    } else {
-#if CPU_HAS_EXTENDED_FAULT_REGISTERS
-        /* Copy status register contents to local stack storage, this must be
-         * done before any calls to other functions to avoid corrupting the
-         * register contents. */
-        uint32_t bfar  = SCB->BFAR;
-        uint32_t mmfar = SCB->MMFAR;
-        uint32_t cfsr  = SCB->CFSR;
-        uint32_t hfsr  = SCB->HFSR;
-        uint32_t dfsr  = SCB->DFSR;
-        uint32_t afsr  = SCB->AFSR;
-#endif
-
+    }
+    else {
         uint32_t  r0 = sp[0];
         uint32_t  r1 = sp[1];
         uint32_t  r2 = sp[2];
         uint32_t  r3 = sp[3];
         uint32_t r12 = sp[4];
         uint32_t  lr = sp[5];  /* Link register. */
-        uint32_t  pc = sp[6];  /* Program counter. */
+                  pc = sp[6];  /* Program counter. */
         uint32_t psr = sp[7];  /* Program status register. */
 
         /* Reconstruct original stack pointer before fault occurred */
-        uint32_t* orig_sp = sp + 8;
+        orig_sp = sp + 8;
         if (psr & SCB_CCR_STKALIGN_Msk) {
             /* Stack was not 8-byte aligned */
             orig_sp += 1;
@@ -244,23 +247,26 @@ __attribute__((used)) void hard_fault_handler(uint32_t* sp, uint32_t corrupted,
                "   pc: 0x%08" PRIx32 "\n"
                "  psr: 0x%08" PRIx32 "\n\n",
                r12, lr, pc, psr);
+    }
 #if CPU_HAS_EXTENDED_FAULT_REGISTERS
-        puts("FSR/FAR:");
-        printf(" CFSR: 0x%08" PRIx32 "\n", cfsr);
-        printf(" HFSR: 0x%08" PRIx32 "\n", hfsr);
-        printf(" DFSR: 0x%08" PRIx32 "\n", dfsr);
-        printf(" AFSR: 0x%08" PRIx32 "\n", afsr);
-        if (((cfsr & SCB_CFSR_BUSFAULTSR_Msk) >> SCB_CFSR_BUSFAULTSR_Pos) & 0x80) {
-            /* BFAR valid flag set */
-            printf(" BFAR: 0x%08" PRIx32 "\n", bfar);
-        }
-        if (((cfsr & SCB_CFSR_MEMFAULTSR_Msk) >> SCB_CFSR_MEMFAULTSR_Pos) & 0x80) {
-            /* MMFAR valid flag set */
-            printf("MMFAR: 0x%08" PRIx32 "\n", mmfar);
-        }
+    puts("FSR/FAR:");
+    printf(" CFSR: 0x%08" PRIx32 "\n", cfsr);
+    printf(" HFSR: 0x%08" PRIx32 "\n", hfsr);
+    printf(" DFSR: 0x%08" PRIx32 "\n", dfsr);
+    printf(" AFSR: 0x%08" PRIx32 "\n", afsr);
+    if (((cfsr & SCB_CFSR_BUSFAULTSR_Msk) >> SCB_CFSR_BUSFAULTSR_Pos) & 0x80) {
+        /* BFAR valid flag set */
+        printf(" BFAR: 0x%08" PRIx32 "\n", bfar);
+    }
+    if (((cfsr & SCB_CFSR_MEMFAULTSR_Msk) >> SCB_CFSR_MEMFAULTSR_Pos) & 0x80) {
+        /* MMFAR valid flag set */
+        printf("MMFAR: 0x%08" PRIx32 "\n", mmfar);
+    }
 #endif
-        puts("Misc");
-        printf("EXC_RET: 0x%08" PRIx32 "\n", exc_return);
+    puts("Misc");
+    printf("EXC_RET: 0x%08" PRIx32 "\n", exc_return);
+
+    if (!corrupted) {
         puts("Attempting to reconstruct state for debugging...");
         printf("In GDB:\n  set $pc=0x%" PRIx32 "\n  frame 0\n  bt\n", pc);
         int stack_left = _stack_size_left(HARDFAULT_HANDLER_REQUIRED_STACK_SPACE);
@@ -295,8 +301,8 @@ __attribute__((used)) void hard_fault_handler(uint32_t* sp, uint32_t corrupted,
               [extra_stack] "r" (r4_to_r11_stack)
             : "r0","r1","r2","r3","r12"
             );
-        __BKPT(1);
     }
+    __BKPT(1);
 
     core_panic(PANIC_HARD_FAULT, "HARD FAULT HANDLER");
 }
-- 
GitLab