1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-25 22:43:50 +01:00

cpu/lpc2387: add support for backup RAM

lpc23xx has 2k of battery RAM that is retained in Deep Power Down mode.

To not overwrite that data it must only be initialized on Power On Reset.
However, RSIR looks the same when waking up from Deep Power Down as it does
on the power-on case.

So use 4 bytes of the backup RAM to keep a signature that is only valid if
memory was retained (no power-on Reset).

A small change to the linker script is required so two sections can be
placed into flash.
This commit is contained in:
Benjamin Valentin 2019-11-09 23:56:29 +01:00 committed by Benjamin Valentin
parent 15fcbe837a
commit 32bbba2fc5
5 changed files with 89 additions and 7 deletions

View File

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

View File

@ -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

View File

@ -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;
}
/** @} */

View File

@ -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

View File

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