PebbleOS v4.44.0-199-g465b7d28c
Loading...
Searching...
No Matches
Calibrated clocks

Track the rate of an imprecise oscillator by measuring it against a reference. More...

Data Structures

struct  pbl_clk_cal_ops
 Gate operations, called from the tick interrupt or a thread, one gate at a time. More...
 
struct  pbl_clk_cal
 A calibrated clock. More...
 
struct  pbl_clk_cal_status
 Calibration state, for diagnostics. More...
 

Macros

#define PBL_CLK_CAL_INIT(_ops, _params, _clk, _gate_cycles, _period_ms)
 Initializer for a struct pbl_clk_cal.
 

Functions

void pbl_clk_cal_start (struct pbl_clk_cal *cal, double nominal_hz)
 Start the periodic gates, the first one now.
 
struct pbl_clk_cal * pbl_clk_cal_find (const char *name)
 Find a calibrated clock by the name of its controller.
 
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.
 
void pbl_clk_cal_hold (struct pbl_clk_cal *cal, uint64_t rate_mhz)
 Publish a fixed rate, or the tracked one again.
 
void pbl_clk_cal_get_status (const struct pbl_clk_cal *cal, struct pbl_clk_cal_status *status)
 Get the calibration state.
 
uint64_t pbl_clk_cal_get_rate (const struct pbl_clk_cal *cal)
 Get the current rate.
 

Detailed Description

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 struct pbl_clk_cal s_cal = PBL_CLK_CAL_INIT(&s_cal_ops, &s_params,
PBL_CLK(&s_ctrl, 0), 2000, 60000);
static int prv_init(const struct pbl_device *dev) {
pbl_clk_cal_start(&s_cal, 32768.0);
return 0;
}
static int prv_get_rate(const struct pbl_clk_controller *ctrl, uint32_t id, uint64_t *mhz) {
*mhz = pbl_clk_cal_get_rate(&s_cal);
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

Data Structure Documentation

◆ pbl_clk_cal

struct pbl_clk_cal

A calibrated clock.

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.

Macro Definition Documentation

◆ 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
_opsGate operations.
_paramsNoise model, a struct pbl_freq_track_params.
_clkClock whose notifiers follow the rate, from PBL_CLK().
_gate_cyclesGate length, in oscillator cycles.
_period_msTime between gates, in milliseconds.

Function Documentation

◆ 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
nameController 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
calCalibrated clock.
Returns
Rate in mHz, 0 before any estimate.

◆ pbl_clk_cal_get_status()

void pbl_clk_cal_get_status ( const struct pbl_clk_cal *  cal,
struct pbl_clk_cal_status *  status 
)

Get the calibration state.

Parameters
calCalibrated clock.
[out]statusState.

◆ 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
calCalibrated clock.
rate_mhzRate 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
calCalibrated clock.
cyclesGate length, in oscillator cycles.
[out]hzMeasured 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
calCalibrated clock.
nominal_hzRate until the first gate succeeds.