diff --git a/cpu/arm7_common/arm7_init.c b/cpu/arm7_common/arm7_init.c index 0dfdf92733..47c0d79a9b 100644 --- a/cpu/arm7_common/arm7_init.c +++ b/cpu/arm7_common/arm7_init.c @@ -24,6 +24,7 @@ #include "puf_sram.h" #endif +#include "cpu.h" #include "log.h" static inline void @@ -35,6 +36,15 @@ _init_data(void) extern unsigned int __bss_start; extern unsigned int __bss_end; +/* Support for LPRAM. */ +#ifdef CPU_HAS_BACKUP_RAM + extern unsigned int _sbackup_data_load[]; + extern unsigned int _sbackup_data[]; + extern unsigned int _ebackup_data[]; + extern unsigned int _sbackup_bss[]; + extern unsigned int _ebackup_bss[]; +#endif /* CPU_HAS_BACKUP_RAM */ + register unsigned int *p1; register unsigned int *p2; register unsigned int *p3; @@ -57,6 +67,23 @@ _init_data(void) while (p1 < p2) { *p1++ = 0; } + +#ifdef CPU_HAS_BACKUP_RAM + if (cpu_woke_from_backup()) { + + /* load low-power data section. */ + for (p1 = _sbackup_data, p2 = _sbackup_data_load; + p1 < _ebackup_data; + p1++, p2++) { + *p1 = *p2; + } + + /* zero-out low-power bss. */ + for (p1 = _sbackup_bss; p1 < _ebackup_bss; p1++) { + *p1 = 0; + } + } +#endif /* CPU_HAS_BACKUP_RAM */ } void bootloader(void) diff --git a/cpu/lpc2387/Makefile.features b/cpu/lpc2387/Makefile.features index 58e25954b0..296fd508bc 100644 --- a/cpu/lpc2387/Makefile.features +++ b/cpu/lpc2387/Makefile.features @@ -1,5 +1,6 @@ # Put defined MCU peripherals here (in alphabetical order) -FEATURES_PROVIDED += periph_gpio periph_gpio_irq +FEATURES_PROVIDED += backup_ram FEATURES_PROVIDED += periph_dac +FEATURES_PROVIDED += periph_gpio periph_gpio_irq -include $(RIOTCPU)/arm7_common/Makefile.features diff --git a/cpu/lpc2387/cpu.c b/cpu/lpc2387/cpu.c index d48e3f7c41..1f5cc7a3fc 100644 --- a/cpu/lpc2387/cpu.c +++ b/cpu/lpc2387/cpu.c @@ -136,4 +136,37 @@ void cpu_init(void) periph_init(); } +/* RSIR will only have POR bit set even when waking up from Deep Power Down + * Use signature in battery RAM to discriminate between Deep Power Down and POR + */ +bool cpu_woke_from_backup(void) +{ + static char signature[] __attribute__((section(".backup.data"))) = { + 'R', 'I', 'O', 'T' + }; + + /* external reset */ + if (RSIR & RSIR_EXTR) { + return false; + } + + if (signature[0] != 'R') { + return false; + } + + if (signature[1] != 'I') { + return false; + } + + if (signature[2] != 'O') { + return false; + } + + if (signature[3] != 'T') { + return false; + } + + return true; +} + /** @} */ diff --git a/cpu/lpc2387/include/cpu.h b/cpu/lpc2387/include/cpu.h index a56181d573..ecc188e823 100644 --- a/cpu/lpc2387/include/cpu.h +++ b/cpu/lpc2387/include/cpu.h @@ -57,6 +57,16 @@ static inline void cpu_print_last_instruction(void) printf("%p\n", (void*) lr_ptr); } +/** + * @brief Returns true if the CPU woke from Deep Sleep + */ +bool cpu_woke_from_backup(void); + +/** + * @brief The CPU has RAM that is retained in the deepest sleep mode. + */ +#define CPU_HAS_BACKUP_RAM (1) + #ifdef __cplusplus } #endif diff --git a/cpu/lpc2387/ldscripts/lpc2387.ld b/cpu/lpc2387/ldscripts/lpc2387.ld index 2cd0b15fe1..072e17774a 100644 --- a/cpu/lpc2387/ldscripts/lpc2387.ld +++ b/cpu/lpc2387/ldscripts/lpc2387.ld @@ -171,7 +171,7 @@ SECTIONS * collect all initialized .data sections that go into RAM * initial values get placed at the end of .text in flash */ - .data : AT (_etext) + .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 */ @@ -196,7 +196,7 @@ SECTIONS KEEP(*(SORT(.fini_array.*))) KEEP(*(.fini_array)) PROVIDE_HIDDEN (__fini_array_end = .); - } >ram /* put all the above into RAM (but load the LMA copy into FLASH) */ + } >ram AT > flash /* 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 */ @@ -287,9 +287,20 @@ SECTIONS } > ram_usb __heap_size = SIZEOF(.heap3); - - .batteryram (NOLOAD) : /* battery ram stays on during powerdown but needs to be handled specially */ - { - *(.batteryram) + .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); } > 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> flash }