kernel::clock
A monotonic microsecond clock.
The scheduler tick is milliseconds and is the wrong instrument for two
jobs: measuring something shorter than a tick, and answering a caller that
wants absolute time rather than a count of scheduling periods. Espressif’s
radio blobs want the second — esp_timer_get_time is one of the entries in
wifi_osi_funcs_t and the blob calls it constantly.
The kernel reads the clock through [hal::clock::MonotonicClock], selecting
one implementation with the SoC. A SoC with a spare hardware counter — the
ESP32’s is TIMG1/T1 (below), the RP2040’s is its free-running 1 MHz timer —
implements it; one without takes the trait default, and [now_us] falls
back to the scaled scheduler tick. So callers — syscall, the self-tests,
the radio adapter — name no chip.
Why the ESP32 implementation lives here, not in soc-esp32
Section titled “Why the ESP32 implementation lives here, not in soc-esp32”It is built on esp32-timg, a Layer-1 driver, and soc-esp32 is Layer 0 —
it may not depend on a driver. The kernel may, so the implementation is a
kernel-local type behind the portable trait rather than a chip name in the
kernel’s neutral code. radio/* still cannot reach TIMG (it may not name
drivers/physical/*), which is why a clock is a kernel service at all.
Sixty-four bits, and no wrap
Section titled “Sixty-four bits, and no wrap”The counter is 64 bits at 1 MHz, so it wraps after about 584,000 years. There is deliberately no wrap handling: code that reads a 32-bit counter and compensates is code with a bug waiting for the boundary, and here the boundary does not exist.
Structs
Section titled “Structs”struct Clock;The kernel’s monotonic clock, selected by SoC.
A kernel-local type so the kernel may implement the hal trait for it — the
esp32-timg the ESP32 body needs is a driver neither hal nor soc-esp32
may depend on (see the module header).
Implements: MonotonicClock
Functions
Section titled “Functions”unsafe fn init() -> boolClaim and start the monotonic clock. See [MonotonicClock::init].
Safety
Section titled “Safety”Takes exclusive ownership of the SoC’s monotonic timer.
now_us
Section titled “now_us”fn now_us() -> u64Microseconds since [init].
Monotonic: it counts up and never goes back, including across a task switch
on either core. On a SoC with a hardware microsecond counter this is that
counter (zero before init); on one without, it is the scheduler tick
scaled to microseconds — monotonic and correctly ordered, but a thousand
times coarser, so callers may check ordering and must not check resolution.