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) }