Skip to main content

Module generic_timer

Module generic_timer 

Source
Available on neither armv6 nor crate feature bcm2712.
Expand description

Per-core ARM generic (architected) timer: monotonic counter, blocking delays, and interrupt-driven deadlines.

Not built for ARMv6 (BCM2835): the generic timer is an ARMv7-A extension, and the per-core control and routing registers this driver programs live in an ARM-local peripheral block the BCM2835 does not have. timer — the BCM System Timer, a peripheral rather than CPU state — is the monotonic clock there.

Not built for BCM2712 yet either: the counter itself is CPU state, but the per-core control registers this driver programs sit in the BCM2836’s ARM-local block, which the BCM2712 does not have. Per-core ARM generic timer – the architected timer built into the Cortex-A7 (BCM2836) and Cortex-A53 (BCM2837) – and the interrupt-driven deadline scheduling it provides.

Unlike the BCM System Timer (crate::timer), which is a single memory-mapped counter shared by all cores and the GPU firmware, the generic timer is per-core CPU state, read and armed through system registers (CP15 coprocessor registers on AArch32, the CNT*_EL0 registers on AArch64) rather than MMIO. Each core has its own comparator and its own timer interrupt, so each core can schedule and take its own tick independently – which is what an interrupt-driven executor (e.g. Embassy) needs and what the polling-only, single- comparator System Timer path can’t give per core.

This drives the physical timer (CNTP), the one accessible from the non-secure PL1/EL1 state rt’s boot code leaves the core in (boot.s drops HYP->SVC, boot64.s drops EL2->EL1, both non-secure). Its interrupt is the non-secure physical timer IRQ (CNTPNSIRQ), routed to the calling core through the BCM2836/2837 ARM-local interrupt controller – the per-core controller that the legacy crate::lic is explicitly not (see that module’s doc comment). Routing lives on GenericTimer::route_irq here rather than in a separate controller type: the generic timer is (today) the only user of that controller this crate wraps, and its routing is inherently per-core, so folding it in avoids a half-built shared abstraction the crate doesn’t yet need.

Three independent gates all have to be open for a tick to fire, the same shape as the System Timer path:

  1. the peripheral raising it – arm_after_us / set_deadline program the comparator and enable the timer;
  2. the source routed to this core – route_irq;
  3. the CPU-level IRQ mask open – crate::irq::enable_irq.

The counter is already free-running from boot at the firmware- programmed rate reported by GenericTimer::frequency (19.2 MHz on this hardware), so – like the System Timer – it needs no clock setup; this deliberately does not touch the ARM-local control/prescaler registers and relies on the firmware’s default counter configuration.

Structs§

GenericTimer
The per-core ARM generic (architected) timer, driving the non-secure physical timer (CNTP).