daniel-p-carvalho opened a new pull request, #20173:
URL: https://github.com/apache/nuttx/pull/20173
## Summary
This PR addresses two critical timing bugs in the single-timer
capture/compare tickless OS drivers across STM32 families
(`stm32_tickless_m3m4_v1.c` for F1/F2/F3/F4/G4, `stm32f7`, `stm32h7`, and
`stm32wb`), along with wall time progression fixes for tickless timekeeping:
1. **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.
2. **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 past `count + period` during 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 via `EGR`, preventing any hang.
3. **`up_timer_cancel()` remaining time calculation:**
Fixes signed/unsigned casting and remaining time calculation when the
timer has already expired.
4. **Sched / Clock Timekeeping:**
- In `nxsched_process_timer()`, `clock_update_wall_time()` is now called
under `CONFIG_CLOCK_TIMEKEEPING`, ensuring monotonic progression of wall time
across tickless timer wakeups.
- In `clock_timekeeping_get_wall_time()`, `clock_update_wall_time()` is
called prior to sampling.
- Allows overriding `NTP_MAX_ADJUST` with
`CONFIG_CLOCK_ADJTIME_SLEWLIMIT_PPM`.
*Note on STM32L4/L5/U5:* STM32L4/L5/U5 utilizes a fundamentally different
two-timer tickless architecture (`stm32l4_tickless.c` with 1 oneshot timer in
pulse mode + 1 freerun timer). It does not use compare match and is
intentionally excluded from this PR.
## Impact
- **Bug fix:** Eliminates intermittent multi-minute / 71-minute deadlocks in
tickless OS mode on STM32 platforms when short sleeps or zero-delay timeouts
are scheduled.
- **Affected targets:** STM32F1, STM32F2, STM32F3, STM32F4, STM32F7,
STM32G4, STM32H7, STM32WB.
- **Compatibility:** Fully backward-compatible. No API breaks.
## 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):
1. **STM32H7 (STM32H743ZI / Custom IED Pextron R550):**
- Driver: `arch/arm/src/stm32h7/stm32_tickless.c`
- Config: `CONFIG_SCHED_TICKLESS=y`, 32-bit TIM2 at 1 MHz, Ethernet RMII
active.
- Results:
- Continuous ICMP ping during tickless idle sleeps: 0% packet loss, RTT
~0.6 ms.
- Accurate `sleep 1s`, `sleep 2s`, `sleep 5s` executions.
- Rapid `usleep` calls wake up immediately without deadlocks or missed
interrupts.
2. **STM32G4 (Nucleo-G431KB):**
- Driver: `arch/arm/src/common/stm32/stm32_tickless_m3m4_v1.c` (shared
core driver with F1/F2/F3/F4)
- Config: `nucleo-g431kb:nsh` with `CONFIG_SCHED_TICKLESS=y`, `TIM2` at 1
MHz (`CONFIG_USEC_PER_TICK=1`).
- Results:
- `sleep 1` wall-clock: 0.9989s
- `sleep 2` wall-clock: 1.9966s
- `sleep 3` wall-clock: 2.9931s
- `usleep 1000` wakes up immediately without hang.
### What was NOT tested on real hardware:
- **STM32F7 / STM32WB:** Drivers received the identical logic and build
cleanly, but physical F7/WB boards were not connected to bench during this test
session.
- **STM32F4 / F1 / F2 / F3:** Code executed is the exact same
`stm32_tickless_m3m4_v1.c` validated on STM32G4, but physical F4/F1/F2/F3
boards were not flashed.
- **STM32L4:** Tested on Nucleo-L432KC, confirmed that it uses a different
two-timer strategy (`stm32l4_tickless.c`) and is not part of this PR.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]