diff --git a/cpu/arm7_common/arm7_init.c b/cpu/arm7_common/arm7_init.c index 715f3d2d93..75cb2d45cf 100644 --- a/cpu/arm7_common/arm7_init.c +++ b/cpu/arm7_common/arm7_init.c @@ -31,10 +31,10 @@ static inline void _init_data(void) { /* (linker script ensures that data is 32-bit aligned) */ extern unsigned int _etext; - extern unsigned int _data; - extern unsigned int _edata; - extern unsigned int __bss_start; - extern unsigned int __bss_end; + extern unsigned int _srelocate; /* .data section */ + extern unsigned int _erelocate; + extern unsigned int _szero; /* .bss section */ + extern unsigned int _ezero; /* Support for Battery Backup RAM */ #ifdef CPU_HAS_BACKUP_RAM @@ -49,18 +49,38 @@ 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 = &_data; - end = &_edata; + dst = &_srelocate; + end = &_erelocate; while (dst < end) { *dst++ = *src++; } /* clear bss */ - dst = &__bss_start; - end = &__bss_end; + dst = &_szero; + end = &_ezero; while (dst < end) { *dst++ = 0; @@ -99,9 +119,9 @@ void bootloader(void) _init_data(); #ifdef MODULE_PUF_SRAM - /* uninitialized heap starts after bss section */ - extern unsigned int __bss_end; - puf_sram_init((uint8_t *) __bss_end, SEED_RAM_LEN); + /* use uninitialized heap */ + extern unsigned _sheap; + puf_sram_init((uint8_t *) &_sheap, SEED_RAM_LEN); #endif /* cpu specific setup of clocks, peripherals */ 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 diff --git a/cpu/lpc2387/ldscripts/lpc2387.ld b/cpu/lpc2387/ldscripts/lpc2387.ld index d54513ddcd..8e266b5538 100644 --- a/cpu/lpc2387/ldscripts/lpc2387.ld +++ b/cpu/lpc2387/ldscripts/lpc2387.ld @@ -100,80 +100,11 @@ SECTIONS { *(.configmem) . = ALIGN(256); - } >infomem + } > infomem - /************************************************************************** - * RAM - **************************************************************************/ - - /* - * collect all zero initialized sections that go into RAM - */ - .bss (NOLOAD) : - { - . = ALIGN(4); /* ensure data is aligned so relocation can use 4-byte operations */ - __bss_start = .; /* define a global symbol marking the start of the .bss section */ - *(.bss*) /* all .bss sections */ - *(COMMON) - } > ram /* put all the above in RAM (it will be cleared in the startup code */ - . = ALIGN(4); /* ensure data is aligned so relocation can use 4-byte operations */ - __bss_end = . ; /* define a global symbol marking the end of the .bss section */ - - /* - * collect all initialized .data sections that go into RAM - * initial values get placed at the end of .text in flash - */ - .data : - { - . = ALIGN(4); /* ensure data is aligned so relocation can use 4-byte operations */ - _data = .; /* create a global symbol marking the start of the .data section */ - *(.data .data.*) /* all .data sections */ - *(.gnu.linkonce.d*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP(*(SORT(.fini_array.*))) - KEEP(*(.fini_array)) - PROVIDE_HIDDEN (__fini_array_end = .); - } >ram AT > rom /* put all the above into RAM (but load the LMA copy into FLASH) */ - . = ALIGN(4); /* ensure data is aligned so relocation can use 4-byte operations */ - _edata = .; /* define a global symbol marking the end of the .data section */ - - /* - * collect all uninitialized sections that go into RAM - */ - .noinit (NOLOAD) : - { - __noinit_start = .; - PROVIDE(__fiq_handler = .); - *(.fiq) - *(.noinit) - } > ram - . = ALIGN(4); - __noinit_end = .; - - _end = .; /* define a global symbol marking the end of application RAM */ - - __heap1_size = ORIGIN(ram) + LENGTH(ram) - . - __stack_size; - .heap1 (NOLOAD) : - { - PROVIDE(_sheap = .); - . = . + __heap1_size; - PROVIDE(_eheap = .); - } > ram +/************************************************************************** + * RAM + **************************************************************************/ /* * Stacks @@ -198,12 +129,56 @@ SECTIONS PROVIDE(__stack_end = .); } > ram + .relocate : + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + KEEP (*(.openocd .openocd.*)) + . = ALIGN(4); + _erelocate = .; + } > ram AT> rom + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + } > ram + + /* + * collect all uninitialized sections that go into RAM + */ + .noinit (NOLOAD) : + { + __noinit_start = .; + PROVIDE(__fiq_handler = .); + *(.fiq) + *(.noinit) + . = ALIGN(4); + __noinit_end = .; + } > ram + + /* heap section */ + . = ALIGN(4); + _sheap = . ; + _eheap = ORIGIN(ram) + LENGTH(ram); + + /* Populate information about ram size */ + _sram = ORIGIN(ram); + _eram = ORIGIN(ram) + LENGTH(ram); + __heap2_size = LENGTH(ram_ethernet); .heap2 (NOLOAD) : { PROVIDE(__heap2_start = . ); - . = . + __heap2_size; - PROVIDE(__heap2_max = .); /* _heap shall always be < _heap_max */ } > ram_ethernet . = ORIGIN(ram_usb); @@ -216,11 +191,18 @@ SECTIONS { __heap3_size = ORIGIN(ram_usb) + LENGTH(ram_usb) - ABSOLUTE(.); PROVIDE(__heap3_start = . ); - . += __heap3_size; - PROVIDE(__heap3_max = .); } > ram_usb __heap_size = SIZEOF(.heap3); + _sbackup_data_load = LOADADDR(.backup.data); + .backup.data : ALIGN(4) { + _sbackup_data = .; + *(.backup.data) + _ebackup_data = .; + /* Round size so that we can use 4 byte copy in init */ + . = ALIGN(4); + } > ram_battery AT> rom + .backup.bss (NOLOAD) : ALIGN(4) { _sbackup_bss = .; *(.backup.bss) @@ -228,13 +210,4 @@ SECTIONS /* Round size so that we can use 4 byte copy in init */ . = ALIGN(4); } > ram_battery - - _sbackup_data_load = LOADADDR(.backup.data); - .backup.data : ALIGN(4) { - _sbackup_data = .; - *(.backup.data) - _ebackup_data = .; - /* Round size so that we can use 4 byte copy in init */ - . = ALIGN(4); - } > ram_battery AT> rom } diff --git a/pkg/micropython/Makefile.dep b/pkg/micropython/Makefile.dep index af55a86953..4c012b59e9 100644 --- a/pkg/micropython/Makefile.dep +++ b/pkg/micropython/Makefile.dep @@ -5,7 +5,7 @@ USEMODULE += stdin FEATURES_BLACKLIST += arch_8bit arch_16bit # This port currently requires ISR_STACKSIZE and thread_isr_stack_start -FEATURES_BLACKLIST += arch_arm7 arch_esp32 arch_esp8266 arch_riscv +FEATURES_BLACKLIST += arch_esp32 arch_esp8266 arch_riscv # The port currently doesn't compile for mips FEATURES_BLACKLIST += arch_mips32r2