Loading...
Searching...
No Matches

Low-level PTP clock peripheral driver. More...

Detailed Description

Low-level PTP clock peripheral driver.

Introduction

The Precision Time Protocol (PTP) can be used to synchronize clocks with hardware support in an Ethernet PHY, that allows to precisely estimate (and, thus, compensate) network delay between time server and client. This allows PTP synchronization to be highly accurate (<< 1 µs offset between server and client), but requires hardware support on each synchronized node and the PTP server, all nodes to be connected to the same* Ethernet network, and (for best results) hardware support in all intermediate switches.

(No) Synchronization Using This API

This API is intended to provide basic access to a PTP hardware clock. This does not cover any synchronization. Some PTP hardware clocks (e.g. on the STM32) can be used without synchronization by manually setting the time. Thus, the PTP clock can be useful even without synchronization implemented.

It is intended that the actual synchronization is implemented externally later on. The functions ptp_clock_adjust and ptp_clock_adjust_speed are specified with the needs of a synchronization solution in mind.

Clock vs Timer

This API provides both ptp_clock_*() and ptp_timer_*() functions, to distinguish between the feature set being used. A PTP peripheral might only support the feature periph_ptp, but not periph_ptp_timer.

(Lack of) Power Considerations

It is assumed that a board connected to a wired network is also powered from mains. Additionally, a high-resolution high-accuracy clock that is periodically synced over network is just not going to play well with low-power application scenarios.

Files

file  ptp.h
 Low-level PTP clock peripheral driver interface definitions.
 

Data Structures

struct  ptp_timestamp_t
 A PTP timestamp in seconds + nanoseconds since UNIX epoch. More...
 

Typedefs

typedef uint32_t ptp_seconds_t
 Unsigned integer type to store seconds since epoch for use in PTP.
 

Functions

static int ptp_cmp (const ptp_timestamp_t *a, const ptp_timestamp_t *b)
 Compare two PTP timestamps.
 
static void ptp_add (ptp_timestamp_t *t, int64_t offset)
 Add a given offset onto the given timestamp.
 
static void ptp_ns2ts (ptp_timestamp_t *dest, uint64_t ns_since_epoch)
 Convert time from nanoseconds since epoch to ptp_timestamp_t format.
 
static uint64_t ptp_ts2ns (const ptp_timestamp_t *t)
 Convert time from nanoseconds since epoch to ptp_timestamp_t format.
 
void ptp_init (void)
 Initialize the given PTP peripheral.
 
void ptp_clock_adjust_speed (int32_t correction)
 Adjust the PTP clock speed as given.
 
void ptp_clock_adjust (int64_t offset)
 Adjust the PTP clock as given.
 
void ptp_clock_read (ptp_timestamp_t *timestamp)
 Get the current system time as PTP timestamp.
 
uint64_t ptp_clock_read_u64 (void)
 Get the current system time in nanosecond since UNIX epoch.
 
void ptp_clock_set (const ptp_timestamp_t *time)
 Set the current system time.
 
void ptp_clock_set_u64 (uint64_t ns_since_epoch)
 Set the current system time in nanosecond since UNIX epoch.
 
void ptp_timer_cb (void)
 External function to call when the PTP clock timer fired.
 
void ptp_timer_set_absolute (const ptp_timestamp_t *target)
 Set an absolute timeout value, possibly overwriting an existing timeout.
 
void ptp_timer_set_absolute_u64 (uint64_t target)
 Set an absolute timeout value, possibly overwriting an existing timeout.
 
void ptp_timer_set_u64 (uint64_t target)
 Set an relative timeout value, possibly overwriting an existing timeout.
 
void ptp_timer_clear (void)
 Clears any pending timeout on the PTP timer.
 

Typedef Documentation

◆ ptp_seconds_t

typedef uint32_t ptp_seconds_t

Unsigned integer type to store seconds since epoch for use in PTP.

The PTP protocol defines the seconds part of PTP timestamps as an 48 bit unsigned integer. We go for 32 bit for now (works until year 2106) and will later extend this type to 64 bit. Users are highly encouraged to use this type instead of uint32_t, if they intent that their software still works in a couple of decades.

Definition at line 93 of file ptp.h.

Function Documentation

◆ ptp_add()

static void ptp_add ( ptp_timestamp_t t,
int64_t  offset 
)
inlinestatic

Add a given offset onto the given timestamp.

Parameters
[in,out]tTimestamp to add offset to
[in]offsetOffset to apply

Definition at line 145 of file ptp.h.

◆ ptp_clock_adjust()

void ptp_clock_adjust ( int64_t  offset)

Adjust the PTP clock as given.

Parameters
offsetOffset to add onto current system time

Same as ptp_clock_set_u64(ptp_clock_read_u64() + offset), but implemented to introduce as little error as possible while setting the offset. This is intended to be used by clock synchronization implementations.

◆ ptp_clock_adjust_speed()

void ptp_clock_adjust_speed ( int32_t  correction)

Adjust the PTP clock speed as given.

Parameters
correctionSpecification of the clock speed adjustment
Note
This implies feature periph_ptp_speed_adjustment

The clock speed is adjusted in regard to its nominal clock speed. This means that calls with the same value in correction are idempotent.

  1. A call with correction set to 0 restores the nominal clock speed.
  2. A call with a positive value for correction speeds the clock up by correction / (1 << 32) (so up to ~50% for INT32_MAX).
  3. A call with a negative value for correction slows the clock down by -correction / (1 << 32) (so up to 50% for INT32_MIN).

This allows the clock speed to be adjusted in steps ± 2.3284E-08 % in relation to its nominal clock speed, thus, allowing to counter systematic clock drift. In addition, this is intended to "smoothly" synchronize the clock over time to avoid jumps in the system time. (Especially calling ptp_clock_adjust with negative values might be something to avoid, when applications are not prepared with clocks going backwards.)

◆ ptp_clock_read()

static void ptp_clock_read ( ptp_timestamp_t timestamp)
inline

Get the current system time as PTP timestamp.

Parameters
[out]timestampThe timestamp will be written here
Precondition
The PTP clock is initialized

Definition at line 356 of file ptp.h.

◆ ptp_clock_read_u64()

static uint64_t ptp_clock_read_u64 ( void  )
inline

Get the current system time in nanosecond since UNIX epoch.

Returns
Nanoseconds since 1. 1. 1970 0:00:00 UTC
Precondition
The PTP clock is initialized
Note
An uint64_t allows nanosecond timestamps within 1970-01-01 and 2554-07-21 to be represented.

Definition at line 363 of file ptp.h.

◆ ptp_clock_set()

static void ptp_clock_set ( const ptp_timestamp_t time)
inline

Set the current system time.

Parameters
timeThe new system time
Precondition
The PTP clock is initialized

Definition at line 372 of file ptp.h.

◆ ptp_clock_set_u64()

static void ptp_clock_set_u64 ( uint64_t  ns_since_epoch)
inline

Set the current system time in nanosecond since UNIX epoch.

Parameters
ns_since_epochNew time to set
Precondition
The PTP clock is initialized

Definition at line 379 of file ptp.h.

◆ ptp_cmp()

static int ptp_cmp ( const ptp_timestamp_t a,
const ptp_timestamp_t b 
)
inlinestatic

Compare two PTP timestamps.

Parameters
aFirst timestamp
bSecond timestamp
Return values
-1a < b
0a == b
1a > b

Definition at line 118 of file ptp.h.

◆ ptp_init()

void ptp_init ( void  )

Initialize the given PTP peripheral.

Note
Implementations of this functions have to use assert() to make the configuration is valid.
Precondition
This function must be called at most once

After calling this, the PTP clock (and the PTP timer, if the feature periph_ptp_timer is used in addition to periph_ptp_clock) can be used.

◆ ptp_ns2ts()

static void ptp_ns2ts ( ptp_timestamp_t dest,
uint64_t  ns_since_epoch 
)
inlinestatic

Convert time from nanoseconds since epoch to ptp_timestamp_t format.

Parameters
[out]destThe timestamp will be written here
[in]ns_since_epochTime in nanoseconds since epoch to convert

Definition at line 176 of file ptp.h.

◆ ptp_timer_cb()

void ptp_timer_cb ( void  )

External function to call when the PTP clock timer fired.

Note
This function needs to be implemented by the user of this API
This function implies feature periph_ptp_timer

Since at most one PTP clock is expected on each board, we can avoid the overhead of indirect function calls here and let users of this API just implement this function.

◆ ptp_timer_clear()

void ptp_timer_clear ( void  )

Clears any pending timeout on the PTP timer.

Note
This function implies feature periph_ptp_timer

◆ ptp_timer_set_absolute()

static void ptp_timer_set_absolute ( const ptp_timestamp_t target)
inline

Set an absolute timeout value, possibly overwriting an existing timeout.

Parameters
targetTimestamp when the timeout should fire
Note
Only a single timeout is supported by the PTP timer
This function implies feature periph_ptp_timer

If the target time is in the past or equal to the current time, the IRQ should trigger right away.

Definition at line 388 of file ptp.h.

◆ ptp_timer_set_absolute_u64()

static void ptp_timer_set_absolute_u64 ( uint64_t  target)
inline

Set an absolute timeout value, possibly overwriting an existing timeout.

Parameters
targetTimestamp when the timeout should fire (ns since epoch)
Note
Only a single timeout is supported by the PTP timer
This function implies feature periph_ptp_timer

If the target time is in the past or equal to the current time, the IRQ should trigger right away.

Definition at line 395 of file ptp.h.

◆ ptp_timer_set_u64()

void ptp_timer_set_u64 ( uint64_t  target)

Set an relative timeout value, possibly overwriting an existing timeout.

Parameters
targetNumber of nanoseconds after which the timeout should fire
Note
Only a single timeout is supported by the PTP timer
This function implies feature periph_ptp_timer

◆ ptp_ts2ns()

static uint64_t ptp_ts2ns ( const ptp_timestamp_t t)
inlinestatic

Convert time from nanoseconds since epoch to ptp_timestamp_t format.

Parameters
[in]tTime to convert to nanoseconds since epoch
Returns
The time specified by t in nanoseconds since epoch

Definition at line 189 of file ptp.h.