diff --git a/cpu/arm7_common/arm7_init.c b/cpu/arm7_common/arm7_init.c index a4e4161f70..75cb2d45cf 100644 --- a/cpu/arm7_common/arm7_init.c +++ b/cpu/arm7_common/arm7_init.c @@ -49,6 +49,26 @@ static inline void _init_data(void) register unsigned int *dst; register unsigned int *end; +#ifdef DEVELHELP + /* Fill user stack with canary values up until the current stack pointer */ + /* Read current stack pointer from CPU register */ + __asm__ volatile ("mov %[end], sp" : [end] "=r" (end) : : ); + dst = &__stack_start; + while (dst < end) { + *(dst++) = STACK_CANARY_WORD; + } + + /* fill the interrupt stacks with canary values */ + extern unsigned int __stack_usr_start; + extern unsigned int __stack_end; + + dst = &__stack_usr_start; + end = &__stack_end; + while (dst < end) { + *(dst++) = STACK_CANARY_WORD; + } +#endif + /* initialize data from flash */ src = &_etext; dst = &_srelocate; diff --git a/cpu/arm7_common/arm_cpu.c b/cpu/arm7_common/arm_cpu.c index 84657a51fb..222e9a97d7 100644 --- a/cpu/arm7_common/arm_cpu.c +++ b/cpu/arm7_common/arm_cpu.c @@ -94,3 +94,43 @@ void thread_print_stack(void) printf("STACK (%d)= %X \n", i, *s); } + +void *thread_isr_stack_start(void) +{ + extern uintptr_t __stack_irq_start; + return (void *)&__stack_irq_start; +} + +void *thread_isr_stack_pointer(void) +{ + void *_sp; + + /* If we are not in interrupt mode, the interrupt stack pointer will + * always point to the start of the interrupt stack. + */ + if (irq_is_in()) { + /* read stack pointer */ + __asm volatile ("mov %0, r13" : "=r" (_sp) ); + } else { + _sp = thread_isr_stack_start(); + } + + return _sp; +} + +/* This function returns the number of bytes used on the ISR stack */ +int thread_isr_stack_usage(void) +{ + extern uintptr_t __stack_irq_start; + extern uintptr_t __stack_irq_size; + + uintptr_t *ptr = &__stack_irq_start - (unsigned) &__stack_irq_size; + + while(((*ptr) == STACK_CANARY_WORD) && (ptr < &__stack_irq_start)) { + ++ptr; + } + + ptrdiff_t num_used_words = &__stack_irq_start - ptr; + + return num_used_words; +} diff --git a/cpu/arm7_common/include/arm_cpu.h b/cpu/arm7_common/include/arm_cpu.h index c0051411f0..e5810d96f3 100644 --- a/cpu/arm7_common/include/arm_cpu.h +++ b/cpu/arm7_common/include/arm_cpu.h @@ -25,6 +25,16 @@ void cpu_clock_scale(uint32_t source, uint32_t target, uint32_t *prescale); void arm_reset(void); +/** + * @brief Interrupt stack canary value + * + * @note 0xeafffffe is the ARM machine code equivalent of asm("b #0") or + * 'while (1);', i.e. an infinite loop. + * @internal + */ +#define STACK_CANARY_WORD (0xEAFFFFFEu) + + #ifdef __cplusplus } #endif diff --git a/cpu/lpc2387/include/cpu_conf.h b/cpu/lpc2387/include/cpu_conf.h index b7a385ec25..b2a4aeb7cb 100644 --- a/cpu/lpc2387/include/cpu_conf.h +++ b/cpu/lpc2387/include/cpu_conf.h @@ -76,6 +76,14 @@ extern "C" { */ #define PUF_SRAM_ATTRIBUTES __attribute__((used, section(".noinit"))) +/** + * @brief Stack size used for the exception (ISR) stack + * @{ + */ +extern unsigned __stack_irq_size; +#define ISR_STACKSIZE ((unsigned) &__stack_irq_size) +/** @} */ + #ifdef __cplusplus } #endif