Precision Timing
The precision timing subsystem provides a small set of reusable mechanisms for
PTP, gPTP, and other users that control high-resolution clocks. Enable it with
CONFIG_PRECISION_TIMING.
Note
The API is at experimental maturity and may still change. A protocol does not change maturity by using this subsystem.
The subsystem deliberately does not implement synchronization policy. PTP and gPTP continue to own their protocol state machines, clock selection, step thresholds, sample acceptance, lock detection, source-loss handling, and diagnostics.
Precision time
precision_time_t is a signed 64-bit nanosecond value. Checked
addition and subtraction helpers report overflow. The type does not identify a
time domain or timescale; modelling TAI, UTC, PHCs, monotonic time, and protocol
relationships is outside this API.
Precision clock
precision_clock dispatches four mandatory clock operations:
read the current time;
set an absolute time;
apply a phase adjustment; and
set a rate offset from the nominal frequency as parts per million with a 16-bit binary fractional field.
All operations must be implemented by a clock adapter. Adjustment ranges and other hardware constraints remain the responsibility of the underlying clock implementation.
precision_clock_ptp_adapter exposes an existing Zephyr PTP clock
device through this interface. It performs the required conversion between
net_ptp_time and precision_time_t; it does not add
capability discovery or synchronization state.
PI controller
precision_pi is an instance-based proportional-integral controller.
Each instance stores its own gains, limits and integral term.
precision_pi_update_interval() takes an error sample and the interval
since the previous sample; the update is equivalent to:
integral = clamp(integral + (ki / interval) * error, integral_limit);
output = clamp((kp / interval) * error + integral, output_limit);
The gains are given for an interval of 1. When the plant integrates the output
over the interval, as a clock does with a rate correction, the loop gain per
sample is then the same for any interval. precision_pi_update() is the
same update with an interval of 1.
precision_pi_set_limits() sets the two limits; a limit of 0 disables it,
which is the state after precision_pi_init(). While the output is at its
limit, the integral term keeps its value instead of moving further towards the
limit, so it does not wind up.
The controller does not decide whether an error should be stepped, rejected, or used for rate adjustment. It also does not track synchronization, acquisition, lock, holdover, source timeout, or clock faults. Callers own those decisions and reset the accumulated integral term when their policy requires it.
The PTP and gPTP integrations initialize their controllers from
CONFIG_PRECISION_TIMING_PI_KP and
CONFIG_PRECISION_TIMING_PI_KI, with the limits from
CONFIG_PRECISION_TIMING_PI_INTEGRAL_LIMIT_PPM and
CONFIG_PRECISION_TIMING_PI_OUTPUT_LIMIT_PPM. The integer gain
values express the gains in thousandths. Direct users of
precision_pi_init() may provide different gains for each controller
instance.
The PTP servo scales its gains by the time since its previous update when
CONFIG_PTP_SERVO_SCALE_GAINS_BY_SYNC_INTERVAL is enabled.
CONFIG_PTP_SERVO_STEP_THRESHOLD_MS and
CONFIG_PTP_SERVO_OUTLIER_THRESHOLD_MS set the offsets above
which the PTP servo steps the clock and, while locked, rejects a sample. Before
the servo locks, it also steps offsets above a fixed 100 ms.
Protocol integration
PTP and the gPTP default clock-update path each keep their existing policy and
use a precision_pi for the shared calculation. They initialize a
PTP-clock adapter once and use precision_clock operations to access
the PHC.
Sample
The Precision timing sample demonstrates checked time arithmetic, a software-backed precision clock, and PI-driven rate adjustment.