I've noticed weird behavior in the software timer scheduling. I my case, there is one timer handling LED blinking. It is used in single shot mode and rescheduled to time the lit up time and blank time. Once the blinking sequence is finished, the timer is not rescheduled and SoC keeps consuming way too much power (~500 uA).
There is something running with 60 s period since the app start, that resolves this increased power consumption.
If I time the LED blinking by sleeping the thread, the issue is not present - it is specific to software timer scheduling and power management tied to it.
Steps to reproduce
- Have a minimal application with power management enabled and SoC current measurement.
- make the main task sleep for some duration
- observer low power consumption (OK)
- Start software times with expiration before 60 s of uptime
- Observe power consumption after the timer expires -> elevated
- Wait for nearest future N*60 s uptime
- Observer power consumption drop to expected low power sleep levels

Environment
- host OS: Archlinux (up to date)
- toolchain: 16.2.0
- NRF connect SDK: 3.4.0
- Zephyr version: ncs-v3.4.0
- hardware: custom NRF54L15 based board
- measured with Joulescope JS-220
Appliction task body to get the idea about sequencing.
auto main() -> int {
AbsTime::sleep(10_s);
leds[0].blink(50_ms, 50_ms, 3);
AbsTime::sleep(10_s);
leds[0].blink(50_ms, 1_s, 3); // starts timer
AbsTime::sleep(60_s);
leds[0].blink(50_ms, 50_ms, 3); // starts timer
return 0;
}
Timer callback
void GpioPulsed::timerExpiredHandler(const std::size_t id) {
utils::RaiiExecutor flipper([&]{
config.on = not config.on;
});
if (config.on) {
gpio.setInactive();
if (config.infinite) {
Timer::start(config.offTime);
} else if (config.remains > 0) { // bot the last blink
Timer::start(config.offTime);
--config.remains;
} // else: end of sequence, no timer rescheduling
} else {
gpio.setActive();
Timer::start(config.onTime);
}
}CONFIG_BT=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_CENTRAL=y CONFIG_BT_MAX_CONN=4 CONFIG_BT_CTLR_SDC_PERIPHERAL_COUNT=2 CONFIG_BT_BONDABLE=n CONFIG_BT_PRIVACY=n CONFIG_BT_RECV_WORKQ_SYS=y CONFIG_BT_SCAN_AND_INITIATE_IN_PARALLEL=y CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS=n CONFIG_BT_AUTO_PHY_UPDATE=n CONFIG_BT_L2CAP_TX_MTU=247 CONFIG_BT_BUF_ACL_TX_SIZE=251 CONFIG_BT_BUF_ACL_RX_SIZE=251 CONFIG_BT_BUF_ACL_TX_COUNT=6 CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 CONFIG_BT_PERIPHERAL_PREF_MIN_INT=10 CONFIG_BT_GATT_CLIENT=y CONFIG_BT_GATT_DYNAMIC_DB=y CONFIG_BT_ATT_PREPARE_COUNT=6 CONFIG_BT_CHANNEL_SOUNDING=y CONFIG_BT_CTLR_PHY_2M=y CONFIG_BT_CTLR_SDC_CS_MAX_ANTENNA_PATHS=1 CONFIG_BT_CTLR_SDC_CS_NUM_ANTENNAS=1 CONFIG_BT_CTLR_SDC_CS_STEP_MODE3=n CONFIG_BT_CTLR_CHANNEL_SOUNDING_TEST=n CONFIG_BT_CTLR_SDC_CS_ROLE_REFLECTOR_ONLY=y CONFIG_BT_CTLR_EXTENDED_FEAT_SET=y CONFIG_BT_CTLR_CHANNEL_SOUNDING_TEST=n CONFIG_BT_TRANSMIT_POWER_CONTROL=y CONFIG_BT_SMP=y CONFIG_BT_TRANSMIT_POWER_CONTROL=y CONFIG_FPU=y CONFIG_FPU_SHARING=y CONFIG_MPSL_ASSERT_HANDLER=y CONFIG_ASSERT=y CONFIG_ASSERT_NO_MSG_INFO=y CONFIG_ASSERT_NO_FILE_INFO=y CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA=2 CONFIG_CPP=y CONFIG_STD_CPP2B=y CONFIG_REQUIRES_FULL_LIBCPP=y CONFIG_BOOTLOADER_MCUBOOT=n CONFIG_DEBUG=y CONFIG_DEBUG_THREAD_INFO=y CONFIG_MULTITHREADING=y CONFIG_SYS_HEAP_RUNTIME_STATS=y CONFIG_SYS_HEAP_LISTENER=y CONFIG_HEAP_MEM_POOL_SIZE=32768 CONFIG_NEWLIB_LIBC_MIN_REQUIRED_HEAP_SIZE=4096 CONFIG_NEWLIB_LIBC_HEAP_LISTENER=y CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 CONFIG_PWM=y CONFIG_FP16=n CONFIG_CBPRINTF_NANO=y CONFIG_ASSERT_VERBOSE=n CONFIG_ASSERT_NO_MSG_INFO=y CONFIG_BOOT_BANNER=n CONFIG_NCS_BOOT_BANNER=n CONFIG_HWINFO=y CONFIG_LOG=n CONFIG_CONSOLE=n CONFIG_PRINTK=n CONFIG_LOG_MODE_DEFERRED=n CONFIG_RTT_CONSOLE=n CONFIG_USE_SEGGER_RTT=n CONFIG_LOG_BACKEND_RTT=n CONFIG_LOG_BACKEND_RTT_MODE_OVERWRITE=n CONFIG_FAULT_DUMP=0 CONFIG_BT_CTLR_CONN_RSSI=y CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y CONFIG_PM=y CONFIG_PM_DEVICE=y CONFIG_PM_DEVICE_RUNTIME=y CONFIG_MAIN_STACK_SIZE=1024 CONFIG_FLASH=y CONFIG_FLASH_MAP=y CONFIG_SPI=y CONFIG_SPI_ASYNC=y CONFIG_SPI_NOR=y CONFIG_SPI_NOR_SFDP_RUNTIME=y CONFIG_FLASH_JESD216_API=y
