/* * Copyright (c) 2018 Intel Corporation. * * SPDX-License-Identifier: Apache-2.0 */ /** * @file * @brief Public functions for the Precision Time Protocol time specification. * * References are to version 2019 of IEEE 1588, ("PTP") * and version 2020 of IEEE 802.1AS ("gPTP"). */ #ifndef ZEPHYR_INCLUDE_NET_PTP_TIME_H_ #define ZEPHYR_INCLUDE_NET_PTP_TIME_H_ /** * @brief Precision Time Protocol time specification * @defgroup ptp_time PTP time * @ingroup networking * @{ */ #include #include #include #ifdef __cplusplus extern "C" { #endif /** * @brief (Generalized) Precision Time Protocol Timestamp format. * * @details This structure represents a timestamp according to the Precision * Time Protocol standard ("PTP", IEEE 1588, section 5.3.3), the Generalized * Precision Time Protocol standard ("gPTP", IEEE 802.1AS, section 6.4.3.4), or * any other well-defined context in which precision structured timestamps are * required on network messages in Zephyr. * * Seconds are encoded as a 48 bits unsigned integer. Nanoseconds are encoded * as a 32 bits unsigned integer. * * In the context of (g)PTP, @em timestamps designate the time, relative to a * local clock ("LocalClock") at which the message timestamp point passes a * reference plane marking the boundary between the PTP Instance and the network * medium (IEEE 1855, section 7.3.4.2; IEEE 802.1AS, section 8.4.3). * * The exact definitions of the message timestamp point and * reference plane depends on the network medium and use case. * * For (g)PTP the media-specific message timestamp points and reference planes * are defined in the standard. In non-PTP contexts specific to Zephyr, * timestamps are measured relative to the same local clock but with a * context-specific message timestamp point and reference plane, defined below * per use case. * * A @em "LocalClock" is a freerunning clock, embedded into a well-defined * entity (e.g. a PTP Instance) and provides a common time to that entity * relative to an arbitrary epoch (IEEE 1855, section 3.1.26, IEEE 802.1AS, * section 3.16). * * In Zephyr, the local clock is usually any instance of a kernel system clock * driver, counter driver, RTC API driver or low-level counter/timer peripheral * (e.g. an ethernet peripheral with hardware timestamp support or a radio * timer) with sufficient precision for the context in which it is used. * * See IEEE 802.1AS, Annex B for specific performance requirements regarding * conformance of local clocks in the gPTP context. See IEEE 1588, Annex A, * section A5.4 for general performance requirements regarding PTP local clocks. * See IEEE 802.15.4-2020, section 15.7 for requirements in the context of * ranging applications and ibid., section 6.7.6 for the relation between guard * times and clock accuracy which again influence the precision required for * subprotocols like CSL, TSCH, RIT, etc. * * Applications that use timestamps across different subsystems or media must * ensure that they understand the definition of the respective reference planes * and interpret timestamps accordingly. Applications must further ensure that * timestamps are either all referenced to the same local clock or convert * between clocks based on sufficiently precise conversion algorithms. * * Timestamps may be measured on ingress (RX timestamps) or egress (TX * timestamps) of network messages. Timestamps can also be used to schedule a * network message to a well-defined point in time in the future at which it is * to be sent over the medium (timed TX). A future timestamp and a duration, * both referenced to the local clock, may be given to specify a time window at * which a network device should expect incoming messages (RX window). * * In Zephyr this timestamp structure is currently used in the following * contexts: * * gPTP for Full Duplex Point-to-Point IEEE 802.3 links (IEEE 802.1AS, * section 11): the reference plane and message timestamp points are as * defined in the standard. * * IEEE 802.15.4 timed TX and RX: Timestamps designate the point in time at * which the end of the last symbol of the start-of-frame delimiter (SFD) (or * equivalently, the start of the first symbol of the PHY header) is at the * local antenna. The standard also refers to this as the "RMARKER" (IEEE * 802.15.4-2020, section 6.9.1) or "symbol boundary" (ibid., section 6.5.2), * depending on the context. In the context of beacon timestamps, the * difference between the timestamp measurement plane and the reference plane * is defined by the MAC PIB attribute "macSyncSymbolOffset", ibid., section * 8.4.3.1, table 8-94. * * If further use cases are added to Zephyr using this timestamp structure, * their clock performance requirements, message timestamp points and reference * plane definition SHALL be added to the above list. */ struct net_ptp_time { /** Seconds encoded on 48 bits. */ union { struct { #ifdef CONFIG_LITTLE_ENDIAN uint32_t low; uint16_t high; uint16_t unused; #else uint16_t unused; uint16_t high; uint32_t low; #endif } _sec; uint64_t second; }; /** Nanoseconds. */ uint32_t nanosecond; }; #ifdef __cplusplus } #endif /** * @brief Generalized Precision Time Protocol Extended Timestamp format. * * @details This structure represents an extended timestamp according to the * Generalized Precision Time Protocol standard (IEEE 802.1AS), see section * 6.4.3.5. * * Seconds are encoded as 48 bits unsigned integer. Fractional nanoseconds are * encoded as 48 bits, their unit is 2*(-16) ns. * * A precise definition of PTP timestamps and their uses in Zephyr is given in * the description of @ref net_ptp_time. */ struct net_ptp_extended_time { /** Seconds encoded on 48 bits. */ union { struct { #ifdef CONFIG_LITTLE_ENDIAN uint32_t low; uint16_t high; uint16_t unused; #else uint16_t unused; uint16_t high; uint32_t low; #endif } _sec; uint64_t second; }; /** Fractional nanoseconds on 48 bits. */ union { struct { #ifdef CONFIG_LITTLE_ENDIAN uint32_t low; uint16_t high; uint16_t unused; #else uint16_t unused; uint16_t high; uint32_t low; #endif } _fns; uint64_t fract_nsecond; }; } __packed; /** * @brief Convert a PTP timestamp to a nanosecond precision timestamp, both * related to the local network reference clock. * * @note Only timestamps representing up to ~290 years can be converted to * nanosecond timestamps. Larger timestamps will return the maximum * representable nanosecond precision timestamp. * * @param ts the PTP timestamp * * @return the corresponding nanosecond precision timestamp */ static inline net_time_t net_ptp_time_to_ns(struct net_ptp_time *ts) { if (!ts) { return 0; } if (ts->second >= NET_TIME_SEC_MAX) { return NET_TIME_MAX; } return ((int64_t)ts->second * NSEC_PER_SEC) + ts->nanosecond; } /** * @brief Convert a nanosecond precision timestamp to a PTP timestamp, both * related to the local network reference clock. * * @param nsec a nanosecond precision timestamp * * @return the corresponding PTP timestamp */ static inline struct net_ptp_time ns_to_net_ptp_time(net_time_t nsec) { struct net_ptp_time ts; __ASSERT_NO_MSG(nsec >= 0); ts.second = nsec / NSEC_PER_SEC; ts.nanosecond = nsec % NSEC_PER_SEC; return ts; } /** * @} */ #endif /* ZEPHYR_INCLUDE_NET_PTP_TIME_H_ */