1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-17 05:12:57 +01:00

cpu/cortexm_common: Make Low-Power SRAM available to programs

Many MCUs contain some Backup or Low Power SRAM that is retained'even
in the deepest sleep modes.

In such sleep modes the MCU is essentually turned off with only the RTC
still running.
It can be woken by a GPIO or a RTC alarm. When this happens, a reset is
triggered and the normal startup routine is invoked.

This adds bss & data section for this memory in the linker script.
This allows for structures to be placed in it e.g.:

e.g.:

    static uint8_t persistent_buffer[64] __attribute__((section(".backup.bss")));
    static uint32_t persistent_counter __attribute__((section(".backup.data"))) = 1234;
This commit is contained in:
Benjamin Valentin 2019-05-03 17:13:26 +02:00
parent c9b827e5d5
commit 2c09d9bd5b
4 changed files with 67 additions and 2 deletions

View File

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

View File

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

View File

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

View File

@ -26,6 +26,7 @@
#include <inttypes.h>
#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(