arch/arm/stm32 and sched/clock: fix tickless timer compare-match race, zero-period hang, and timekeeping updates - #20173
Merged
xiaoxiang781216 merged 2 commits intoSep 18, 2026
Conversation
This patch addresses two issues in the single-timer capture/compare tickless OS drivers for STM32 families (common m3m4 v1 for F1/F2/F3/F4/G4, F7, H7, and WB): 1. Zero-period handling: when up_timer_start() is called with a zero or negative duration (or period converts to 0 ticks), the driver now enables the compare match interrupt and immediately fires an event via EGR (CCxG), avoiding missed events or unexpected counter behavior. 2. Compare-match race condition: after programming CCR and enabling the compare interrupt, a post-check validates whether the free-running counter already reached or passed count + period during register configuration. If elapsed, the interrupt is forced immediately via EGR, preventing the counter from missing the match and hanging until a full 32-bit rollover (approx. 71 minutes at 1 MHz). Verified on real hardware: - STM32H743ZI (IED R550): validated with ping, sleep, and usleep. - STM32G431KB (Nucleo-G431KB): validated with uptime, sleep, and usleep. Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
… PPM 1. nxsched_process_timer: call clock_update_wall_time() under CONFIG_CLOCK_TIMEKEEPING so that wall time is updated on timer events during tickless operation. 2. clock_timekeeping_get_wall_time: call clock_update_wall_time() before sampling the base and counter. 3. clock_timekeeping: allow overriding NTP_MAX_ADJUST with CONFIG_CLOCK_ADJTIME_SLEWLIMIT_PPM if configured. 4. Use clock_t consistently for counter values in clock_timekeeping.c. Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
daniel-p-carvalho
requested review from
antmerlino,
gustavonihei,
jerpelea and
xiaoxiang781216
as code owners
September 17, 2026 12:43
xiaoxiang781216
approved these changes
Sep 17, 2026
hartmannathan
approved these changes
Sep 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR addresses two critical timing bugs in the single-timer capture/compare tickless OS drivers across STM32 families (
stm32_tickless_m3m4_v1.cfor F1/F2/F3/F4/G4,stm32f7,stm32h7, andstm32wb), along with wall time progression fixes for tickless timekeeping:Zero-period handling:
When
up_timer_start()is invoked with a zero/negative duration (or when converted delay equals 0 ticks), the driver now enables the compare match interrupt and immediately forces a hardware event via the Event Generation Register (EGR_CCxG). Previously, zero period could lead to missed events, improper compare programming, or undefined timeout behavior.Compare-match race condition (elimination of ~71-minute hang):
In the single-timer continuous free-running architecture (32-bit counter, 0 to
0xFFFFFFFF), interval timing relies on setting the capture/compare register (CCR = count + period) and waiting for the counter to match. If the counter reaches or advances pastcount + periodduring register programming or critical section entry, the compare match event is missed, causing the CPU to hang until the 32-bit counter wraps all the way around (4,294,967,295 ticks, which corresponds to ~71.5 minutes at 1 MHz).A post-configuration check is introduced to verify whether
(counter - count) >= period. If the target timestamp already elapsed, the compare interrupt is triggered immediately viaEGR, preventing any hang.up_timer_cancel()remaining time calculation:Fixes signed/unsigned casting and remaining time calculation when the timer has already expired.
Sched / Clock Timekeeping:
nxsched_process_timer(),clock_update_wall_time()is now called underCONFIG_CLOCK_TIMEKEEPING, ensuring monotonic progression of wall time across tickless timer wakeups.clock_timekeeping_get_wall_time(),clock_update_wall_time()is called prior to sampling.NTP_MAX_ADJUSTwithCONFIG_CLOCK_ADJTIME_SLEWLIMIT_PPM.Note on STM32L4/L5/U5: STM32L4/L5/U5 utilizes a fundamentally different two-timer tickless architecture (
stm32l4_tickless.cwith 1 oneshot timer in pulse mode + 1 freerun timer). It does not use compare match and is intentionally excluded from this PR.Impact
Testing
Host machine: Linux x86_64, arm-none-eabi-gcc 13.3.1.
All patches verified with
./tools/checkpatch.sh(zero errors, zero warnings).Hardware tested (validated in bench):
STM32H7 (STM32H743BI / Custom board):
arch/arm/src/stm32h7/stm32_tickless.cCONFIG_SCHED_TICKLESS=y, 32-bit TIM2 at 1 MHz, Ethernet RMII active.sleep 1s,sleep 2s,sleep 5sexecutions.usleepcalls wake up immediately without deadlocks or missed interrupts.STM32G4 (Nucleo-G431KB):
arch/arm/src/common/stm32/stm32_tickless_m3m4_v1.c(shared core driver with F1/F2/F3/F4)nucleo-g431kb:nshwithCONFIG_SCHED_TICKLESS=y,TIM2at 1 MHz (CONFIG_USEC_PER_TICK=1).sleep 1wall-clock: 0.9989ssleep 2wall-clock: 1.9966ssleep 3wall-clock: 2.9931susleep 1000wakes up immediately without hang.What was NOT tested on real hardware:
stm32_tickless_m3m4_v1.cvalidated on STM32G4, but physical F4/F1/F2/F3 boards were not flashed.stm32l4_tickless.c) and is not part of this PR.