FreeRTOS Tick/Tickless via LPTIM
Use LPTIM for the FreeRTOS tick instead of the SysTick Timer for ultra-low-power applications.
- No drift or slippage in kernel time
- Use STOP modes even while FreeRTOS timers are running or delays are underway
- For any STM32 with LPTIM (STM32L, STM32F, STM32G, STM32H, STM32U, STM32W)
This repository demonstrates integration and testing of the lptimTick.c gist on Nucleo-L476RG (STM32L476). The project uses STM32CubeIDE and its integrated code-generation tool (STM32CubeMX). However, lptimTick.c is compatible with any toolchain supported by FreeRTOS.
A separate repository, LPTIM-Tick-U5, is adapted to the STM32U family.
For a thorough evaluation, this project can be built without tickless idle, with the default tickless idle, or with the custom tickless idle provided by lptimTick.c. See branches for additional evaluation options.
Press the blue button to cycle between tests:
- Maintain kernel time only. LED blinks every 5 seconds.
- Validate tick timing. LED blinks every 2 seconds.
- Stress test tick timing. LED blinks every second.
Tests 2 and 3 display live test results to a serial terminal. Connect to the STLink Virtual COM Port at 115200 8N1. Additionally, the LED blinks twice (instead of just once) in case of test failure.
Current readings shown are averages, not including the LED
With lptimTick.c (configUSE_TICKLESS_IDLE 2
)
- Test 1: 2μA, no drift
- Test 2: 55μA, no drift
- Test 3: 110μA, no drift
Default tickless idle (configUSE_TICKLESS_IDLE 1
)
- Test 1: 3.70mA, trivial drift
- Test 2: 3.72mA, trivial drift
- Test 3: 3.74mA, trivial drift (with kernel v10.5.1 or newer)
Tickless disabled (configUSE_TICKLESS_IDLE 0
)
- Test 1: 9.86mA, no drift
- Test 2: 9.86mA, no drift
- Test 3: 9.86mA, no drift
- Add lptimTick.c to your project folder, configuration, and/or makefile.
- In FreeRTOSConfig.h, define
configUSE_TICKLESS_IDLE
to2
, and eliminate the preprocessor definition forxPortSysTickHandler
. If using LSI instead of LSE, defineconfigTICK_USES_LSI
andconfigLPTIM_REF_CLOCK_HZ
(typically32000
or37000
), too. - Update the #include for your MCU.
- Update the LPTIM instance selection. (For STM32WL users, here too.) LPTIM1 is the default.
- Update the initialization code that is specific to both the MCU family and the LPTIM instance.
- You must ensure that no combination of your application's interrupt handlers and your code in
configPOST_SLEEP_PROCESSING()
can delay the tick ISR more than one tick period. To help your application meet this requirement, consider settingconfigTICK_INTERRUPT_PRIORITY
toconfigLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY
, and make sure to implementconfigPOST_SLEEP_PROCESSING()
so it executes quickly. See vUlpPostSleepProcessing() for an example.