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:
- the peripheral raising it –
arm_after_us/set_deadlineprogram the comparator and enable the timer; - the source routed to this core –
route_irq; - 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§
- Generic
Timer - The per-core ARM generic (architected) timer, driving the non-secure
physical timer (
CNTP).