sample: s2ram: Introduce S2RAM sample
Introduce a template / sample for S2RAM running on rf5340dk. Signed-off-by: Carlo Caione <ccaione@baylibre.com>
This commit is contained in:
parent
0ed637a7b6
commit
2f5fef960e
7
samples/boards/nrf/s2ram/CMakeLists.txt
Normal file
7
samples/boards/nrf/s2ram/CMakeLists.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.20.0)
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
project(nrf_s2ram)
|
||||
|
||||
target_sources(app PRIVATE src/main.c)
|
55
samples/boards/nrf/s2ram/README.rst
Normal file
55
samples/boards/nrf/s2ram/README.rst
Normal file
|
@ -0,0 +1,55 @@
|
|||
.. _nrf-s2ram-sample:
|
||||
|
||||
nRF5x S2RAM demo
|
||||
################
|
||||
|
||||
NOTE
|
||||
****
|
||||
|
||||
>> THIS IS A NON-FULLY FUNCTIONAL SAMPLE <<
|
||||
|
||||
Please note that the sample is only restoring the CPU context needed to
|
||||
continue the execution of the sample but it is not restoring any other core
|
||||
peripheral (NVIC, RTC, MPU, etc...), that must be taken care of separately by
|
||||
SoC or platform code, or device, that should be restored by the PM subsystem.
|
||||
This means that on resume we cannot use any device or core peripheral (timers,
|
||||
UART, etc..) so we use a GPIO LED instead.
|
||||
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
This sample can be used as template and to show the suspend-to-RAM (S2RAM)
|
||||
capability of Zephyr.
|
||||
|
||||
On boot the sample is turning the LED1 on and going immediately into S2RAM (the
|
||||
board is powered off). On suspend the CPU context is saved in RAM (that is
|
||||
retained) and a special marker is set in RAM to signal that the CPU has the
|
||||
context saved in RAM.
|
||||
|
||||
When the Button1 is pushed the board restarts from the reset routine and checks
|
||||
for the special marker. If the special marker is present, the CPU context is
|
||||
restored from RAM and the execution continues from the point where it left on
|
||||
suspend, turning the LED3 on.
|
||||
|
||||
Requirements
|
||||
************
|
||||
|
||||
This application uses nRF5340 DK board for the demo.
|
||||
|
||||
Building, Flashing and Running
|
||||
******************************
|
||||
|
||||
.. zephyr-app-commands::
|
||||
:zephyr-app: samples/boards/nrf/s2ram
|
||||
:board: nrf5340dk_nrf5340_cpuapp
|
||||
:goals: build flash
|
||||
:compact:
|
||||
|
||||
Running:
|
||||
|
||||
1. Open UART terminal.
|
||||
2. Power Cycle Device.
|
||||
3. LED1 will be on and the device will automatically turn itself off (S2RAM)
|
||||
4. Press Button 1 to wake the device and restart the application as if it had
|
||||
been powered back on and the LED3 will turn on.
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Carlo Caione <ccaione@baylibre.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/ {
|
||||
power-states {
|
||||
idle: idle {
|
||||
compatible = "zephyr,power-state";
|
||||
power-state-name = "suspend-to-idle";
|
||||
min-residency-us = <1000>;
|
||||
};
|
||||
|
||||
s2ram: s2ram {
|
||||
compatible = "zephyr,power-state";
|
||||
power-state-name = "suspend-to-ram";
|
||||
min-residency-us = <5000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&cpu0 {
|
||||
cpu-power-states = <&idle &s2ram>;
|
||||
};
|
3
samples/boards/nrf/s2ram/prj.conf
Normal file
3
samples/boards/nrf/s2ram/prj.conf
Normal file
|
@ -0,0 +1,3 @@
|
|||
CONFIG_PM=y
|
||||
CONFIG_PM_S2RAM=y
|
||||
CONFIG_GPIO=y
|
7
samples/boards/nrf/s2ram/sample.yaml
Normal file
7
samples/boards/nrf/s2ram/sample.yaml
Normal file
|
@ -0,0 +1,7 @@
|
|||
sample:
|
||||
name: S2RAM Sample for nRF5x
|
||||
common:
|
||||
tags: power
|
||||
tests:
|
||||
sample.boards.nrf.s2ram:
|
||||
platform_allow: nrf5340dk_nrf5340_cpuapp
|
92
samples/boards/nrf/s2ram/src/main.c
Normal file
92
samples/boards/nrf/s2ram/src/main.c
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Carlo Caione <ccaione@baylibre.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/zephyr.h>
|
||||
|
||||
#include <zephyr/pm/pm.h>
|
||||
#include <zephyr/pm/policy.h>
|
||||
|
||||
#include <zephyr/arch/common/pm_s2ram.h>
|
||||
|
||||
#include <hal/nrf_power.h>
|
||||
#include <hal/nrf_regulators.h>
|
||||
#include <hal/nrf_gpio.h>
|
||||
|
||||
static void system_off(void)
|
||||
{
|
||||
nrf_regulators_system_off(NRF_REGULATORS);
|
||||
}
|
||||
|
||||
static void do_suspend(void)
|
||||
{
|
||||
irq_lock();
|
||||
|
||||
/*
|
||||
* Save the CPU context (including the return address),set the SRAM
|
||||
* marker and power off the system.
|
||||
*/
|
||||
arch_pm_s2ram_suspend(system_off);
|
||||
|
||||
/*
|
||||
* XXX: On resuming we return exactly *HERE*
|
||||
*/
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
printk("S2RAM demo (%s)\n", CONFIG_BOARD);
|
||||
|
||||
/*
|
||||
* Enable wake-up button and LED1
|
||||
*/
|
||||
nrf_gpio_cfg_input(23, NRF_GPIO_PIN_PULLUP);
|
||||
nrf_gpio_cfg_sense_set(23, NRF_GPIO_PIN_SENSE_LOW);
|
||||
nrf_gpio_cfg_output(28);
|
||||
|
||||
/*
|
||||
* Sleep enough time to trigger S2RAM
|
||||
*/
|
||||
while (true) {
|
||||
k_msleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
void pm_state_set(enum pm_state state, uint8_t substate_id)
|
||||
{
|
||||
if (state != PM_STATE_SUSPEND_TO_RAM) {
|
||||
return;
|
||||
}
|
||||
|
||||
do_suspend();
|
||||
}
|
||||
|
||||
void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
|
||||
{
|
||||
if (state != PM_STATE_SUSPEND_TO_RAM) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Turn the LED3 on
|
||||
*/
|
||||
nrf_gpio_cfg_output(30);
|
||||
|
||||
/*
|
||||
* XXX: Read the README.rst
|
||||
*
|
||||
* This is not a fully functional test. To have the kernel back in a
|
||||
* fully functional state, here we should restore all the peripherals
|
||||
* of the platforms that will not be restored by the PM subsystem (like
|
||||
* NVIC, PMU, RTC, etc...). We are still missing the framework and code
|
||||
* for that, so for now we stop here.
|
||||
*/
|
||||
|
||||
irq_unlock(0);
|
||||
|
||||
while (true) {
|
||||
/* stop here */
|
||||
}
|
||||
}
|
|
@ -28,6 +28,9 @@
|
|||
#elif defined(CONFIG_SOC_NRF5340_CPUNET)
|
||||
#include <hal/nrf_nvmc.h>
|
||||
#endif
|
||||
#if defined(CONFIG_PM_S2RAM)
|
||||
#include <hal/nrf_vmc.h>
|
||||
#endif
|
||||
#include <soc_secure.h>
|
||||
|
||||
#define PIN_XL1 0
|
||||
|
@ -66,6 +69,35 @@ extern void z_arm_nmi_init(void);
|
|||
#define LOG_LEVEL CONFIG_SOC_LOG_LEVEL
|
||||
LOG_MODULE_REGISTER(soc);
|
||||
|
||||
#if defined(CONFIG_PM_S2RAM)
|
||||
|
||||
#if defined(CONFIG_SOC_NRF5340_CPUAPP)
|
||||
#define RAM_N_BLOCK (8)
|
||||
#elif defined(CONFIG_SOC_NRF5340_CPUNET)
|
||||
#define RAM_N_BLOCK (4)
|
||||
#endif /* CONFIG_SOC_NRF5340_CPUAPP || CONFIG_SOC_NRF5340_CPUNET */
|
||||
|
||||
#define MASK_ALL_SECT (VMC_RAM_POWER_S0RETENTION_Msk | VMC_RAM_POWER_S1RETENTION_Msk | \
|
||||
VMC_RAM_POWER_S2RETENTION_Msk | VMC_RAM_POWER_S3RETENTION_Msk | \
|
||||
VMC_RAM_POWER_S4RETENTION_Msk | VMC_RAM_POWER_S5RETENTION_Msk | \
|
||||
VMC_RAM_POWER_S6RETENTION_Msk | VMC_RAM_POWER_S7RETENTION_Msk | \
|
||||
VMC_RAM_POWER_S8RETENTION_Msk | VMC_RAM_POWER_S9RETENTION_Msk | \
|
||||
VMC_RAM_POWER_S10RETENTION_Msk | VMC_RAM_POWER_S11RETENTION_Msk | \
|
||||
VMC_RAM_POWER_S12RETENTION_Msk | VMC_RAM_POWER_S13RETENTION_Msk | \
|
||||
VMC_RAM_POWER_S14RETENTION_Msk | VMC_RAM_POWER_S15RETENTION_Msk)
|
||||
|
||||
static void enable_ram_retention(void)
|
||||
{
|
||||
/*
|
||||
* Enable RAM retention for *ALL* the SRAM
|
||||
*/
|
||||
for (size_t n = 0; n < RAM_N_BLOCK; n++) {
|
||||
nrf_vmc_ram_block_retention_set(NRF_VMC, n, MASK_ALL_SECT);
|
||||
}
|
||||
|
||||
}
|
||||
#endif /* CONFIG_PM_S2RAM */
|
||||
|
||||
static int nordicsemi_nrf53_init(const struct device *arg)
|
||||
{
|
||||
uint32_t key;
|
||||
|
@ -148,6 +180,10 @@ static int nordicsemi_nrf53_init(const struct device *arg)
|
|||
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PM_S2RAM)
|
||||
enable_ram_retention();
|
||||
#endif /* CONFIG_PM_S2RAM */
|
||||
|
||||
/* Install default handler that simply resets the CPU
|
||||
* if configured in the kernel, NOP otherwise
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue