mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #11486 from benpicco/saml21-lpram
cpu/saml21: Make Low-Power SRAM available to programs
This commit is contained in:
commit
aed628f08b
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@ -78,7 +92,7 @@ __attribute__((weak)) void post_startup (void)
|
||||
void reset_handler_default(void)
|
||||
{
|
||||
uint32_t *dst;
|
||||
uint32_t *src = &_etext;
|
||||
const uint32_t *src = &_etext;
|
||||
|
||||
#ifdef MODULE_PUF_SRAM
|
||||
puf_sram_init((uint8_t *)&_srelocate, SEED_RAM_LEN);
|
||||
@ -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(
|
||||
|
@ -476,6 +476,18 @@ static inline void sercom_set_gen(void *sercom, uint32_t gclk)
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the CPU woke deep sleep (backup/standby)
|
||||
*/
|
||||
static inline bool cpu_woke_from_backup(void)
|
||||
{
|
||||
#ifdef RSTC_RCAUSE_BACKUP
|
||||
return RSTC->RCAUSE.bit.BACKUP;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ADC Channel Configuration
|
||||
*/
|
||||
|
@ -1,3 +1,4 @@
|
||||
FEATURES_PROVIDED += periph_hwrng
|
||||
FEATURES_PROVIDED += backup_ram
|
||||
|
||||
include $(RIOTCPU)/sam0_common/Makefile.features
|
||||
|
@ -8,5 +8,8 @@ RIOTBOOT_LEN ?= 0x4000
|
||||
|
||||
USEMODULE += pm_layered
|
||||
|
||||
BACKUP_RAM_ADDR = 0x47000000
|
||||
BACKUP_RAM_LEN = 0x2000
|
||||
|
||||
include $(RIOTCPU)/sam0_common/Makefile.include
|
||||
include $(RIOTMAKE)/arch/cortexm.inc.mk
|
||||
|
@ -1,8 +1,15 @@
|
||||
# The SAMR30 line of MCUs does not contain a TRNG
|
||||
BOARDS_WITHOUT_HWRNG += samr30-xpro
|
||||
|
||||
# Low Power SRAM is *not* retained during Backup Sleep.
|
||||
# It therefore does not fulfill the requirements of the 'backup_ram' interface.
|
||||
# It can still be used in normal and standby mode, but code that relies on it
|
||||
# being availiable during deep sleep / backup mode will not be portable here.
|
||||
FEATURES_PROVIDED += backup_ram
|
||||
|
||||
ifeq (,$(filter $(BOARDS_WITHOUT_HWRNG),$(BOARD)))
|
||||
FEATURES_PROVIDED += periph_hwrng
|
||||
endif
|
||||
|
||||
|
||||
include $(RIOTCPU)/sam0_common/Makefile.features
|
||||
|
@ -3,5 +3,10 @@ export CPU_FAM = saml21
|
||||
|
||||
USEMODULE += pm_layered
|
||||
|
||||
ifneq (,$(filter saml21j18b saml21j18a samr30g18a samr34j18b,$(CPU_MODEL)))
|
||||
BACKUP_RAM_ADDR = 0x30000000
|
||||
BACKUP_RAM_LEN = 0x2000
|
||||
endif
|
||||
|
||||
include $(RIOTCPU)/sam0_common/Makefile.include
|
||||
include $(RIOTMAKE)/arch/cortexm.inc.mk
|
||||
|
@ -26,6 +26,11 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief The Low Power SRAM is not retained during deep sleep.
|
||||
*/
|
||||
#define CPU_BACKUP_RAM_NOT_RETAINED (1)
|
||||
|
||||
/**
|
||||
* @brief Mapping of pins to EXTI lines, -1 means not EXTI possible
|
||||
*/
|
||||
|
11
tests/periph_backup_ram/Makefile
Normal file
11
tests/periph_backup_ram/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
include ../Makefile.tests_common
|
||||
|
||||
FEATURES_REQUIRED = backup_ram
|
||||
|
||||
USEMODULE += pm_layered
|
||||
USEMODULE += periph_rtc
|
||||
USEMODULE += xtimer
|
||||
|
||||
CFLAGS += -DLOG_LEVEL=LOG_WARNING
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
10
tests/periph_backup_ram/README.md
Normal file
10
tests/periph_backup_ram/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
Expected result
|
||||
===============
|
||||
This test periodically puts the device into deep sleep mode.
|
||||
During deep sleep only the backup RAM is retained and the device is
|
||||
reset upon leaving deep sleep.
|
||||
To test the memory retention, a counter is incemented with each wake-up.
|
||||
|
||||
Background
|
||||
==========
|
||||
Test the functionality of a platforms Backup RAM implementation.
|
80
tests/periph_backup_ram/main.c
Normal file
80
tests/periph_backup_ram/main.c
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2019 ML!PA Consulting GmbH
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Low-level test for backup RAM
|
||||
*
|
||||
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "periph/rtc.h"
|
||||
#include "pm_layered.h"
|
||||
#include "xtimer.h"
|
||||
|
||||
#ifndef SLEEP_SEC
|
||||
#define SLEEP_SEC 1
|
||||
#endif
|
||||
|
||||
#ifndef DELAY_SEC
|
||||
#define DELAY_SEC 3
|
||||
#endif
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* We keep a copy of counter in the .noinit section (normal RAM).
|
||||
* In the deepest sleep normal RAM is not retained, so if it matches
|
||||
* counter anyway after wakeup, we did not sleep properly.
|
||||
*/
|
||||
static int counter_noinit __attribute__((section(".noinit")));
|
||||
static int counter __attribute__((section(".backup.bss")));
|
||||
|
||||
if (counter == 0) {
|
||||
puts("\nBackup RAM test\n");
|
||||
printf("This test will increment the counter by 1, "
|
||||
"then enter deep sleep for %ds.\n\n", SLEEP_SEC);
|
||||
printf(" Because some tools have trouble re-flashing/debugging in deep sleep,\n"
|
||||
" the test will wait for %ds before entering deep sleep.\n\n", DELAY_SEC);
|
||||
} else if (counter_noinit == counter) {
|
||||
puts("WARNING: non-backup memory retained - did we really enter deep sleep?");
|
||||
}
|
||||
|
||||
printf("counter: %d\n", ++counter);
|
||||
counter_noinit = counter;
|
||||
|
||||
/* Some tools have trouble flashing MCUs in deep sleep.
|
||||
* Wait a bit to make re-flashing / debugging easier.
|
||||
*/
|
||||
xtimer_sleep(DELAY_SEC);
|
||||
|
||||
#ifndef CPU_BACKUP_RAM_NOT_RETAINED
|
||||
|
||||
/* schedule RTC wake in SLEEP_SEC s */
|
||||
struct tm time;
|
||||
rtc_get_time(&time);
|
||||
time.tm_sec += SLEEP_SEC;
|
||||
rtc_set_alarm(&time, NULL, NULL);
|
||||
|
||||
/* put the device in deep sleep */
|
||||
pm_set(0);
|
||||
|
||||
puts("would sleep now - YOU SHOULD NOT SEE THIS!");
|
||||
|
||||
#else
|
||||
puts("low power RAM not retained during sleep - aborting test.");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user