OS: Windows 10
NCS: 2.0.0
nRF Connect for Desktop: v3.12.0
Power Profiler: v3.5.3
We are starting work on battery optimization on our product. I setup the PPK2 with my nRF52833 DK to learn the PPK2 and implementing nRF52 low power modes in the Zephyr world.
I am running the Zephyr "System Off" demo on the DK. https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.0.0/zephyr/samples/boards/nrf/system_off/README.html
I setup the PPK2 with the DK and ran the demo, but I am seeing really odd results. As you can see, while the demo is going through it's stages, the PPK2 data logger looks correct.
However, approximately three seconds after then nRF52833 goes into "system off" mode, the PPK2 data logger displays the below, until a button 1 or reset button press.
Since I am new to nRF52 low power modes in Zephyr (long history with the old SDK) and this is the first time using the PPK2, I am unclear what I am seeing. I have attached main.c from the "system off" project for reference. Does anyone have an explanation for what I am seeing? Thanks in advance.
.
/* * Copyright (c) 2019 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ #include <stdio.h> #include <zephyr.h> #include <device.h> #include <init.h> #include <pm/pm.h> #include <pm/device.h> #include <pm/policy.h> #include <soc.h> #include "retained.h" #include <hal/nrf_gpio.h> #define CONSOLE_LABEL DT_LABEL(DT_CHOSEN(zephyr_console)) #define BUSY_WAIT_S 2U #define SLEEP_S 2U /* Prevent deep sleep (system off) from being entered on long timeouts * or `K_FOREVER` due to the default residency policy. * * This has to be done before anything tries to sleep, which means * before the threading system starts up between PRE_KERNEL_2 and * POST_KERNEL. Do it at the start of PRE_KERNEL_2. */ static int disable_ds_1(const struct device *dev) { ARG_UNUSED(dev); pm_policy_state_lock_get(PM_STATE_SOFT_OFF); return 0; } SYS_INIT(disable_ds_1, PRE_KERNEL_2, 0); void main(void) { int rc; const struct device *cons = device_get_binding(CONSOLE_LABEL); printk("\n%s system off demo\n", CONFIG_BOARD); if (IS_ENABLED(CONFIG_APP_RETENTION)) { bool retained_ok = retained_validate(); /* Increment for this boot attempt and update. */ retained.boots += 1; retained_update(); printk("Retained data: %s\n", retained_ok ? "valid" : "INVALID"); printk("Boot count: %u\n", retained.boots); printk("Off count: %u\n", retained.off_count); printk("Active Ticks: %" PRIu64 "\n", retained.uptime_sum); } else { printk("Retained data not supported\n"); } /* Configure to generate PORT event (wakeup) on button 1 press. */ nrf_gpio_cfg_input(NRF_DT_GPIOS_TO_PSEL(DT_ALIAS(sw0), gpios), NRF_GPIO_PIN_PULLUP); nrf_gpio_cfg_sense_set(NRF_DT_GPIOS_TO_PSEL(DT_ALIAS(sw0), gpios), NRF_GPIO_PIN_SENSE_LOW); printk("Busy-wait %u s\n", BUSY_WAIT_S); k_busy_wait(BUSY_WAIT_S * USEC_PER_SEC); printk("Busy-wait %u s with UART off\n", BUSY_WAIT_S); rc = pm_device_action_run(cons, PM_DEVICE_ACTION_SUSPEND); k_busy_wait(BUSY_WAIT_S * USEC_PER_SEC); rc = pm_device_action_run(cons, PM_DEVICE_ACTION_RESUME); printk("Sleep %u s\n", SLEEP_S); k_sleep(K_SECONDS(SLEEP_S)); printk("Sleep %u s with UART off\n", SLEEP_S); rc = pm_device_action_run(cons, PM_DEVICE_ACTION_SUSPEND); k_sleep(K_SECONDS(SLEEP_S)); rc = pm_device_action_run(cons, PM_DEVICE_ACTION_RESUME); printk("Entering system off; press BUTTON1 to restart\n"); if (IS_ENABLED(CONFIG_APP_RETENTION)) { /* Update the retained state */ retained.off_count += 1; retained_update(); } /* Above we disabled entry to deep sleep based on duration of * controlled delay. Here we need to override that, then * force entry to deep sleep on any delay. */ pm_state_force(0u, &(struct pm_state_info){PM_STATE_SOFT_OFF, 0, 0}); /* Now we need to go sleep. This will let the idle thread runs and * the pm subsystem will use the forced state. To confirm that the * forced state is used, lets set the same timeout used previously. */ k_sleep(K_SECONDS(SLEEP_S)); printk("ERROR: System off failed\n"); while (true) { /* spin to avoid fall-off behavior */ } }