1 /*
2  * Copyright (c) 2018 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief Public functions for the Precision Time Protocol time specification.
10  *
11  * References are to version 2019 of IEEE 1588, ("PTP")
12  * and version 2020 of IEEE 802.1AS ("gPTP").
13  */
14 
15 #ifndef ZEPHYR_INCLUDE_NET_PTP_TIME_H_
16 #define ZEPHYR_INCLUDE_NET_PTP_TIME_H_
17 
18 /**
19  * @brief Precision Time Protocol time specification
20  * @defgroup ptp_time PTP time
21  * @since 1.13
22  * @version 0.8.0
23  * @ingroup networking
24  * @{
25  */
26 
27 #include <zephyr/net/net_core.h>
28 #include <zephyr/net/net_time.h>
29 #include <zephyr/toolchain.h>
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 /**
36  * @brief (Generalized) Precision Time Protocol Timestamp format.
37  *
38  * @details This structure represents a timestamp according to the Precision
39  * Time Protocol standard ("PTP", IEEE 1588, section 5.3.3), the Generalized
40  * Precision Time Protocol standard ("gPTP", IEEE 802.1AS, section 6.4.3.4), or
41  * any other well-defined context in which precision structured timestamps are
42  * required on network messages in Zephyr.
43  *
44  * Seconds are encoded as a 48 bits unsigned integer. Nanoseconds are encoded
45  * as a 32 bits unsigned integer.
46  *
47  * In the context of (g)PTP, @em timestamps designate the time, relative to a
48  * local clock ("LocalClock") at which the message timestamp point passes a
49  * reference plane marking the boundary between the PTP Instance and the network
50  * medium (IEEE 1855, section 7.3.4.2; IEEE 802.1AS, section 8.4.3).
51  *
52  * The exact definitions of the <em>message timestamp point</em> and
53  * <em>reference plane</em> depends on the network medium and use case.
54  *
55  * For (g)PTP the media-specific message timestamp points and reference planes
56  * are defined in the standard. In non-PTP contexts specific to Zephyr,
57  * timestamps are measured relative to the same local clock but with a
58  * context-specific message timestamp point and reference plane, defined below
59  * per use case.
60  *
61  * A @em "LocalClock" is a freerunning clock, embedded into a well-defined
62  * entity (e.g. a PTP Instance) and provides a common time to that entity
63  * relative to an arbitrary epoch (IEEE 1855, section 3.1.26, IEEE 802.1AS,
64  * section 3.16).
65  *
66  * In Zephyr, the local clock is usually any instance of a kernel system clock
67  * driver, counter driver, RTC API driver or low-level counter/timer peripheral
68  * (e.g. an ethernet peripheral with hardware timestamp support or a radio
69  * timer) with sufficient precision for the context in which it is used.
70  *
71  * See IEEE 802.1AS, Annex B for specific performance requirements regarding
72  * conformance of local clocks in the gPTP context. See IEEE 1588, Annex A,
73  * section A5.4 for general performance requirements regarding PTP local clocks.
74  * See IEEE 802.15.4-2020, section 15.7 for requirements in the context of
75  * ranging applications and ibid., section 6.7.6 for the relation between guard
76  * times and clock accuracy which again influence the precision required for
77  * subprotocols like CSL, TSCH, RIT, etc.
78  *
79  * Applications that use timestamps across different subsystems or media must
80  * ensure that they understand the definition of the respective reference planes
81  * and interpret timestamps accordingly. Applications must further ensure that
82  * timestamps are either all referenced to the same local clock or convert
83  * between clocks based on sufficiently precise conversion algorithms.
84  *
85  * Timestamps may be measured on ingress (RX timestamps) or egress (TX
86  * timestamps) of network messages. Timestamps can also be used to schedule a
87  * network message to a well-defined point in time in the future at which it is
88  * to be sent over the medium (timed TX). A future timestamp and a duration,
89  * both referenced to the local clock, may be given to specify a time window at
90  * which a network device should expect incoming messages (RX window).
91  *
92  * In Zephyr this timestamp structure is currently used in the following
93  * contexts:
94  *  * gPTP for Full Duplex Point-to-Point IEEE 802.3 links (IEEE 802.1AS,
95  *    section 11): the reference plane and message timestamp points are as
96  *    defined in the standard.
97  *  * IEEE 802.15.4 timed TX and RX: Timestamps designate the point in time at
98  *    which the end of the last symbol of the start-of-frame delimiter (SFD) (or
99  *    equivalently, the start of the first symbol of the PHY header) is at the
100  *    local antenna. The standard also refers to this as the "RMARKER" (IEEE
101  *    802.15.4-2020, section 6.9.1) or "symbol boundary" (ibid., section 6.5.2),
102  *    depending on the context. In the context of beacon timestamps, the
103  *    difference between the timestamp measurement plane and the reference plane
104  *    is defined by the MAC PIB attribute "macSyncSymbolOffset", ibid., section
105  *    8.4.3.1, table 8-94.
106  *
107  * If further use cases are added to Zephyr using this timestamp structure,
108  * their clock performance requirements, message timestamp points and reference
109  * plane definition SHALL be added to the above list.
110  */
111 struct net_ptp_time {
112 	/** Seconds encoded on 48 bits. */
113 	union {
114 
115 /** @cond INTERNAL_HIDDEN */
116 		struct {
117 #ifdef CONFIG_LITTLE_ENDIAN
118 			uint32_t low;
119 			uint16_t high;
120 			uint16_t unused;
121 #else
122 			uint16_t unused;
123 			uint16_t high;
124 			uint32_t low;
125 #endif
126 		} _sec;
127 /** @endcond */
128 
129 		/** Second value. */
130 		uint64_t second;
131 	};
132 
133 	/** Nanoseconds. */
134 	uint32_t nanosecond;
135 };
136 
137 #ifdef __cplusplus
138 }
139 #endif
140 
141 /**
142  * @brief Generalized Precision Time Protocol Extended Timestamp format.
143  *
144  * @details This structure represents an extended timestamp according to the
145  * Generalized Precision Time Protocol standard (IEEE 802.1AS), see section
146  * 6.4.3.5.
147  *
148  * Seconds are encoded as 48 bits unsigned integer. Fractional nanoseconds are
149  * encoded as 48 bits, their unit is 2*(-16) ns.
150  *
151  * A precise definition of PTP timestamps and their uses in Zephyr is given in
152  * the description of @ref net_ptp_time.
153  */
154 struct net_ptp_extended_time {
155 	/** Seconds encoded on 48 bits. */
156 	union {
157 
158 /** @cond INTERNAL_HIDDEN */
159 		struct {
160 #ifdef CONFIG_LITTLE_ENDIAN
161 			uint32_t low;
162 			uint16_t high;
163 			uint16_t unused;
164 #else
165 			uint16_t unused;
166 			uint16_t high;
167 			uint32_t low;
168 #endif
169 		} _sec;
170 /** @endcond */
171 
172 		/** Second value. */
173 		uint64_t second;
174 	};
175 
176 	/** Fractional nanoseconds on 48 bits. */
177 	union {
178 
179 /** @cond INTERNAL_HIDDEN */
180 		struct {
181 #ifdef CONFIG_LITTLE_ENDIAN
182 			uint32_t low;
183 			uint16_t high;
184 			uint16_t unused;
185 #else
186 			uint16_t unused;
187 			uint16_t high;
188 			uint32_t low;
189 #endif
190 		} _fns;
191 /** @endcond */
192 
193 		/** Fractional nanoseconds value. */
194 		uint64_t fract_nsecond;
195 	};
196 } __packed;
197 
198 /**
199  * @brief Convert a PTP timestamp to a nanosecond precision timestamp, both
200  * related to the local network reference clock.
201  *
202  * @note Only timestamps representing up to ~290 years can be converted to
203  * nanosecond timestamps. Larger timestamps will return the maximum
204  * representable nanosecond precision timestamp.
205  *
206  * @param ts the PTP timestamp
207  *
208  * @return the corresponding nanosecond precision timestamp
209  */
net_ptp_time_to_ns(struct net_ptp_time * ts)210 static inline net_time_t net_ptp_time_to_ns(struct net_ptp_time *ts)
211 {
212 	if (!ts) {
213 		return 0;
214 	}
215 
216 	if (ts->second >= NET_TIME_SEC_MAX) {
217 		return NET_TIME_MAX;
218 	}
219 
220 	return ((int64_t)ts->second * NSEC_PER_SEC) + ts->nanosecond;
221 }
222 
223 /**
224  * @brief Convert a nanosecond precision timestamp to a PTP timestamp, both
225  * related to the local network reference clock.
226  *
227  * @param nsec a nanosecond precision timestamp
228  *
229  * @return the corresponding PTP timestamp
230  */
ns_to_net_ptp_time(net_time_t nsec)231 static inline struct net_ptp_time ns_to_net_ptp_time(net_time_t nsec)
232 {
233 	struct net_ptp_time ts;
234 
235 	__ASSERT_NO_MSG(nsec >= 0);
236 
237 	ts.second = nsec / NSEC_PER_SEC;
238 	ts.nanosecond = nsec % NSEC_PER_SEC;
239 	return ts;
240 }
241 
242 /**
243  * @}
244  */
245 
246 #endif /* ZEPHYR_INCLUDE_NET_PTP_TIME_H_ */
247