Track the rate of an imprecise oscillator by measuring it against a reference.
More...
Track the rate of an imprecise oscillator by measuring it against a reference.
For clock providers whose rate is only known by measurement, such as an RC oscillator. The provider counts a gate of gate_cycles oscillator cycles against a reference clock; this module runs a gate every period_ms from a kernel timer, feeds the results to a Frequency tracking tracker with the oscillator's noise model, and reports the new rate to the clock's notifiers. Gates and notifiers run in the tick interrupt, so the CPU sleeps through each gate. Until the first gate succeeds, the rate is the nominal one and gates are retried every second.
To characterize an oscillator, pbl_clk_cal_sample() takes raw gates of any length and pbl_clk_cal_hold() fixes the published rate; the clk shell command exposes both.
static int prv_init(
const struct pbl_device *dev) {
return 0;
}
static int prv_get_rate(
const struct pbl_clk_controller *ctrl, uint32_t
id, uint64_t *mhz) {
return 0;
}
A calibrated clock.
Definition cal.h:63
void pbl_clk_cal_start(struct pbl_clk_cal *cal, double nominal_hz)
Start the periodic gates, the first one now.
#define PBL_CLK_CAL_INIT(_ops, _params, _clk, _gate_cycles, _period_ms)
Initializer for a struct pbl_clk_cal.
Definition cal.h:116
uint64_t pbl_clk_cal_get_rate(const struct pbl_clk_cal *cal)
Get the current rate.
A clock controller.
Definition clk.h:48
#define PBL_CLK(_ctrl, _id)
Initializer for a struct pbl_clk.
Definition clk.h:105
A hardware device.
Definition device.h:87
◆ pbl_clk_cal
| Data Fields |
|
struct pbl_clk |
clk |
Clock whose notifiers follow the rate. |
|
uint32_t |
gate_cycles |
Gate length, in oscillator cycles. |
|
const struct pbl_clk_cal_ops * |
ops |
Gate operations. |
|
const struct pbl_freq_track_params * |
params |
Noise model of the oscillator. |
|
uint32_t |
period_ms |
Time between gates, in milliseconds. |
◆ pbl_clk_cal_status
| struct pbl_clk_cal_status |
Calibration state, for diagnostics.
| Data Fields |
|
uint32_t |
accepted |
Gates used. |
|
uint32_t |
failed |
Gates skipped or failed. |
|
bool |
held |
Whether the rate is held. |
|
uint64_t |
rate_mhz |
Published rate, in mHz: the tracked one unless held. |
|
uint32_t |
rejected |
Gates rejected as outliers. |
|
uint32_t |
sigma_ppb |
Standard deviation of the tracked frequency, in parts per billion. |
|
uint64_t |
tracked_mhz |
Tracked frequency, in mHz. |
◆ PBL_CLK_CAL_INIT
| #define PBL_CLK_CAL_INIT |
( |
|
_ops, |
|
|
|
_params, |
|
|
|
_clk, |
|
|
|
_gate_cycles, |
|
|
|
_period_ms |
|
) |
| |
Value: { \
.ops = (_ops), \
.params = (_params), \
.clk = _clk, \
.gate_cycles = (_gate_cycles), \
.period_ms = (_period_ms), \
}
Initializer for a struct pbl_clk_cal.
- Parameters
-
| _ops | Gate operations. |
| _params | Noise model, a struct pbl_freq_track_params. |
| _clk | Clock whose notifiers follow the rate, from PBL_CLK(). |
| _gate_cycles | Gate length, in oscillator cycles. |
| _period_ms | Time between gates, in milliseconds. |
◆ pbl_clk_cal_find()
| struct pbl_clk_cal * pbl_clk_cal_find |
( |
const char * |
name | ) |
|
Find a calibrated clock by the name of its controller.
- Parameters
-
| name | Controller device name. |
- Returns
- Calibrated clock, or NULL if none is started under that name.
◆ pbl_clk_cal_get_rate()
| uint64_t pbl_clk_cal_get_rate |
( |
const struct pbl_clk_cal * |
cal | ) |
|
Get the current rate.
- Parameters
-
- Returns
- Rate in mHz, 0 before any estimate.
◆ pbl_clk_cal_get_status()
Get the calibration state.
- Parameters
-
| cal | Calibrated clock. |
| [out] | status | State. |
◆ pbl_clk_cal_hold()
| void pbl_clk_cal_hold |
( |
struct pbl_clk_cal * |
cal, |
|
|
uint64_t |
rate_mhz |
|
) |
| |
Publish a fixed rate, or the tracked one again.
The tracker keeps running. With a fixed rate, comparing the time kept by the clock against a reference gives the true mean rate of the oscillator.
- Parameters
-
| cal | Calibrated clock. |
| rate_mhz | Rate to publish in mHz, or 0 to follow the tracker again. |
◆ pbl_clk_cal_sample()
| int pbl_clk_cal_sample |
( |
struct pbl_clk_cal * |
cal, |
|
|
uint32_t |
cycles, |
|
|
double * |
hz |
|
) |
| |
Take one raw gate, outside the periodic calibration, which waits meanwhile.
Blocks for the gate; thread context only. The result does not reach the tracker.
- Parameters
-
| cal | Calibrated clock. |
| cycles | Gate length, in oscillator cycles. |
| [out] | hz | Measured frequency. |
- Returns
- 0 or a negative errno.
◆ pbl_clk_cal_start()
| void pbl_clk_cal_start |
( |
struct pbl_clk_cal * |
cal, |
|
|
double |
nominal_hz |
|
) |
| |
Start the periodic gates, the first one now.
- Parameters
-
| cal | Calibrated clock. |
| nominal_hz | Rate until the first gate succeeds. |