diff --git a/cpu/cortexm_common/Makefile.include b/cpu/cortexm_common/Makefile.include index 4f68848e16..2d220a8f79 100644 --- a/cpu/cortexm_common/Makefile.include +++ b/cpu/cortexm_common/Makefile.include @@ -15,6 +15,12 @@ ifneq (,$(ROM_START_ADDR)$(RAM_START_ADDR)$(ROM_LEN)$(RAM_LEN)) LINKFLAGS += $(LINKFLAGPREFIX)--defsym=_ram_length=$(RAM_LEN) endif +ifneq (,$(BACKUP_RAM_LEN)) + LINKFLAGS += $(LINKFLAGPREFIX)--defsym=_backup_ram_start_addr=$(BACKUP_RAM_ADDR) + LINKFLAGS += $(LINKFLAGPREFIX)--defsym=_backup_ram_len=$(BACKUP_RAM_LEN) + CFLAGS += -DCPU_HAS_BACKUP_RAM=1 +endif + TOOLCHAINS_SUPPORTED = gnu llvm # Only define the linker symbol if the variable is set diff --git a/cpu/cortexm_common/ldscripts/cortexm.ld b/cpu/cortexm_common/ldscripts/cortexm.ld index aa84f27647..eb885b3389 100644 --- a/cpu/cortexm_common/ldscripts/cortexm.ld +++ b/cpu/cortexm_common/ldscripts/cortexm.ld @@ -24,8 +24,8 @@ INCLUDE cortexm_rom_offset.ld MEMORY { - rom (rx) : ORIGIN = _rom_start_addr + _rom_offset, LENGTH = _fw_rom_length - ram (w!rx) : ORIGIN = _ram_start_addr, LENGTH = _ram_length + rom (rx) : ORIGIN = _rom_start_addr + _rom_offset, LENGTH = _fw_rom_length + ram (w!rx) : ORIGIN = _ram_start_addr, LENGTH = _ram_length } INCLUDE cortexm_base.ld diff --git a/cpu/cortexm_common/ldscripts/cortexm_base.ld b/cpu/cortexm_common/ldscripts/cortexm_base.ld index bf1ae6fc20..f89e115fc8 100644 --- a/cpu/cortexm_common/ldscripts/cortexm_base.ld +++ b/cpu/cortexm_common/ldscripts/cortexm_base.ld @@ -34,6 +34,15 @@ SEARCH_DIR(.) /* This is only used by gdb to understand where to start */ ENTRY(reset_handler_default) +_backup_ram_start_addr = DEFINED( _backup_ram_start_addr ) ? _backup_ram_start_addr : 0x0 ; +_backup_ram_len = DEFINED( _backup_ram_len ) ? _backup_ram_len : 0x0 ; + +/* not all Cortex-M platforms use cortexm.ld yet */ +MEMORY +{ + bkup-ram (w!rx) : ORIGIN = _backup_ram_start_addr, LENGTH = _backup_ram_len +} + /* Section Definitions */ SECTIONS { @@ -159,4 +168,21 @@ SECTIONS /* Populate information about ram size */ _sram = ORIGIN(ram); _eram = ORIGIN(ram) + LENGTH(ram); + + _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); + } > bkup-ram AT> rom + + .backup.bss (NOLOAD) : ALIGN(4) { + _sbackup_bss = .; + *(.backup.bss) + _ebackup_bss = .; + /* Round size so that we can use 4 byte copy in init */ + . = ALIGN(4); + } > bkup-ram } diff --git a/cpu/cortexm_common/vectors_cortexm.c b/cpu/cortexm_common/vectors_cortexm.c index 60e53d5881..2312c3872d 100644 --- a/cpu/cortexm_common/vectors_cortexm.c +++ b/cpu/cortexm_common/vectors_cortexm.c @@ -26,6 +26,7 @@ #include #include "cpu.h" +#include "periph_cpu.h" #include "kernel_init.h" #include "board.h" #include "mpu.h" @@ -39,6 +40,10 @@ #define SRAM_BASE 0 #endif +#ifndef CPU_BACKUP_RAM_NOT_RETAINED +#define CPU_BACKUP_RAM_NOT_RETAINED 0 +#endif + /** * @brief Memory markers, defined in the linker script * @{ @@ -54,6 +59,15 @@ extern uint32_t _sstack; extern uint32_t _estack; extern uint8_t _sram; extern uint8_t _eram; + +/* Support for LPRAM. */ +#ifdef CPU_HAS_BACKUP_RAM +extern const uint32_t _sbackup_data_load[]; +extern uint32_t _sbackup_data[]; +extern uint32_t _ebackup_data[]; +extern uint32_t _sbackup_bss[]; +extern uint32_t _ebackup_bss[]; +#endif /* CPU_HAS_BACKUP_RAM */ /** @} */ /** @@ -101,11 +115,30 @@ void reset_handler_default(void) for (dst = &_srelocate; dst < &_erelocate; ) { *(dst++) = *(src++); } + /* default bss section to zero */ for (dst = &_szero; dst < &_ezero; ) { *(dst++) = 0; } +#ifdef CPU_HAS_BACKUP_RAM + if (!cpu_woke_from_backup() || + CPU_BACKUP_RAM_NOT_RETAINED) { + + /* load low-power data section. */ + for (dst = _sbackup_data, src = _sbackup_data_load; + dst < _ebackup_data; + dst++, src++) { + *dst = *src; + } + + /* zero-out low-power bss. */ + for (dst = _sbackup_bss; dst < _ebackup_bss; dst++) { + *dst = 0; + } + } +#endif /* CPU_HAS_BACKUP_RAM */ + #ifdef MODULE_MPU_STACK_GUARD if (((uintptr_t)&_sstack) != SRAM_BASE) { mpu_configure(