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:
Carlo Caione 2022-05-04 14:26:31 +02:00 committed by Carles Cufí
parent 0ed637a7b6
commit 2f5fef960e
7 changed files with 225 additions and 0 deletions

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

View 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.

View file

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

View file

@ -0,0 +1,3 @@
CONFIG_PM=y
CONFIG_PM_S2RAM=y
CONFIG_GPIO=y

View file

@ -0,0 +1,7 @@
sample:
name: S2RAM Sample for nRF5x
common:
tags: power
tests:
sample.boards.nrf.s2ram:
platform_allow: nrf5340dk_nrf5340_cpuapp

View 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 */
}
}

View file

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