diff --git a/cpu/cc2538/ldscripts/cc2538.ld b/cpu/cc2538/ldscripts/cc2538.ld index 846248359abd17cdf71d4bff2fb4297548ef5f1e..54b52326ffbf036bf6112fafdf90816173171049 100644 --- a/cpu/cc2538/ldscripts/cc2538.ld +++ b/cpu/cc2538/ldscripts/cc2538.ld @@ -144,6 +144,10 @@ SECTIONS _sheap = . ; _eheap = ORIGIN(ram) + LENGTH(ram); + /* Populate information abour ram size */ + _sram = ORIGIN(ram); + _eram = ORIGIN(ram) + LENGTH(ram); + .flashcca : { KEEP(*(.flashcca)) diff --git a/cpu/cortexm_common/include/vectors_cortexm.h b/cpu/cortexm_common/include/vectors_cortexm.h index f47957ccb99bb3b598fed10fa899c8e5294fd1d7..30d899a6992a3288b137a97839033f8d2f37f03b 100644 --- a/cpu/cortexm_common/include/vectors_cortexm.h +++ b/cpu/cortexm_common/include/vectors_cortexm.h @@ -62,7 +62,7 @@ void nmi_default(void); * causes of hard faults are access to un-aligned pointers on Cortex-M0 CPUs * and calls of function pointers that are set to NULL. */ -void hard_fault_default(void); +void hard_fault_default(void) __attribute__((naked)); /* The following four exceptions are only present for Cortex-M3 and -M4 CPUs */ #if defined(CPU_ARCH_CORTEX_M3) || defined(CPU_ARCH_CORTEX_M4) || \ diff --git a/cpu/cortexm_common/ldscripts/cortexm_base.ld b/cpu/cortexm_common/ldscripts/cortexm_base.ld index 1dc468ec7ea4ec809fda42dfb16024b1447b0c68..a53c4df7eb2f6372bda5714f48b8d2aba6ee8fa2 100644 --- a/cpu/cortexm_common/ldscripts/cortexm_base.ld +++ b/cpu/cortexm_common/ldscripts/cortexm_base.ld @@ -143,4 +143,8 @@ SECTIONS . = ALIGN(4); _sheap = . ; _eheap = ORIGIN(ram) + LENGTH(ram); + + /* Populate information abour ram size */ + _sram = ORIGIN(ram); + _eram = ORIGIN(ram) + LENGTH(ram); } diff --git a/cpu/cortexm_common/vectors_cortexm.c b/cpu/cortexm_common/vectors_cortexm.c index 9fab189ae27f3b4da6295ab5df25d30a9ae45d28..6b90b2d56db1e5d0b32a6133c3e1a934b4de87e3 100644 --- a/cpu/cortexm_common/vectors_cortexm.c +++ b/cpu/cortexm_common/vectors_cortexm.c @@ -15,11 +15,13 @@ * exception handlers * * @author Hauke Petersen <hauke.petersen@fu-berlin.de> + * @author Daniel Krebs <github@daniel-krebs.net> * * @} */ #include <stdint.h> +#include <stdio.h> #include "board.h" #include "panic.h" @@ -39,6 +41,8 @@ extern uint32_t _szero; extern uint32_t _ezero; extern uint32_t _sstack; extern uint32_t _estack; +extern uint32_t _sram; +extern uint32_t _eram; /** @} */ /** @brief Interrupt stack canary value @@ -112,10 +116,92 @@ void nmi_default(void) core_panic(PANIC_NMI_HANDLER, "NMI HANDLER"); } +#ifdef DEVELHELP + +/* Trampoline function to save stackpointer before calling hardfault handler */ +void hard_fault_default(void) +{ + /* Get stackpointer where exception stackframe lies */ + __ASM volatile + ( + "movs r0, #4 \n" /* r0 = 0x4 */ + "mov r1, lr \n" /* r1 = lr */ + "tst r1, r0 \n" /* if(lr & 0x4) */ + "bne use_psp \n" /* { */ + "mrs r0, msp \n" /* r0 = msp */ + "b out \n" /* } */ + " use_psp: \n" /* else { */ + "mrs r0, psp \n" /* r0 = psp */ + " out: \n" /* } */ + "mov r1, #0 \n" /* corrupted = false */ + "cmp r0, sp \n" /* If msp is active stack- */ + "bne hardfault \n" /* pointer, check if valid so */ + "cmp r0, %[eram] \n" /* so calling c-func works . */ + "bge fix_msp \n" /* if(r0 == msp) { */ + "cmn r0, %[sram] \n" /* if( (r0 >= estack) || */ + "bl hardfault \n" /* (r0 < sstack) ) { */ + " fix_msp: \n" /* corrupted = true */ + "mov r0, %[estack] \n" /* r0 = _estack */ + "mov sp, r0 \n" /* sp = _estack */ + "mov r1, #1 \n" /* } */ + " hardfault: \n" /* } */ + "b hard_fault_handler \n" /* hard_fault_handler(r0) */ + : + : [sram] "r" (&_sram), + [eram] "r" (&_eram), + [estack] "r" (&_estack) + : "r0","r1" + ); +} + +void hard_fault_handler(uint32_t* sp, uint32_t corrupted) +{ + /* Make them volatile so that they won't get optimized out */ + volatile unsigned int r0; + volatile unsigned int r1; + volatile unsigned int r2; + volatile unsigned int r3; + volatile unsigned int r12; + volatile unsigned int lr; /* Link register. */ + volatile unsigned int pc; /* Program counter. */ + volatile unsigned int psr;/* Program status register. */ + + /* Sanity check stackpointer and give additional feedback about hardfault */ + if( corrupted ) { + puts("Stackpointer corrupted, reset to top of stack"); + } else { + r0 = sp[0]; + r1 = sp[1]; + r2 = sp[2]; + r3 = sp[3]; + r12 = sp[4]; + lr = sp[5]; + pc = sp[6]; + psr = sp[7]; + + puts("\nContext before hardfault:"); + + /* TODO: printf in ISR context might be a bad idea */ + printf("r0: 0x%x\n" + "r1: 0x%x\n" + "r2: 0x%x\n" + "r3: 0x%x\n", + r0, r1, r2, r3); + printf("r12: 0x%x\n" + "lr : 0x%x\n" + "pc : 0x%x\n" + "psr: 0x%x\n\n", + r12, lr, pc, psr); + } + + core_panic(PANIC_HARD_FAULT, "HARD FAULT HANDLER"); +} +#else void hard_fault_default(void) { core_panic(PANIC_HARD_FAULT, "HARD FAULT HANDLER"); } +#endif /* DEVELHELP */ #if defined(CPU_ARCH_CORTEX_M3) || defined(CPU_ARCH_CORTEX_M4) || \ defined(CPU_ARCH_CORTEX_M4F) diff --git a/cpu/kinetis_common/ldscripts/kinetis.ld b/cpu/kinetis_common/ldscripts/kinetis.ld index 50aac950341ab67c5edba3903af3146c01f57c78..c8fb5ecc54b125200abdc038dc73e9b96289c6a5 100644 --- a/cpu/kinetis_common/ldscripts/kinetis.ld +++ b/cpu/kinetis_common/ldscripts/kinetis.ld @@ -199,6 +199,10 @@ SECTIONS _sheap = . ; _eheap = ORIGIN(sram) + LENGTH(sram); + /* Populate information abour ram size */ + _sram = ORIGIN(sram); + _eram = ORIGIN(sram) + LENGTH(sram); + /* Any debugging sections */ /* Stabs debugging sections. */ .stab 0 : { *(.stab) }