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
9#pragma once
10
57
58#include <stdint.h>
59
60#include "periph_cpu.h"
61#include "timex.h"
62
63#ifdef __cplusplus
64extern "C" {
65#endif
66
67/* verify settings from periph_cpu.h */
68#if !defined(HAVE_PTP_CLOCK_READ) && !defined(HAVE_PTP_CLOCK_READ_U64)
69#error "Neither ptp_clock_read() nor ptp_clock_read_u64() implemented"
70#endif
71
72#if !defined(HAVE_PTP_CLOCK_SET) && !defined(HAVE_PTP_CLOCK_SET_U64)
73#error "Neither ptp_clock_set() nor ptp_clock_set_u64() implemented"
74#endif
75
76#if \
77 !defined(HAVE_PTP_TIMER_SET_ABSOLUTE) && \
78 !defined(HAVE_PTP_TIMER_SET_ABSOLUTE_U64) && \
79 IS_USED(MODULE_PERIPH_PTP_TIMER)
80#error "Neither ptp_timer_set_absolute() nor ptp_timer_set_absolute_u64() implemented"
81#endif
82
92typedef uint32_t ptp_seconds_t;
93
106
117static inline int ptp_cmp(const ptp_timestamp_t *a, const ptp_timestamp_t *b)
118{
119 if (a->seconds < b->seconds) {
120 return -1;
121 }
122
123 if (a->seconds > b->seconds) {
124 return 1;
125 }
126
127 if (a->nanoseconds < b->nanoseconds) {
128 return -1;
129 }
130
131 if (a->nanoseconds > b->nanoseconds) {
132 return 1;
133 }
134
135 return 0;
136}
137
144static inline void ptp_add(ptp_timestamp_t *t, int64_t offset)
145{
146 /* Modulo for negative numbers should be avoided */
147 if (offset >= 0) {
148 uint64_t abs_offset = offset;
149 t->seconds += abs_offset / NS_PER_SEC;
150 t->nanoseconds += abs_offset % NS_PER_SEC;
151 /* correct overflow of nanosecond part */
152 if (t->nanoseconds >= NS_PER_SEC) {
154 t->seconds++;
155 }
156 }
157 else {
158 uint64_t abs_offset = -offset;
159 t->seconds -= abs_offset / NS_PER_SEC;
160 t->nanoseconds -= abs_offset % NS_PER_SEC;
161 /* correct underflow of nanosecond part */
162 if (t->nanoseconds > NS_PER_SEC) {
164 t->seconds--;
165 }
166 }
167}
168
175static inline void ptp_ns2ts(ptp_timestamp_t *dest, uint64_t ns_since_epoch)
176{
177 dest->seconds = ns_since_epoch / NS_PER_SEC;
178 dest->nanoseconds = ns_since_epoch % NS_PER_SEC;
179}
180
188static inline uint64_t ptp_ts2ns(const ptp_timestamp_t *t)
189{
190 return t->seconds * NS_PER_SEC + t->nanoseconds;
191}
192
204void ptp_init(void);
205
229void ptp_clock_adjust_speed(int32_t correction);
230
240void ptp_clock_adjust(int64_t offset);
241
242#if defined(HAVE_PTP_CLOCK_READ) || defined(DOXYGEN)
249void ptp_clock_read(ptp_timestamp_t *timestamp);
250#endif /* HAVE_PTP_CLOCK_READ */
251
252#if defined(HAVE_PTP_CLOCK_READ_U64) || defined(DOXYGEN)
263uint64_t ptp_clock_read_u64(void);
264#endif /* HAVE_PTP_CLOCK_READ_U64 */
265
266#if defined(HAVE_PTP_CLOCK_SET) || defined(DOXYGEN)
274void ptp_clock_set(const ptp_timestamp_t *time);
275#endif /* HAVE_PTP_CLOCK_SET */
276
277#if defined(HAVE_PTP_CLOCK_SET_U64) || defined(DOXYGEN)
285void ptp_clock_set_u64(uint64_t ns_since_epoch);
286#endif /* HAVE_PTP_CLOCK_SET_U64 */
287
298void ptp_timer_cb(void);
299
300#if defined(HAVE_PTP_TIMER_SET_ABSOLUTE) || defined(DOXYGEN)
313void ptp_timer_set_absolute(const ptp_timestamp_t *target);
314#endif /* HAVE_PTP_TIMER_SET_ABSOLUTE */
315
316#if defined(HAVE_PTP_TIMER_SET_ABSOLUTE_U64) || defined(DOXYGEN)
329void ptp_timer_set_absolute_u64(uint64_t target);
330#endif /* HAVE_PTP_TIMER_SET_ABSOLUTE_U64 */
331
341void ptp_timer_set_u64(uint64_t target);
342
349
350/* Fallback implementations (the driver can implement either the
351 * functions using `ptp_timestamp_t` or `uint64_t`, the other flavor will
352 * be provided on top here): */
353
354#ifndef HAVE_PTP_CLOCK_READ
355static inline void ptp_clock_read(struct ptp_timestamp_t *timestamp)
356{
357 ptp_ns2ts(timestamp, ptp_clock_read_u64());
358}
359#endif /* !HAVE_PTP_CLOCK_READ */
360
361#ifndef HAVE_PTP_CLOCK_READ_U64
362static inline uint64_t ptp_clock_read_u64(void)
363{
365 ptp_clock_read(&ts);
366 return ptp_ts2ns(&ts);
367}
368#endif /* !HAVE_PTP_CLOCK_READ_U64 */
369
370#ifndef HAVE_PTP_CLOCK_SET
371static inline void ptp_clock_set(const ptp_timestamp_t *time)
372{
374}
375#endif /* !HAVE_PTP_CLOCK_SET */
376
377#ifndef HAVE_PTP_CLOCK_SET_U64
378static inline void ptp_clock_set_u64(uint64_t ns_since_epoch)
379{
380 ptp_timestamp_t time;
381 ptp_ns2ts(&time, ns_since_epoch);
382 ptp_clock_set(&time);
383}
384#endif /* !HAVE_PTP_CLOCK_SET_U64 */
385
386#ifndef HAVE_PTP_TIMER_SET_ABSOLUTE
387static inline void ptp_timer_set_absolute(const ptp_timestamp_t *target)
388{
390}
391#endif /* !HAVE_PTP_TIMER_SET_ABSOLUTE */
392
393#ifndef HAVE_PTP_TIMER_SET_ABSOLUTE_U64
394static inline void ptp_timer_set_absolute_u64(uint64_t target)
395{
397 ptp_ns2ts(&ts, target);
399}
400#endif /* !HAVE_PTP_TIMER_SET_ABSOLUTE_U64 */
401
402#ifdef __cplusplus
403}
404#endif
405
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:144
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:175
uint32_t ptp_seconds_t
Unsigned integer type to store seconds since epoch for use in PTP.
Definition ptp.h:92
void ptp_clock_set_u64(uint64_t ns_since_epoch)
Set the current system time in nanosecond since UNIX epoch.
Definition ptp.h:378
static int ptp_cmp(const ptp_timestamp_t *a, const ptp_timestamp_t *b)
Compare two PTP timestamps.
Definition ptp.h:117
uint64_t ptp_clock_read_u64(void)
Get the current system time in nanosecond since UNIX epoch.
Definition ptp.h:362
void ptp_timer_set_absolute_u64(uint64_t target)
Set an absolute timeout value, possibly overwriting an existing timeout.
Definition ptp.h:394
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:355
void ptp_timer_set_absolute(const ptp_timestamp_t *target)
Set an absolute timeout value, possibly overwriting an existing timeout.
Definition ptp.h:387
void ptp_clock_set(const ptp_timestamp_t *time)
Set the current system time.
Definition ptp.h:371
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:188
#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:102
uint32_t nanoseconds
Nanoseconds part.
Definition ptp.h:104
ptp_seconds_t seconds
Seconds since UNIX epoch.
Definition ptp.h:103
Utility library for comparing and computing timestamps.