configUSE_TICKLESS_IDLE
embedded
runtime_error
ai_generated
true
FreeRTOS: tickless idle mode missed Systick interrupt, system clock drift detected
ID: embedded/rtos-tickless-idle-systick-missed
75%Fix Rate
83%Confidence
1Evidence
2024-01-10First Seen
Root Cause
In tickless idle mode, the MCU enters a deep sleep state and the Systick timer is stopped; if the wake-up source (e.g., RTC or external interrupt) triggers too late or the sleep exit time is longer than expected, the next Systick interrupt is missed, causing the system tick count to drift.
generic中文
在无滴答空闲模式下,MCU进入深度睡眠状态且系统滴答定时器停止;若唤醒源(如RTC或外部中断)触发过晚或退出睡眠时间超出预期,则下一个系统滴答中断被错过,导致系统滴答计数漂移。
Official Documentation
https://www.freertos.org/Documentation/RTOS_book.htmlWorkarounds
-
80% success Implement a correction algorithm in the portSUPPRESS_TICKS_AND_SLEEP() macro. Example: #define portSUPPRESS_TICKS_AND_SLEEP(xExpectedIdleTime) \ do { \ uint32_t ulSysTickCount = SysTick->VAL; \ if (xExpectedIdleTime > 100) { \ // Enter sleep with RTC wake-up \ HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, xExpectedIdleTime - 1, RTC_WAKEUPCLOCK_RTCCLK_DIV16); \ __WFI(); \ // Recalculate missed ticks \ xExpectedIdleTime = (xExpectedIdleTime - (ulSysTickCount - SysTick->VAL) / (SystemCoreClock / 1000)); \ } \ } while(0)
Implement a correction algorithm in the portSUPPRESS_TICKS_AND_SLEEP() macro. Example: #define portSUPPRESS_TICKS_AND_SLEEP(xExpectedIdleTime) \ do { \ uint32_t ulSysTickCount = SysTick->VAL; \ if (xExpectedIdleTime > 100) { \ // Enter sleep with RTC wake-up \ HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, xExpectedIdleTime - 1, RTC_WAKEUPCLOCK_RTCCLK_DIV16); \ __WFI(); \ // Recalculate missed ticks \ xExpectedIdleTime = (xExpectedIdleTime - (ulSysTickCount - SysTick->VAL) / (SystemCoreClock / 1000)); \ } \ } while(0) -
85% success Use a dedicated low-power timer (LPTIM) as the wake-up source instead of the RTC, which provides finer granularity and reduces drift.
Use a dedicated low-power timer (LPTIM) as the wake-up source instead of the RTC, which provides finer granularity and reduces drift.
中文步骤
Implement a correction algorithm in the portSUPPRESS_TICKS_AND_SLEEP() macro. Example: #define portSUPPRESS_TICKS_AND_SLEEP(xExpectedIdleTime) \ do { \ uint32_t ulSysTickCount = SysTick->VAL; \ if (xExpectedIdleTime > 100) { \ // Enter sleep with RTC wake-up \ HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, xExpectedIdleTime - 1, RTC_WAKEUPCLOCK_RTCCLK_DIV16); \ __WFI(); \ // Recalculate missed ticks \ xExpectedIdleTime = (xExpectedIdleTime - (ulSysTickCount - SysTick->VAL) / (SystemCoreClock / 1000)); \ } \ } while(0)Use a dedicated low-power timer (LPTIM) as the wake-up source instead of the RTC, which provides finer granularity and reduces drift.
Dead Ends
Common approaches that don't work:
-
50% fail
Disabling tickless idle entirely (configUSE_TICKLESS_IDLE = 0) increases power consumption but does not fix the underlying issue of Systick wake-up timing.
-
80% fail
Increasing the Systick interrupt priority does not prevent the miss because the issue is timing, not priority inversion.