Loading...
Searching...
No Matches
ptp.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2020 Otto-von-Guericke-Universität Magdeburg
3 *
4 * This file is subject to the terms and conditions of the GNU Lesser
5 * General Public License v2.1. See the file LICENSE in the top level
6 * directory for more details.
7 */
8
56#ifndef PERIPH_PTP_H
57#define PERIPH_PTP_H
58
59#include <stdint.h>
60
61#include "periph_cpu.h"
62#include "timex.h"
63
64#ifdef __cplusplus
65extern "C" {
66#endif
67
68/* verify settings from periph_cpu.h */
69#if !defined(HAVE_PTP_CLOCK_READ) && !defined(HAVE_PTP_CLOCK_READ_U64)
70#error "Neither ptp_clock_read() nor ptp_clock_read_u64() implemented"
71#endif
72
73#if !defined(HAVE_PTP_CLOCK_SET) && !defined(HAVE_PTP_CLOCK_SET_U64)
74#error "Neither ptp_clock_set() nor ptp_clock_set_u64() implemented"
75#endif
76
77#if \
78 !defined(HAVE_PTP_TIMER_SET_ABSOLUTE) && \
79 !defined(HAVE_PTP_TIMER_SET_ABSOLUTE_U64) && \
80 IS_USED(MODULE_PERIPH_PTP_TIMER)
81#error "Neither ptp_timer_set_absolute() nor ptp_timer_set_absolute_u64() implemented"
82#endif
83
93typedef uint32_t ptp_seconds_t;
94
107
118static inline int ptp_cmp(const ptp_timestamp_t *a, const ptp_timestamp_t *b)
119{
120 if (a->seconds < b->seconds) {
121 return -1;
122 }
123
124 if (a->seconds > b->seconds) {
125 return 1;
126 }
127
128 if (a->nanoseconds < b->nanoseconds) {
129 return -1;
130 }
131
132 if (a->nanoseconds > b->nanoseconds) {
133 return 1;
134 }
135
136 return 0;
137}
138
145static inline void ptp_add(ptp_timestamp_t *t, int64_t offset)
146{
147 /* Modulo for negative numbers should be avoided */
148 if (offset >= 0) {
149 uint64_t abs_offset = offset;
150 t->seconds += abs_offset / NS_PER_SEC;
151 t->nanoseconds += abs_offset % NS_PER_SEC;
152 /* correct overflow of nanosecond part */
153 if (t->nanoseconds >= NS_PER_SEC) {
155 t->seconds++;
156 }
157 }
158 else {
159 uint64_t abs_offset = -offset;
160 t->seconds -= abs_offset / NS_PER_SEC;
161 t->nanoseconds -= abs_offset % NS_PER_SEC;
162 /* correct underflow of nanosecond part */
163 if (t->nanoseconds > NS_PER_SEC) {
165 t->seconds--;
166 }
167 }
168}
169
176static inline void ptp_ns2ts(ptp_timestamp_t *dest, uint64_t ns_since_epoch)
177{
178 dest->seconds = ns_since_epoch / NS_PER_SEC;
179 dest->nanoseconds = ns_since_epoch % NS_PER_SEC;
180}
181
189static inline uint64_t ptp_ts2ns(const ptp_timestamp_t *t)
190{
191 return t->seconds * NS_PER_SEC + t->nanoseconds;
192}
193
205void ptp_init(void);
206
230void ptp_clock_adjust_speed(int32_t correction);
231
241void ptp_clock_adjust(int64_t offset);
242
243#if defined(HAVE_PTP_CLOCK_READ) || defined(DOXYGEN)
250void ptp_clock_read(ptp_timestamp_t *timestamp);
251#endif /* HAVE_PTP_CLOCK_READ */
252
253#if defined(HAVE_PTP_CLOCK_READ_U64) || defined(DOXYGEN)
264uint64_t ptp_clock_read_u64(void);
265#endif /* HAVE_PTP_CLOCK_READ_U64 */
266
267#if defined(HAVE_PTP_CLOCK_SET) || defined(DOXYGEN)
275void ptp_clock_set(const ptp_timestamp_t *time);
276#endif /* HAVE_PTP_CLOCK_SET */
277
278#if defined(HAVE_PTP_CLOCK_SET_U64) || defined(DOXYGEN)
286void ptp_clock_set_u64(uint64_t ns_since_epoch);
287#endif /* HAVE_PTP_CLOCK_SET_U64 */
288
299void ptp_timer_cb(void);
300
301#if defined(HAVE_PTP_TIMER_SET_ABSOLUTE) || defined(DOXYGEN)
314void ptp_timer_set_absolute(const ptp_timestamp_t *target);
315#endif /* HAVE_PTP_TIMER_SET_ABSOLUTE */
316
317#if defined(HAVE_PTP_TIMER_SET_ABSOLUTE_U64) || defined(DOXYGEN)
330void ptp_timer_set_absolute_u64(uint64_t target);
331#endif /* HAVE_PTP_TIMER_SET_ABSOLUTE_U64 */
332
342void ptp_timer_set_u64(uint64_t target);
343
350
351/* Fallback implementations (the driver can implement either the
352 * functions using `ptp_timestamp_t` or `uint64_t`, the other flavor will
353 * be provided on top here): */
354
355#ifndef HAVE_PTP_CLOCK_READ
356static inline void ptp_clock_read(struct ptp_timestamp_t *timestamp)
357{
358 ptp_ns2ts(timestamp, ptp_clock_read_u64());
359}
360#endif /* !HAVE_PTP_CLOCK_READ */
361
362#ifndef HAVE_PTP_CLOCK_READ_U64
363static inline uint64_t ptp_clock_read_u64(void)
364{
366 ptp_clock_read(&ts);
367 return ptp_ts2ns(&ts);
368}
369#endif /* !HAVE_PTP_CLOCK_READ_U64 */
370
371#ifndef HAVE_PTP_CLOCK_SET
372static inline void ptp_clock_set(const ptp_timestamp_t *time)
373{
375}
376#endif /* !HAVE_PTP_CLOCK_SET */
377
378#ifndef HAVE_PTP_CLOCK_SET_U64
379static inline void ptp_clock_set_u64(uint64_t ns_since_epoch)
380{
381 ptp_timestamp_t time;
382 ptp_ns2ts(&time, ns_since_epoch);
383 ptp_clock_set(&time);
384}
385#endif /* !HAVE_PTP_CLOCK_SET_U64 */
386
387#ifndef HAVE_PTP_TIMER_SET_ABSOLUTE
388static inline void ptp_timer_set_absolute(const ptp_timestamp_t *target)
389{
391}
392#endif /* !HAVE_PTP_TIMER_SET_ABSOLUTE */
393
394#ifndef HAVE_PTP_TIMER_SET_ABSOLUTE_U64
395static inline void ptp_timer_set_absolute_u64(uint64_t target)
396{
398 ptp_ns2ts(&ts, target);
400}
401#endif /* !HAVE_PTP_TIMER_SET_ABSOLUTE_U64 */
402
403#ifdef __cplusplus
404}
405#endif
406
407#endif /* PERIPH_PTP_H */
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:145
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:176
uint32_t ptp_seconds_t
Unsigned integer type to store seconds since epoch for use in PTP.
Definition ptp.h:93
void ptp_clock_set_u64(uint64_t ns_since_epoch)
Set the current system time in nanosecond since UNIX epoch.
Definition ptp.h:379
static int ptp_cmp(const ptp_timestamp_t *a, const ptp_timestamp_t *b)
Compare two PTP timestamps.
Definition ptp.h:118
uint64_t ptp_clock_read_u64(void)
Get the current system time in nanosecond since UNIX epoch.
Definition ptp.h:363
void ptp_timer_set_absolute_u64(uint64_t target)
Set an absolute timeout value, possibly overwriting an existing timeout.
Definition ptp.h:395
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:356
void ptp_timer_set_absolute(const ptp_timestamp_t *target)
Set an absolute timeout value, possibly overwriting an existing timeout.
Definition ptp.h:388
void ptp_clock_set(const ptp_timestamp_t *time)
Set the current system time.
Definition ptp.h:372
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:189
#define NS_PER_SEC
The number of nanoseconds per second.
Definition time_units.h:110
A PTP timestamp in seconds + nanoseconds since UNIX epoch.
Definition ptp.h:103
uint32_t nanoseconds
Nanoseconds part.
Definition ptp.h:105
ptp_seconds_t seconds
Seconds since UNIX epoch.
Definition ptp.h:104
Utility library for comparing and computing timestamps.