rp23xx: Add /dev/timer driver on the TIMER0/TIMER1 blocks.

The RP2350 has two system timer blocks (TIMER0, TIMER1), each a free-running
64-bit counter incremented once per microsecond by the TICKS block (set up in
rp23xx_clock.c).  They are independent of the ARM SysTick that drives the OS
tick, so they are free for application use, but the port had no driver for
them.

Add rp23xx_timer.c, a NuttX timer lower-half that binds a block to a
/dev/timerN device.  It uses ALARM0 of the block, which matches the low 32
bits of the microsecond counter, to implement single-shot and periodic
timeouts with 1 us resolution and a maximum interval of 2^32 - 1 us (~71.5
minutes).  Periodic reloads are scheduled relative to the previous expiry to
avoid drift, but never behind the counter (an alarm set in the past would not
match until the 32-bit counter wraps).

Enable with CONFIG_RP23XX_TIMER (which selects CONFIG_TIMER), then turn on each
block independently: CONFIG_RP23XX_TIMER0 registers /dev/timer0 and
CONFIG_RP23XX_TIMER1 registers /dev/timer1.  A block claimed by the tickless
oneshot (CONFIG_RP23XX_SYSTIMER_TICKLESS) is excluded from these choices in
Kconfig, so the two features can be enabled together without colliding on the
same block or its alarm IRQ.

Tested on Pimoroni Pico Plus 2 (RP2350B) hardware with examples/timer and a
CMSIS-DAP probe.  The device registers as /dev/timer0; the ALARM0 interrupt
fires at the programmed period (verified over SWD at the configured 1 s
interval, not a busy loop), and the full path -- alarm match, the driver ISR,
the timer notification and delivery of the SIGNO to user space -- reaches the
example's signal handler and increments its counter.

Assisted-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
This commit is contained in:
Marco Casaroli 2026-07-25 02:24:12 +02:00 committed by Alan C. Assis
parent 7eb6a3ca59
commit b00d7005b0
7 changed files with 566 additions and 0 deletions

View file

@ -43,6 +43,7 @@ SRAM Boot Working Requires external SWD debugger
PSRAM Working Three modes of heap allocation described below
TRNG Working Hardware RNG at /dev/random and /dev/urandom
Flash MTD Working Unused flash tail as an MTD device, answers BIOC_XIPBASE
Timer Working /dev/timerN on TIMER0/TIMER1, 1 us resolution
============== ============ =====
Installation
@ -171,6 +172,29 @@ external PSRAM is configured as a separate user heap called
`psram` and can be used through the global variable
`g_psramheap` after including `rp23xx_heaps.h`
Timer
=====
The RP2350 has two system timer blocks, TIMER0 and TIMER1, each a
free-running 64-bit counter incremented once per microsecond. They are
independent of the ARM SysTick that drives the OS tick, so they are
available for application timers.
Enable the driver with `RP23XX_TIMER` (which selects `TIMER`), then turn on
each block you want: `RP23XX_TIMER0` registers `/dev/timer0` (TIMER0) and
`RP23XX_TIMER1` registers `/dev/timer1` (TIMER1). Each device implements the
standard NuttX timer lower-half: single-shot or periodic timeouts with 1 us
resolution and a maximum interval of 2^32 - 1 us (about 71.5 minutes), driven
by ALARM0 of the block.
A block claimed by the tickless-OS oneshot
(`RP23XX_SYSTIMER_TICKLESS`) is removed from the choices above, so a
`/dev/timer` device and the tickless OS time source never collide on the same
block -- you can run both at once (e.g. tickless on TIMER0, `/dev/timer1` on
TIMER1). With tickless disabled, both `/dev/timer0` and
`/dev/timer1` are available. The `examples/timer` application can exercise a
device; point `CONFIG_EXAMPLES_TIMER_DEVNAME` at the block you enabled.
Programming
============