
Many RTOS kernels use a heartbeat — a periodic interrupt that drives the scheduler, tracks timeouts, and advances task delays. In many RTOS implementations, this comes from a hardware timer like ARM’s SysTick. While effective for scheduling, this periodic tick becomes a liability in battery-powered embedded systems: every tick wakes the CPU, even when no work needs to be done.
This article explores how RTOS-based systems manage timing internally — through software timers and daemon tasks — and how tickless idle mode dramatically reduces power consumption by eliminating unnecessary wakeups.
Software timers let you schedule callback functions at a future time or periodically without dedicating a task to each timer. When configUSE_TIMERS is enabled, FreeRTOS implements them through a central daemon task created automatically when the scheduler starts.
When you call xTimerStart(), a command is sent through the timer command queue to the daemon task. When the timer expires, the daemon executes the callback. Two timer types exist: one-shot (fires once) and auto-reload (restarts automatically). Callbacks run in the daemon task context, so they must not call APIs that block the daemon task — doing so would delay all other timer callbacks.
Configure the daemon task via configTIMER_TASK_PRIORITY and configTIMER_TASK_STACK_DEPTH in FreeRTOSConfig.h. Choose its priority based on how quickly timer callbacks must run relative to your application’s real-time tasks.
A typical timeout pattern uses a one-shot timer:
void comm_timeout_callback(TimerHandle_t xTimer) {report_comm_failure();}void on_packet_sent(void) {xTimerStart(xCommTimeout, 0); // Start 2-second countdown}void on_packet_received(void) {xTimerStop(xCommTimeout, 0); // Cancel — response received}
For periodic work, auto-reload timers eliminate the need for a dedicated task:
void heartbeat_callback(TimerHandle_t xTimer) {toggle_status_led();}
Use hardware timers for sub-millisecond resolution or precise periodic interrupts. Use software timers for timeouts, heartbeats, and status checks where tick-level resolution and scheduler-induced latency are acceptable.
In a traditional ticked system, the periodic tick fires even when the CPU is idle. At 1 ms tick rate, that is 1,000 wakeups per second — each preventing the MCU from entering deep sleep. Tickless idle solves this by stopping the tick during idle periods and compensating the tick count on wakeup.
When only the Idle task can run and no tasks will become ready for a known duration, the kernel programs a wake-up source (RTC or adjusted SysTick), stops the periodic tick, and enters a low-power state. On wakeup, it compensates the kernel’s tick count using the elapsed time from the secondary timer.
FreeRTOS supports two levels: configUSE_TICKLESS_IDLE = 1 uses the built-in implementation on ports that support it; on many Cortex-M ports this typically enters sleep using WFI. Setting it to 2 allows a custom implementation for deeper, platform-specific low-power modes.
When SysTick cannot maintain time across a deeper low-power mode, a secondary timer (RTC, LPTIM) must track elapsed time. The following is illustrative pseudocode rather than a drop-in implementation:
void vApplicationSleep(TickType_t xExpectedIdleTime){uint32_t sleep_ms = xExpectedIdleTime * portTICK_PERIOD_MS;if (sleep_ms > 10) {configure_rtc_wakeup(sleep_ms);uint32_t rtc_before = read_rtc_counter();enter_stop_mode();uint32_t elapsed_ms = (read_rtc_counter() - rtc_before);vTaskStepTick(elapsed_ms / portTICK_PERIOD_MS);} else {__WFI();}}
The secondary timer must stay initialized and running continuously. Common choices include the RTC (32.768 kHz, ~30 microsecond resolution) or a low-power timer peripheral.
ARM Cortex-M cores provide Sleep and Deep Sleep behavior at the architecture level. MCU vendors often build additional product-specific low-power states on top of these, with names such as Stop, Standby, Deep Sleep, or Power-down. Power draw and wake-up latency vary dramatically by MCU family, board design, clock tree, and enabled peripherals; for example, NXP measured a 2.34 mA current reduction with tickless mode on an LPC55S16-EVK example.
FreeRTOS provides hook macros to optimize power around sleep transitions. configPRE_SLEEP_PROCESSING can gate peripheral clocks and lower core voltage. configPOST_SLEEP_PROCESSING restores the system to full operation after wakeup.
Zephyr RTOS takes a different approach from FreeRTOS. Its kernel commonly uses CONFIG_TICKLESS_KERNEL, so idle operation does not require a fixed periodic tick. Combined with Zephyr’s power management subsystem, this can help the system select deeper sleep states automatically when the platform supports them.
Timer management is foundational to every RTOS system. Software timers enable event-driven callback patterns without dedicated tasks. Tickless idle mode eliminates the wasted energy of periodic ticks during inactivity. By understanding these mechanisms — daemon task configuration, secondary timers for deep sleep, and sleep-level trade-offs — you can design firmware that meets both real-time deadlines and aggressive power budgets. For battery-powered products, tickless idle is the difference between hours and years of battery life.
Quick Links
Legal Stuff





