diff --git a/samples/boards/nordic/system_off/CMakeLists.txt b/samples/boards/nordic/system_off/CMakeLists.txt index 1cff779506b..986fca97f34 100644 --- a/samples/boards/nordic/system_off/CMakeLists.txt +++ b/samples/boards/nordic/system_off/CMakeLists.txt @@ -5,6 +5,6 @@ find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(nrf_system_off) target_sources(app PRIVATE src/main.c) -if (CONFIG_APP_USE_NRF_RETENTION OR CONFIG_APP_USE_RETAINED_MEM) +if (CONFIG_APP_USE_RETAINED_MEM) target_sources(app PRIVATE src/retained.c) endif() diff --git a/samples/boards/nordic/system_off/Kconfig b/samples/boards/nordic/system_off/Kconfig index c5a0f492d90..798927205bd 100644 --- a/samples/boards/nordic/system_off/Kconfig +++ b/samples/boards/nordic/system_off/Kconfig @@ -3,23 +3,9 @@ mainmenu "Nordic SYSTEM_OFF demo" -choice - prompt "Use retention" - optional - -config APP_USE_NRF_RETENTION - bool "Use state retention in system off using nRF POWER" - depends on SOC_COMPATIBLE_NRF52X && CRC - help - On some Nordic chips this application supports retaining - memory while in system off using POWER peripheral. - Select this to enable the feature. - config APP_USE_RETAINED_MEM bool "Use state retention in system off using retained_mem driver" - depends on RETAINED_MEM - -endchoice + select RETAINED_MEM config GRTC_WAKEUP_ENABLE bool "Use GRTC to wake up device from system off" diff --git a/samples/boards/nordic/system_off/README.rst b/samples/boards/nordic/system_off/README.rst index 7c98a4e8336..5124d087b77 100644 --- a/samples/boards/nordic/system_off/README.rst +++ b/samples/boards/nordic/system_off/README.rst @@ -13,10 +13,10 @@ deep sleep on Nordic platforms. RAM Retention ============= -This sample can also can demonstrate RAM retention. By selecting -``CONFIG_APP_USE_NRF_RETENTION=y`` or ``CONFIG_APP_USE_RETAINED_MEM=y`` -state related to number of boots, number of times system off was entered, -and total uptime since initial power-on are retained in a checksummed data structure. +This sample can also demonstrate RAM retention. +By selecting ``CONFIG_APP_USE_RETAINED_MEM=y`` state related to number of boots, +number of times system off was entered, and total uptime since initial power-on +are retained in a checksummed data structure. RAM is configured to keep the containing section powered while in system-off mode. Requirements diff --git a/samples/boards/nordic/system_off/boards/nrf52840dk_nrf52840.overlay b/samples/boards/nordic/system_off/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 00000000000..c203d90a0a1 --- /dev/null +++ b/samples/boards/nordic/system_off/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,22 @@ +/ { + sram0@2003f000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x2003f000 DT_SIZE_K(4)>; + zephyr,memory-region = "RetainedMem"; + status = "okay"; + + retainedmem0: retainedmem { + compatible = "zephyr,retained-ram"; + status = "okay"; + }; + }; + + aliases { + retainedmemdevice = &retainedmem0; + }; +}; + +&sram0 { + /* Shrink SRAM size to avoid overlap with retained memory region */ + reg = <0x20000000 DT_SIZE_K(252)>; +}; diff --git a/samples/boards/nordic/system_off/boards/nrf52dk_nrf52832.overlay b/samples/boards/nordic/system_off/boards/nrf52dk_nrf52832.overlay new file mode 100644 index 00000000000..13e2e99ddf2 --- /dev/null +++ b/samples/boards/nordic/system_off/boards/nrf52dk_nrf52832.overlay @@ -0,0 +1,22 @@ +/ { + sram0@20007000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x20007000 DT_SIZE_K(4)>; + zephyr,memory-region = "RetainedMem"; + status = "okay"; + + retainedmem0: retainedmem { + compatible = "zephyr,retained-ram"; + status = "okay"; + }; + }; + + aliases { + retainedmemdevice = &retainedmem0; + }; +}; + +&sram0 { + /* Shrink SRAM size to avoid overlap with retained memory region */ + reg = <0x20000000 DT_SIZE_K(28)>; +}; diff --git a/samples/boards/nordic/system_off/boards/nrf54l15dk_nrf54l05_cpuapp_retained_mem.overlay b/samples/boards/nordic/system_off/boards/nrf54l15dk_nrf54l05_cpuapp.overlay similarity index 100% rename from samples/boards/nordic/system_off/boards/nrf54l15dk_nrf54l05_cpuapp_retained_mem.overlay rename to samples/boards/nordic/system_off/boards/nrf54l15dk_nrf54l05_cpuapp.overlay diff --git a/samples/boards/nordic/system_off/boards/nrf54l15dk_nrf54l10_cpuapp_retained_mem.overlay b/samples/boards/nordic/system_off/boards/nrf54l15dk_nrf54l10_cpuapp.overlay similarity index 100% rename from samples/boards/nordic/system_off/boards/nrf54l15dk_nrf54l10_cpuapp_retained_mem.overlay rename to samples/boards/nordic/system_off/boards/nrf54l15dk_nrf54l10_cpuapp.overlay diff --git a/samples/boards/nordic/system_off/boards/nrf54l15dk_nrf54l15_cpuapp_retained_mem.overlay b/samples/boards/nordic/system_off/boards/nrf54l15dk_nrf54l15_cpuapp.overlay similarity index 100% rename from samples/boards/nordic/system_off/boards/nrf54l15dk_nrf54l15_cpuapp_retained_mem.overlay rename to samples/boards/nordic/system_off/boards/nrf54l15dk_nrf54l15_cpuapp.overlay diff --git a/samples/boards/nordic/system_off/sample.yaml b/samples/boards/nordic/system_off/sample.yaml index 18f629c4e54..fcc96f6c44d 100644 --- a/samples/boards/nordic/system_off/sample.yaml +++ b/samples/boards/nordic/system_off/sample.yaml @@ -22,32 +22,17 @@ tests: - "system off demo" - "Retained data not supported" - "Entering system off; press sw0 to restart" - sample.boards.nrf.system_off.nrf_retained: + sample.boards.nrf.system_off.retained_mem: integration_platforms: - nrf52840dk/nrf52840 platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 - extra_configs: - - CONFIG_APP_USE_NRF_RETENTION=y - harness: console - harness_config: - type: multi_line - ordered: true - regex: - - "system off demo" - - "Retained data: INVALID" - - "Boot count: 1" - - "Off count: 0" - - "Active Ticks:" - - "Entering system off; press sw0 to restart" - sample.boards.nrf.system_off.retained_mem: - extra_args: DTC_OVERLAY_FILE="boards/nrf54l15dk_nrf54l15_cpuapp_retained_mem.overlay" - platform_allow: - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l10/cpuapp + - nrf54l15dk/nrf54l05/cpuapp extra_configs: - CONFIG_APP_USE_RETAINED_MEM=y - - CONFIG_RETAINED_MEM=y harness: console harness_config: type: multi_line @@ -62,6 +47,8 @@ tests: sample.boards.nrf.system_off.grtc_wakeup: platform_allow: - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l10/cpuapp + - nrf54l15dk/nrf54l05/cpuapp extra_configs: - CONFIG_GRTC_WAKEUP_ENABLE=y harness: console @@ -79,13 +66,13 @@ tests: - "Retained data not supported" - "Entering system off; wait 2 seconds to restart" sample.boards.nrf.system_off.retained_mem.grtc_wakeup: - extra_args: DTC_OVERLAY_FILE="boards/nrf54l15dk_nrf54l15_cpuapp_retained_mem.overlay" platform_allow: - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l10/cpuapp + - nrf54l15dk/nrf54l05/cpuapp extra_configs: - CONFIG_APP_USE_RETAINED_MEM=y - CONFIG_GRTC_WAKEUP_ENABLE=y - - CONFIG_RETAINED_MEM=y harness: console harness_config: type: multi_line diff --git a/samples/boards/nordic/system_off/src/main.c b/samples/boards/nordic/system_off/src/main.c index b40b1ea26da..40c4f2bb7a5 100644 --- a/samples/boards/nordic/system_off/src/main.c +++ b/samples/boards/nordic/system_off/src/main.c @@ -35,7 +35,7 @@ int main(void) printf("\n%s system off demo\n", CONFIG_BOARD); - if (IS_ENABLED(CONFIG_APP_USE_NRF_RETENTION) || IS_ENABLED(CONFIG_APP_USE_RETAINED_MEM)) { + if (IS_ENABLED(CONFIG_APP_USE_RETAINED_MEM)) { bool retained_ok = retained_validate(); /* Increment for this boot attempt and update. */ @@ -81,7 +81,7 @@ int main(void) return 0; } - if (IS_ENABLED(CONFIG_APP_USE_NRF_RETENTION) || IS_ENABLED(CONFIG_APP_USE_RETAINED_MEM)) { + if (IS_ENABLED(CONFIG_APP_USE_RETAINED_MEM)) { /* Update the retained state */ retained.off_count += 1; retained_update(); diff --git a/samples/boards/nordic/system_off/src/retained.c b/samples/boards/nordic/system_off/src/retained.c index 66f6a353f04..316ec165d62 100644 --- a/samples/boards/nordic/system_off/src/retained.c +++ b/samples/boards/nordic/system_off/src/retained.c @@ -15,147 +15,24 @@ #include #include -#if CONFIG_APP_USE_NRF_RETENTION -#include - -/* nRF52 RAM (really, RAM AHB slaves) are partitioned as: - * * Up to 8 blocks of two 4 KiBy byte "small" sections - * * A 9th block of with 32 KiBy "large" sections - * - * At time of writing the maximum number of large sections is 6, all - * within the first large block. Theoretically there could be more - * sections in the 9th block, and possibly more blocks. - */ - -/* Inclusive address of RAM start */ -#define SRAM_BEGIN (uintptr_t)DT_REG_ADDR(DT_NODELABEL(sram0)) - -/* Exclusive address of RAM end */ -#define SRAM_END (SRAM_BEGIN + (uintptr_t)DT_REG_SIZE(DT_NODELABEL(sram0))) - -/* Size of a controllable RAM section in the small blocks */ -#define SMALL_SECTION_SIZE 4096 - -/* Number of controllable RAM sections in each of the lower blocks */ -#define SMALL_SECTIONS_PER_BLOCK 2 - -/* Span of a small block */ -#define SMALL_BLOCK_SIZE (SMALL_SECTIONS_PER_BLOCK * SMALL_SECTION_SIZE) - -/* Number of small blocks */ -#define SMALL_BLOCK_COUNT 8 - -/* Span of the SRAM area covered by small sections */ -#define SMALL_SECTION_SPAN (SMALL_BLOCK_COUNT * SMALL_BLOCK_SIZE) - -/* Inclusive address of the RAM range covered by large sections */ -#define LARGE_SECTION_BEGIN (SRAM_BEGIN + SMALL_SECTION_SPAN) - -/* Size of a controllable RAM section in large blocks */ -#define LARGE_SECTION_SIZE 32768 - -#elif CONFIG_APP_USE_RETAINED_MEM +#if DT_NODE_HAS_STATUS_OKAY(DT_ALIAS(retainedmemdevice)) const static struct device *retained_mem_device = DEVICE_DT_GET(DT_ALIAS(retainedmemdevice)); -#endif - -/* Set or clear RAM retention in SYSTEM_OFF for the provided object. - * - * @param ptr pointer to the start of the retainable object - * - * @param len length of the retainable object - * - * @param enable true to enable retention, false to clear retention - */ -static int ram_range_retain(const void *ptr, - size_t len, - bool enable) -{ - int rc = 0; - -#if CONFIG_APP_USE_NRF_RETENTION - /* This only works for nRF52 with the POWER module. - * The other Nordic chips use a different low-level API, - * which is not currently used by this variant. - */ - uintptr_t addr = (uintptr_t)ptr; - uintptr_t addr_end = addr + len; - - /* Error if the provided range is empty or doesn't lie - * entirely within the SRAM address space. - */ - if ((len == 0U) - || (addr < SRAM_BEGIN) - || (addr > (SRAM_END - len))) { - return -EINVAL; - } - - /* Iterate over each section covered by the range, setting the - * corresponding RAM OFF retention bit in the parent block. - */ - do { - uintptr_t block_base = SRAM_BEGIN; - uint32_t section_size = SMALL_SECTION_SIZE; - uint32_t sections_per_block = SMALL_SECTIONS_PER_BLOCK; - bool is_large = (addr >= LARGE_SECTION_BEGIN); - uint8_t block = 0; - - if (is_large) { - block = 8; - block_base = LARGE_SECTION_BEGIN; - section_size = LARGE_SECTION_SIZE; - - /* RAM[x] supports only 16 sections, each its own bit - * for POWER (0..15) and RETENTION (16..31). We don't - * know directly how many sections are present, so - * assume they all are; the true limit will be - * determined by the SRAM size. - */ - sections_per_block = 16; - } - - uint32_t section = (addr - block_base) / section_size; - - if (section >= sections_per_block) { - block += section / sections_per_block; - section %= sections_per_block; - } - - uint32_t section_mask = - (POWER_RAM_POWERSET_S0RETENTION_On - << (section + POWER_RAM_POWERSET_S0RETENTION_Pos)); - - if (enable) { - nrf_power_rampower_mask_on(NRF_POWER, block, section_mask); - } else { - nrf_power_rampower_mask_off(NRF_POWER, block, section_mask); - } - - /* Move to the first address in the next section. */ - addr += section_size - (addr % section_size); - } while (addr < addr_end); -#elif CONFIG_APP_USE_RETAINED_MEM - /* Retention setting cannot be controlled runtime with retained_mem API */ - (void)enable; - rc = retained_mem_write(retained_mem_device, 0, ptr, len); #else - #error "Unsupported retention setting" +#error "retained_mem region not defined" #endif - return rc; -} - -/* Retained data must be defined in a no-init section to prevent the C - * runtime initialization from zeroing it before anybody can see it. - * It is not necesarry when retained_mem driver is utilized - * as in this case retained data is stored in an area not initialized in runtime. - */ -__noinit struct retained_data retained; +struct retained_data retained; #define RETAINED_CRC_OFFSET offsetof(struct retained_data, crc) #define RETAINED_CHECKED_SIZE (RETAINED_CRC_OFFSET + sizeof(retained.crc)) bool retained_validate(void) { + int rc; + + rc = retained_mem_read(retained_mem_device, 0, (uint8_t *)&retained, sizeof(retained)); + __ASSERT_NO_MSG(rc == 0); + /* The residue of a CRC is what you get from the CRC over the * message catenated with its CRC. This is the post-final-xor * residue for CRC-32 (CRC-32/ISO-HDLC) which Zephyr calls @@ -174,19 +51,13 @@ bool retained_validate(void) /* Reset to accrue runtime from this session. */ retained.uptime_latest = 0; - /* Reconfigure to retain the state during system off, regardless of - * whether validation succeeded. Although these values can sometimes - * be observed to be preserved across System OFF, the product - * specification states they are not retained in that situation, and - * that can also be observed. - */ - (void)ram_range_retain(&retained, RETAINED_CHECKED_SIZE, true); - return valid; } void retained_update(void) { + int rc; + uint64_t now = k_uptime_ticks(); retained.uptime_sum += (now - retained.uptime_latest); @@ -196,4 +67,7 @@ void retained_update(void) RETAINED_CRC_OFFSET); retained.crc = sys_cpu_to_le32(crc); + + rc = retained_mem_write(retained_mem_device, 0, (uint8_t *)&retained, sizeof(retained)); + __ASSERT_NO_MSG(rc == 0); }