
Battery-operated embedded systems face constant pressure to maximize operational lifetime between charges. One often-overlooked optimization lies in the FreeRTOS tick rate configuration, which directly influences how frequently the microcontroller wakes from low-power states to execute the scheduler. This article examines the relationship between tick rate and power consumption, provides a methodology for selecting an optimal tick rate, details the necessary configuration changes, and quantifies the potential power savings for typical battery-powered applications.
The FreeRTOS kernel relies on a periodic timer interrupt, known as the tick interrupt, to manage timekeeping and task scheduling. By default, this interrupt occurs at a frequency defined by configTICK_RATE_HZ in FreeRTOSConfig.h. Common values range from 100Hz (10ms interval) to 1000Hz (1ms interval), with 1000Hz being frequent in many template projects.
Each tick interrupt serves several critical functions:
vTaskDelay() or semaphore takesHowever, every tick interrupt forces the CPU to exit sleep states, execute the interrupt service routine (ISR), and often run the scheduler before potentially returning to sleep. This wake-up cycle consumes measurable energy each time, particularly significant in battery-operated devices that spend most of their time in idle or sleep modes.
+----------------+ +----------------+ +----------------+| ASLEEP |--> | TICK ISR |--> | ASLEEP || (Low Power) | | (CPU Awake) | | (Low Power) |+----------------+ +----------------+ +----------------+^ 10ms interval ^ 10ms interval ^ 10ms interval| | |Tick #1 Tick #2 Tick #3
At 1000Hz tick rate, this wake-sleep cycle repeats 1000 times per second. Even if each wake cycle consumes only 10 uJ, the tick-related overhead amounts to 10 mJ/s or 10 mW of continuous power drain. In a device targeting 10 uA average current at 3.3V (33 uW), this represents a 300x increase in power consumption—clearly unacceptable for battery longevity.
Consider a typical battery-powered sensor node that wakes once per second to take a measurement, transmit data, then return to sleep. The application requires no timing precision finer than 10ms for its operation. Yet if configured with the default 1000Hz tick rate, the CPU experiences 1000 wake-ups per second solely for tick processing, despite having no actual work to do 99% of the time.
This scenario illustrates the core problem: the tick rate often exceeds the application’s actual timing requirements, creating unnecessary power waste without providing functional benefit.
The root cause typically stems from two factors:
To determine whether your tick rate is excessive, ask:
For many applications—periodic sensor readings, user interface updates, communication polling, or control loops with 100ms+ periods—the answer is no. These systems can often operate correctly with tick rates of 100Hz or even lower.
Reducing the FreeRTOS tick rate involves a four-step process:
Begin by identifying all time-dependent operations in your firmware:
vTaskDelay())Record the shortest interval required across all these operations. For example:
In this case, the shortest genuine requirement is 20ms (for debouncing), suggesting a minimum tick rate of 50Hz (1 / 0.020s = 50Hz) to maintain 20ms resolution.
Choose a tick rate that provides adequate resolution for your shortest requirement while allowing margin for error. A common approach is to select the next standard rate above your calculated minimum:
Standard tick rates to consider: 50Hz, 100Hz, 200Hz, 250Hz, 500Hz, 1000Hz.
Modify FreeRTOSConfig.h with two critical changes:
/* Reduce tick rate to 100Hz (10ms ticks) */#define configTICK_RATE_HZ ( ( TickType_t ) 100 )/* Enable tickless idle to suppress ticks during idle periods */#define configUSE_TICKLESS_IDLE 1
The configUSE_TICKLESS_IDLE setting allows FreeRTOS to enter tickless idle mode when no tasks are ready to run. Rather than continuing periodic tick interrupts, the kernel calculates the time until the next scheduled timeout, programs a one-shot timer for that duration, and enters a low-power state. The CPU wakes only when:
By default, FreeRTOS requires that the expected idle duration equals or exceeds configEXPECTED_IDLE_TIME_BEFORE_SLEEP (which defaults to 2 ticks, or 20ms at 100Hz) before entering tickless sleep. At lower tick rates, ensure this threshold aligns with your application’s sleep window.
This combination—reduced base tick rate plus tickless idle—yields multiplicative power savings compared to simply lowering the tick rate alone.
All timeout values specified in ticks must be adjusted proportionally when changing configTICK_RATE_HZ. If legacy code hardcoded tick counts assuming a 1ms tick:
vTaskDelay(1000) originally waited 1000ms at 1000Hz, but at 100Hz it will block for 10 seconds (10,000ms).vTaskDelay(1000 / portTICK_PERIOD_MS) functions when configTICK_RATE_HZ divides evenly into 1000, but introduces integer rounding truncation errors at non-divisor rates (e.g., at 300Hz).The robust standard is to use the pdMS_TO_TICKS() macro, which correctly scales milliseconds to ticks using 64-bit intermediate arithmetic to prevent integer truncation:
vTaskDelay(pdMS_TO_TICKS(1000)); // 1-second delay at any configured tick rate
After configuration changes, validate that:
To illustrate the impact, consider a typical 32-bit microcontroller running at 3.3V with the following characteristics:
At 1000Hz tick rate:
1000 * 5us = 5ms5ms / 1000ms = 0.005(5mA * 0.005) + (5uA * 0.995) ~= 30uA30uA * 3.3V ~= 99uWAt 100Hz tick rate with tickless idle:
100 * 0.10 = 10 ticks10 * 5us = 50us50us / 1000ms = 0.00005(5mA * 0.00005) + (5uA * 0.99995) ~= 5.25uA5.25uA * 3.3V ~= 17.3uWPower reduction: ~83% from tick-related overhead alone.
In systems with deeper sleep modes or longer idle periods, savings can exceed 90% of the tick-related power component. For a device targeting 10 uA average current, reducing tick-related wake-ups might extend battery life by weeks or months depending on battery capacity and duty cycle.
Here’s a concrete example using an STM32L4 microcontroller running FreeRTOS:
#define configTICK_RATE_HZ ( ( TickType_t ) 100 )#define configUSE_TICKLESS_IDLE 1#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
configUSE_PORT_OPTIMISED_TASK_SELECTION leverages hardware CLZ (Count Leading Zeros) assembly instructions on Cortex-M4 to determine the highest-priority ready task in O(1) constant time, minimizing active execution cycles during scheduler wake-ups.
Ensure low-power modes are correctly configured in STM32CubeMX or HAL:
portSUPPRESS_TICKS_AND_SLEEP(xExpectedIdleTime) calls vPortSuppressTicksAndSleep() during RTOS idle periodsUse an oscilloscope or current probe to measure:
Quick Links
Legal Stuff





