ProtoCore v0.0.1
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
clock.h File Reference

Pluggable monotonic clock for all library timing. More...

#include <Arduino.h>
#include <stdint.h>

Go to the source code of this file.

Classes

struct  pc_latency_stat
 Rolling latency statistics in microseconds: sample count, min / max / mean, and how many samples blew a budget. Fixed size, no heap; a subsystem (the preempting queue, a DMA path, a forwarding rule) keeps one and reports it for real-time visibility. More...
 

Typedefs

typedef uint32_t(* pc_clock_fn) (void)
 User clock: returns a free-running monotonic tick count.
 

Functions

pc_clock_fn_pc_clock_fn_ref ()
 
uint32_t & _pc_clock_div_ref ()
 
void pc_set_clock (pc_clock_fn fn, uint32_t ticks_per_second)
 Install a custom clock running at ticks_per_second; the library divides it down to its internal 1000 Hz. Pass (nullptr, 0) to revert to the platform default.
 
uint32_t pc_millis (void)
 The library's monotonic time at 1000 Hz (milliseconds).
 
void pcdelay (uint32_t ms)
 Block for at least ms milliseconds - the library's single delay primitive.
 
pc_clock_fn_pc_micros_fn_ref ()
 
uint32_t & _pc_micros_div_ref ()
 
void pc_set_micros_clock (pc_clock_fn fn, uint32_t ticks_per_second)
 Install a custom microsecond clock running at ticks_per_second; the library divides it down to 1 MHz. Pass (nullptr, 0) for the platform default.
 
uint32_t pc_micros (void)
 Monotonic microseconds - the high-resolution time base for ISR timestamps and sub-millisecond latency. Safe to call from an ISR. Wraps roughly every 71 minutes, so use it only for short deltas (unsigned subtraction is wrap-safe).
 
void pc_lat_reset (pc_latency_stat *s)
 Zero a stat (min seeded high so the first sample sets it).
 
uint32_t pc_lat_begin (void)
 Start of a measured span: capture the current microsecond time.
 
void pc_lat_end (pc_latency_stat *s, uint32_t start_us, uint32_t budget_us)
 End of a span started at start_us: record its latency, counting it as over-budget when budget_us is non-zero and exceeded. Wrap-safe.
 
uint32_t pc_lat_avg_us (const pc_latency_stat *s)
 Mean latency (us) over the recorded samples, 0 if none.
 
uint32_t pc_cycles (void)
 Free-running CPU cycle count. ISR-safe. On ARDUINO/ESP32 this is the hardware cycle counter (CCOUNT); on host it falls back to pc_micros() scaled by host_fallback_mhz (a coarse stand-in - override with a real cycle source in a host test that needs nanosecond precision).
 
uint32_t pc_cycles_to_ns (uint32_t delta_cycles, uint32_t cpu_mhz)
 Convert a cycle-count delta to nanoseconds at cpu_mhz (the running CPU frequency, e.g. getCpuFrequencyMhz() on ESP32). delta_cycles must come from a wrap-safe unsigned subtraction of two pc_cycles() reads.
 

Detailed Description

Pluggable monotonic clock for all library timing.

The library's internal timing runs at 1000 Hz - one tick is one millisecond, the cadence the test suite asserts and every timeout / poll is expressed in. pc_millis() is that single time source; by default it is the platform millis().

To drive the library from your own clock (a hardware timer, an external RTC, a simulation clock), call:

pc_set_clock(my_clock_fn, my_ticks_per_second);

Your clock reports a free-running tick count at ticks_per_second. The library divides it down to its internal 1000 Hz, so timeouts and polling keep the exact 1 ms granularity the tests verify regardless of how fast your clock runs. Pass a rate >= 1000, ideally a multiple of 1000 for exact division (e.g. a 1 MHz timer -> ticks_per_second = 1000000, divided by 1000). Pass nullptr to revert to the platform default. One source covers everything - swap it once and every subsystem follows.

The worker poll cadence is fixed at 1000 Hz (the tested default); a build can trade latency for idle power with PC_WORKER_POLL_TICKS - see protocore_config.h.

Header-only (the override state lives in inline-function-local statics, a single instance across the whole program), so there is nothing extra to compile or link.

Author
Douglas Quigg (dstroy0)
Date
2026

Definition in file clock.h.

Typedef Documentation

◆ pc_clock_fn

typedef uint32_t(* pc_clock_fn) (void)

User clock: returns a free-running monotonic tick count.

Definition at line 43 of file clock.h.

Function Documentation

◆ _pc_clock_fn_ref()

pc_clock_fn & _pc_clock_fn_ref ( )
inline

Definition at line 48 of file clock.h.

Referenced by pc_millis(), and pc_set_clock().

◆ _pc_clock_div_ref()

uint32_t & _pc_clock_div_ref ( )
inline

Definition at line 53 of file clock.h.

Referenced by pc_millis(), and pc_set_clock().

◆ pc_set_clock()

void pc_set_clock ( pc_clock_fn  fn,
uint32_t  ticks_per_second 
)
inline

Install a custom clock running at ticks_per_second; the library divides it down to its internal 1000 Hz. Pass (nullptr, 0) to revert to the platform default.

Definition at line 64 of file clock.h.

References _pc_clock_div_ref(), and _pc_clock_fn_ref().

◆ pc_millis()

◆ pcdelay()

void pcdelay ( uint32_t  ms)
inline

Block for at least ms milliseconds - the library's single delay primitive.

src/ never calls the platform delay() directly; every wait goes through this so timing stays centralized and portable. On device it yields to the RTOS one tick at a time until ms has elapsed on the monotonic clock (so it sleeps the task and feeds the watchdog, never starving the scheduler); on host it spins on the same clock. Measured against pc_millis, so a custom clock governs it too.

Definition at line 89 of file clock.h.

References pc_millis().

◆ _pc_micros_fn_ref()

pc_clock_fn & _pc_micros_fn_ref ( )
inline

Definition at line 120 of file clock.h.

Referenced by pc_micros(), and pc_set_micros_clock().

◆ _pc_micros_div_ref()

uint32_t & _pc_micros_div_ref ( )
inline

Definition at line 125 of file clock.h.

Referenced by pc_micros(), and pc_set_micros_clock().

◆ pc_set_micros_clock()

void pc_set_micros_clock ( pc_clock_fn  fn,
uint32_t  ticks_per_second 
)
inline

Install a custom microsecond clock running at ticks_per_second; the library divides it down to 1 MHz. Pass (nullptr, 0) for the platform default.

Definition at line 136 of file clock.h.

References _pc_micros_div_ref(), and _pc_micros_fn_ref().

◆ pc_micros()

uint32_t pc_micros ( void  )
inline

Monotonic microseconds - the high-resolution time base for ISR timestamps and sub-millisecond latency. Safe to call from an ISR. Wraps roughly every 71 minutes, so use it only for short deltas (unsigned subtraction is wrap-safe).

Definition at line 148 of file clock.h.

References _pc_micros_div_ref(), _pc_micros_fn_ref(), and pc_millis().

Referenced by pc_cycles(), pc_lat_begin(), and pc_lat_end().

◆ pc_lat_reset()

void pc_lat_reset ( pc_latency_stat s)
inline

Zero a stat (min seeded high so the first sample sets it).

Definition at line 182 of file clock.h.

References pc_latency_stat::count, pc_latency_stat::max_us, pc_latency_stat::min_us, pc_latency_stat::over_budget, and pc_latency_stat::sum_us.

◆ pc_lat_begin()

uint32_t pc_lat_begin ( void  )
inline

Start of a measured span: capture the current microsecond time.

Definition at line 192 of file clock.h.

References pc_micros().

◆ pc_lat_end()

void pc_lat_end ( pc_latency_stat s,
uint32_t  start_us,
uint32_t  budget_us 
)
inline

End of a span started at start_us: record its latency, counting it as over-budget when budget_us is non-zero and exceeded. Wrap-safe.

Definition at line 201 of file clock.h.

References pc_latency_stat::count, pc_latency_stat::max_us, pc_latency_stat::min_us, pc_latency_stat::over_budget, pc_micros(), and pc_latency_stat::sum_us.

◆ pc_lat_avg_us()

uint32_t pc_lat_avg_us ( const pc_latency_stat s)
inline

Mean latency (us) over the recorded samples, 0 if none.

Definition at line 221 of file clock.h.

References pc_latency_stat::count, and pc_latency_stat::sum_us.

◆ pc_cycles()

uint32_t pc_cycles ( void  )
inline

Free-running CPU cycle count. ISR-safe. On ARDUINO/ESP32 this is the hardware cycle counter (CCOUNT); on host it falls back to pc_micros() scaled by host_fallback_mhz (a coarse stand-in - override with a real cycle source in a host test that needs nanosecond precision).

Definition at line 248 of file clock.h.

References pc_micros().

◆ pc_cycles_to_ns()

uint32_t pc_cycles_to_ns ( uint32_t  delta_cycles,
uint32_t  cpu_mhz 
)
inline

Convert a cycle-count delta to nanoseconds at cpu_mhz (the running CPU frequency, e.g. getCpuFrequencyMhz() on ESP32). delta_cycles must come from a wrap-safe unsigned subtraction of two pc_cycles() reads.

Definition at line 263 of file clock.h.