Loading...
Searching...
No Matches
ptp.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2020 Otto-von-Guericke-Universität Magdeburg
3 * SPDX-License-Identifier: LGPL-2.1-only
4 */
5
6#pragma once
7
54
55#include <stdint.h>
56
57#include "periph_cpu.h"
58#include "timex.h"
59
60#ifdef __cplusplus
61extern "C" {
62#endif
63
64/* verify settings from periph_cpu.h */
65#if !defined(HAVE_PTP_CLOCK_READ) && !defined(HAVE_PTP_CLOCK_READ_U64)
66#error "Neither ptp_clock_read() nor ptp_clock_read_u64() implemented"
67#endif
68
69#if !defined(HAVE_PTP_CLOCK_SET) && !defined(HAVE_PTP_CLOCK_SET_U64)
70#error "Neither ptp_clock_set() nor ptp_clock_set_u64() implemented"
71#endif
72
73#if \
74 !defined(HAVE_PTP_TIMER_SET_ABSOLUTE) && \
75 !defined(HAVE_PTP_TIMER_SET_ABSOLUTE_U64) && \
76 IS_USED(MODULE_PERIPH_PTP_TIMER)
77#error "Neither ptp_timer_set_absolute() nor ptp_timer_set_absolute_u64() implemented"
78#endif
79
89typedef uint32_t ptp_seconds_t;
90
99typedef struct {
101 uint32_t nanoseconds;
103
114static inline int ptp_cmp(const ptp_timestamp_t *a, const ptp_timestamp_t *b)
115{
116 if (a->seconds < b->seconds) {
117 return -1;
118 }
119
120 if (a->seconds > b->seconds) {
121 return 1;
122 }
123
124 if (a->nanoseconds < b->nanoseconds) {
125 return -1;
126 }
127
128 if (a->nanoseconds > b->nanoseconds) {
129 return 1;
130 }
131
132 return 0;
133}
134
141static inline void ptp_add(ptp_timestamp_t *t, int64_t offset)
142{
143 /* Modulo for negative numbers should be avoided */
144 if (offset >= 0) {
145 uint64_t abs_offset = offset;
146 t->seconds += abs_offset / NS_PER_SEC;
147 t->nanoseconds += abs_offset % NS_PER_SEC;
148 /* correct overflow of nanosecond part */
149 if (t->nanoseconds >= NS_PER_SEC) {
151 t->seconds++;
152 }
153 }
154 else {
155 uint64_t abs_offset = -offset;
156 t->seconds -= abs_offset / NS_PER_SEC;
157 t->nanoseconds -= abs_offset % NS_PER_SEC;
158 /* correct underflow of nanosecond part */
159 if (t->nanoseconds > NS_PER_SEC) {
161 t->seconds--;
162 }
163 }
164}
165
172static inline void ptp_ns2ts(ptp_timestamp_t *dest, uint64_t ns_since_epoch)
173{
174 dest->seconds = ns_since_epoch / NS_PER_SEC;
175 dest->nanoseconds = ns_since_epoch % NS_PER_SEC;
176}
177
185static inline uint64_t ptp_ts2ns(const ptp_timestamp_t *t)
186{
187 return t->seconds * NS_PER_SEC + t->nanoseconds;
188}
189
201void ptp_init(void);
202
226void ptp_clock_adjust_speed(int32_t correction);
227
237void ptp_clock_adjust(int64_t offset);
238
239#if defined(HAVE_PTP_CLOCK_READ) || defined(DOXYGEN)
246void ptp_clock_read(ptp_timestamp_t *timestamp);
247#endif /* HAVE_PTP_CLOCK_READ */
248
249#if defined(HAVE_PTP_CLOCK_READ_U64) || defined(DOXYGEN)
260uint64_t ptp_clock_read_u64(void);
261#endif /* HAVE_PTP_CLOCK_READ_U64 */
262
263#if defined(HAVE_PTP_CLOCK_SET) || defined(DOXYGEN)
271void ptp_clock_set(const ptp_timestamp_t *time);
272#endif /* HAVE_PTP_CLOCK_SET */
273
274#if defined(HAVE_PTP_CLOCK_SET_U64) || defined(DOXYGEN)
282void ptp_clock_set_u64(uint64_t ns_since_epoch);
283#endif /* HAVE_PTP_CLOCK_SET_U64 */
284
295void ptp_timer_cb(void);
296
297#if defined(HAVE_PTP_TIMER_SET_ABSOLUTE) || defined(DOXYGEN)
310void ptp_timer_set_absolute(const ptp_timestamp_t *target);
311#endif /* HAVE_PTP_TIMER_SET_ABSOLUTE */
312
313#if defined(HAVE_PTP_TIMER_SET_ABSOLUTE_U64) || defined(DOXYGEN)
326void ptp_timer_set_absolute_u64(uint64_t target);
327#endif /* HAVE_PTP_TIMER_SET_ABSOLUTE_U64 */
328
338void ptp_timer_set_u64(uint64_t target);
339
346
347/* Fallback implementations (the driver can implement either the
348 * functions using `ptp_timestamp_t` or `uint64_t`, the other flavor will
349 * be provided on top here): */
350
351#ifndef HAVE_PTP_CLOCK_READ
352static inline void ptp_clock_read(struct ptp_timestamp_t *timestamp)
353{
354 ptp_ns2ts(timestamp, ptp_clock_read_u64());
355}
356#endif /* !HAVE_PTP_CLOCK_READ */
357
358#ifndef HAVE_PTP_CLOCK_READ_U64
359static inline uint64_t ptp_clock_read_u64(void)
360{
362 ptp_clock_read(&ts);
363 return ptp_ts2ns(&ts);
364}
365#endif /* !HAVE_PTP_CLOCK_READ_U64 */
366
367#ifndef HAVE_PTP_CLOCK_SET
368static inline void ptp_clock_set(const ptp_timestamp_t *time)
369{
371}
372#endif /* !HAVE_PTP_CLOCK_SET */
373
374#ifndef HAVE_PTP_CLOCK_SET_U64
375static inline void ptp_clock_set_u64(uint64_t ns_since_epoch)
376{
377 ptp_timestamp_t time;
378 ptp_ns2ts(&time, ns_since_epoch);
379 ptp_clock_set(&time);
380}
381#endif /* !HAVE_PTP_CLOCK_SET_U64 */
382
383#ifndef HAVE_PTP_TIMER_SET_ABSOLUTE
384static inline void ptp_timer_set_absolute(const ptp_timestamp_t *target)
385{
387}
388#endif /* !HAVE_PTP_TIMER_SET_ABSOLUTE */
389
390#ifndef HAVE_PTP_TIMER_SET_ABSOLUTE_U64
391static inline void ptp_timer_set_absolute_u64(uint64_t target)
392{
394 ptp_ns2ts(&ts, target);
396}
397#endif /* !HAVE_PTP_TIMER_SET_ABSOLUTE_U64 */
398
399#ifdef __cplusplus
400}
401#endif
402
void ptp_timer_set_u64(uint64_t target)
Set an relative timeout value, possibly overwriting an existing timeout.
static void ptp_add(ptp_timestamp_t *t, int64_t offset)
Add a given offset onto the given timestamp.
Definition ptp.h:141
static void ptp_ns2ts(ptp_timestamp_t *dest, uint64_t ns_since_epoch)
Convert time from nanoseconds since epoch to ptp_timestamp_t format.
Definition ptp.h:172
uint32_t ptp_seconds_t
Unsigned integer type to store seconds since epoch for use in PTP.
Definition ptp.h:89
void ptp_clock_set_u64(uint64_t ns_since_epoch)
Set the current system time in nanosecond since UNIX epoch.
Definition ptp.h:375
static int ptp_cmp(const ptp_timestamp_t *a, const ptp_timestamp_t *b)
Compare two PTP timestamps.
Definition ptp.h:114
uint64_t ptp_clock_read_u64(void)
Get the current system time in nanosecond since UNIX epoch.
Definition ptp.h:359
void ptp_timer_set_absolute_u64(uint64_t target)
Set an absolute timeout value, possibly overwriting an existing timeout.
Definition ptp.h:391
void ptp_clock_adjust_speed(int32_t correction)
Adjust the PTP clock speed as given.
void ptp_clock_read(ptp_timestamp_t *timestamp)
Get the current system time as PTP timestamp.
Definition ptp.h:352
void ptp_timer_set_absolute(const ptp_timestamp_t *target)
Set an absolute timeout value, possibly overwriting an existing timeout.
Definition ptp.h:384
void ptp_clock_set(const ptp_timestamp_t *time)
Set the current system time.
Definition ptp.h:368
void ptp_timer_cb(void)
External function to call when the PTP clock timer fired.
void ptp_timer_clear(void)
Clears any pending timeout on the PTP timer.
void ptp_clock_adjust(int64_t offset)
Adjust the PTP clock as given.
void ptp_init(void)
Initialize the given PTP peripheral.
static uint64_t ptp_ts2ns(const ptp_timestamp_t *t)
Convert time from nanoseconds since epoch to ptp_timestamp_t format.
Definition ptp.h:185
#define NS_PER_SEC
The number of nanoseconds per second.
Definition time_units.h:109
A PTP timestamp in seconds + nanoseconds since UNIX epoch.
Definition ptp.h:99
uint32_t nanoseconds
Nanoseconds part.
Definition ptp.h:101
ptp_seconds_t seconds
Seconds since UNIX epoch.
Definition ptp.h:100
Utility library for comparing and computing timestamps.