casaroli opened a new pull request, #19530:
URL: https://github.com/apache/nuttx/pull/19530

   ## Summary
   
   The RP2350 has two independent system timer blocks (TIMER0, TIMER1), each a
   free-running 64-bit microsecond counter clocked by the TICKS block (1 MHz) 
and
   independent of the ARM SysTick that drives the OS tick. Each block has four
   independent alarms (ALARM0–3), each with its own compare register and IRQ.
   The port had no driver for these blocks. This PR adds two features built on
   them and makes them share the hardware cleanly.
   
   **1. `/dev/timer` driver (`rp23xx_timer.c`)**
   
   - A standard NuttX timer lower-half bound to a block; uses ALARM0 (matches 
the
     low 32 bits of the counter) for single-shot or periodic timeouts, 1 µs
     resolution, up to 2³²−1 µs (~71.5 min) per interval.
   - Periodic reloads are scheduled relative to the previous expiry (no drift),
     never behind the counter (a past alarm would not match until the 32-bit
     counter wraps).
   - Enabled with `CONFIG_RP23XX_TIMER`; each block is toggled independently:
     `CONFIG_RP23XX_TIMER0` → `/dev/timer0`, `CONFIG_RP23XX_TIMER1` → 
`/dev/timer1`.
   
   **2. Tickless OS (`rp23xx_oneshot.c`)**
   
   - An `ONESHOT_COUNT` alarm/oneshot lower-half (mirrors
     `arch/risc-v/src/common/riscv_mtimer.c`) that drives the tickless scheduler
     through `up_alarm_set_lowerhalf()`. The 64-bit counter is the monotonic 
time
     base (`current()`); ALARM0 is the next-event compare.
   - The one adaptation vs. a full 64-bit-compare timer: the ALARM registers 
match
     only the low 32 bits of the counter. `max_delay()` is capped below 2³² 
counts
     so the scheduler never asks for a longer interval, and any deadline already
     due — or reached while the alarm is being armed — is forced immediately via
     the INTF register instead of waiting a full 32-bit wrap.
   - Enabled with `CONFIG_RP23XX_SYSTIMER_TICKLESS` (mutually exclusive with
     `CONFIG_RP23XX_SYSTIMER_SYSTICK`); the block is selectable with
     `CONFIG_RP23XX_SYSTIMER_TICKLESS_TIMER0` (default) / `_TIMER1`.
     `ARCH_CHIP_RP23XX` now selects `ARCH_HAVE_TICKLESS`.
   
   **Coexistence.** The block chosen for tickless is claimed exclusively by the
   scheduler and is removed from the `/dev/timer` choices in Kconfig
   (`RP23XX_TIMER0 depends on !RP23XX_SYSTIMER_TICKLESS_TIMER0`, and likewise 
for
   TIMER1), so the two features never collide on the same block or its alarm 
IRQ.
   Result:
   
   - tickless disabled → both `/dev/timer0` and `/dev/timer1` available;
   - tickless on TIMER0 → scheduler owns TIMER0, `/dev/timer1` available;
   - tickless on TIMER1 → scheduler owns TIMER1, `/dev/timer0` available.
   
   ## Impact
   
   - New feature, opt-in; no change to existing behavior when both options are
     disabled. Default OS tick remains the ARM SysTick.
   - Arch: `arm` (rp23xx / RP2350). Boards: rp23xx common bringup registers the
     enabled `/dev/timerN` device(s).
   - No new external dependencies. No ABI/API changes outside the new Kconfig
     symbols and the new `/dev/timerN` device nodes.
   
   ## Testing
   
   **Hardware:** RP2350 board (Pimoroni Pico Plus 2), `raspberrypi-pico-2:nsh`
   configuration, programmed over SWD with a Raspberry Pi Debug Probe (probe-rs)
   and driven from the `nsh` console on UART0 through the same probe's UART
   bridge. Both timer blocks were exercised in **both roles**, and in each build
   the two features ran **at the same time** on different blocks.
   
   ### Configuration A — tickless on TIMER0, `/dev/timer1` on TIMER1
   
   `RP23XX_SYSTIMER_TICKLESS` + `SYSTIMER_TICKLESS_TIMER0` + `SCHED_TICKLESS` +
   `SCHED_TICKLESS_ALARM` + `RP23XX_TIMER` + `RP23XX_TIMER1` + `EXAMPLES_TIMER`
   with `CONFIG_EXAMPLES_TIMER_DEVNAME="/dev/timer1"`.
   
   - Boots to `nsh`.
   - **Kconfig exclusion confirmed at runtime:** `ls /dev` lists `timer1` and
     **not** `timer0` — the block the scheduler claimed is not offered as a
     `/dev/timer` device.
   - **`examples/timer` on `/dev/timer1` runs while tickless drives the 
scheduler
     from TIMER0** — this is the coexistence proof. `timeleft` counts down
     smoothly within each 1 s interval and `nsignals` increments 0 → 1 → 2 as 
the
     ALARM0 matches are delivered to the user signal handler; the app stops the
     timer and exits cleanly.
   - **Timed wakeups** (`sleep N`, measured by when the prompt returns):
     1 s → +0.014 s, 2 s → +0.061 s, 4 s → +0.053 s, 8 s → +0.063 s.
   - **Clock rate:** board `uptime` advanced **123 s while the host wall clock
     advanced 123.04 s** — −0.034 % over two minutes, within `uptime`'s 1 s
     display quantization.
   
   ### Configuration B — tickless on TIMER1, `/dev/timer0` on TIMER0
   
   The mirror image of A (`SYSTIMER_TICKLESS_TIMER1` + `RP23XX_TIMER0`,
   `CONFIG_EXAMPLES_TIMER_DEVNAME="/dev/timer0"`), which exercises the 
block-select
   path for both features.
   
   - Boots to `nsh`; `ls /dev` lists `timer0` and **not** `timer1`.
   - `examples/timer` on `/dev/timer0` runs to completion with `nsignals`
     incrementing, while tickless runs on TIMER1.
   - **Timed wakeups:** 1 s → +0.055 s, 2 s → +0.043 s, 4 s → +0.059 s,
     8 s → +0.061 s.
   - **Clock rate:** `uptime` +123 s vs 123.02 s wall — −0.016 % over two 
minutes.
   
   The residual tens of milliseconds on `sleep` are shell/scheduler round-trip
   overhead, not clock drift: the two-minute rate measurements bound the drift 
at
   well under 0.05 %.
   
   ### Build / config matrix (all clean)
   
   | Configuration | Result |
   |---|---|
   | `RP23XX_TIMER` + `RP23XX_TIMER0` + `RP23XX_TIMER1` + `EXAMPLES_TIMER` | 
builds & links |
   | tickless on TIMER0 + `/dev/timer1` (config A above) | builds, links, 
**HW-tested** |
   | tickless on TIMER1 + `/dev/timer0` (config B above) | builds, links, 
**HW-tested** |
   
   - `tools/checkpatch.sh -f` (nxstyle) and `-g` (patches + commit messages):
     clean on both commits.
   - No Kconfig warnings; the forward references between the two features 
degrade
     to `n` when only one is present.
   
   ### Note on the console used
   
   Testing used the UART0 console rather than `usbnsh`. On this board the 
USB-CDC
   console drops after a couple of commands; that is **independent of this PR** 
—
   a pristine `raspberrypi-pico-2:usbnsh` build with none of these options 
enabled
   was flashed as a control and behaved identically, which matches the existing
   entry in the rp23xx documentation ("USB — Experimental — usbnsh configuration
   is somewhat working with some data corruption"). Nothing in this PR touches 
the
   USB device driver.
   


-- 
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]

Reply via email to