344 lines
7.9 KiB
C
344 lines
7.9 KiB
C
/*
|
|
* Copyright (c) 2017 Intel Corporation.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
* @brief Public functions for the Precision Time Protocol Stack.
|
|
*
|
|
*/
|
|
|
|
#ifndef ZEPHYR_INCLUDE_NET_GPTP_H_
|
|
#define ZEPHYR_INCLUDE_NET_GPTP_H_
|
|
|
|
/**
|
|
* @brief generic Precision Time Protocol (gPTP) support
|
|
* @defgroup gptp gPTP support
|
|
* @ingroup networking
|
|
* @{
|
|
*/
|
|
|
|
#include <net/net_core.h>
|
|
#include <net/ptp_time.h>
|
|
#include <stdbool.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/** @cond INTERNAL_HIDDEN */
|
|
|
|
#define GPTP_OFFSET_SCALED_LOG_VAR_UNKNOWN 0x436A
|
|
|
|
#define GPTP_PRIORITY1_NON_GM_CAPABLE 255
|
|
#define GPTP_PRIORITY1_GM_CAPABLE 248
|
|
#define GPTP_PRIORITY2_DEFAULT 248
|
|
|
|
/** @endcond */
|
|
|
|
/**
|
|
* @brief Scaled Nanoseconds.
|
|
*/
|
|
struct gptp_scaled_ns {
|
|
/** High half. */
|
|
s32_t high;
|
|
|
|
/** Low half. */
|
|
s64_t low;
|
|
} __packed;
|
|
|
|
/**
|
|
* @brief UScaled Nanoseconds.
|
|
*/
|
|
struct gptp_uscaled_ns {
|
|
/** High half. */
|
|
u32_t high;
|
|
|
|
/** Low half. */
|
|
u64_t low;
|
|
} __packed;
|
|
|
|
/** @cond INTERNAL_HIDDEN */
|
|
|
|
#if defined(CONFIG_NEWLIB_LIBC)
|
|
#include <math.h>
|
|
|
|
#define GPTP_POW2(exp) pow(2, exp)
|
|
#else
|
|
|
|
static inline double gptp_pow2(int exp)
|
|
{
|
|
double res;
|
|
|
|
if (exp >= 0) {
|
|
res = 1 << exp;
|
|
} else {
|
|
res = 1.0;
|
|
|
|
while (exp++) {
|
|
res /= 2;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
#define GPTP_POW2(exp) gptp_pow2(exp)
|
|
#endif
|
|
|
|
/* Pre-calculated constants */
|
|
/* 2^16 */
|
|
#define GPTP_POW2_16 65536.0
|
|
/* 2^41 */
|
|
#define GPTP_POW2_41 2199023255552.0
|
|
|
|
/* Message types. Event messages have BIT(3) set to 0, and general messages
|
|
* have that bit set to 1. IEEE 802.1AS chapter 10.5.2.2.2
|
|
*/
|
|
#define GPTP_SYNC_MESSAGE 0x00
|
|
#define GPTP_DELAY_REQ_MESSAGE 0x01
|
|
#define GPTP_PATH_DELAY_REQ_MESSAGE 0x02
|
|
#define GPTP_PATH_DELAY_RESP_MESSAGE 0x03
|
|
#define GPTP_FOLLOWUP_MESSAGE 0x08
|
|
#define GPTP_DELAY_RESP_MESSAGE 0x09
|
|
#define GPTP_PATH_DELAY_FOLLOWUP_MESSAGE 0x0a
|
|
#define GPTP_ANNOUNCE_MESSAGE 0x0b
|
|
#define GPTP_SIGNALING_MESSAGE 0x0c
|
|
#define GPTP_MANAGEMENT_MESSAGE 0x0d
|
|
|
|
#define GPTP_IS_EVENT_MSG(msg_type) (!((msg_type) & BIT(3)))
|
|
|
|
#define GPTP_CLOCK_ID_LEN 8
|
|
|
|
/** @endcond */
|
|
|
|
/**
|
|
* @brief Port Identity.
|
|
*/
|
|
struct gptp_port_identity {
|
|
/** Clock identity of the port. */
|
|
u8_t clk_id[GPTP_CLOCK_ID_LEN];
|
|
|
|
/** Number of the port. */
|
|
u16_t port_number;
|
|
} __packed;
|
|
|
|
struct gptp_flags {
|
|
union {
|
|
/** Byte access. */
|
|
u8_t octets[2];
|
|
|
|
/** Whole field access. */
|
|
u16_t all;
|
|
};
|
|
} __packed;
|
|
|
|
struct gptp_hdr {
|
|
/** Type of the message. */
|
|
u8_t message_type:4;
|
|
|
|
/** Transport specific, always 1. */
|
|
u8_t transport_specific:4;
|
|
|
|
/** Version of the PTP, always 2. */
|
|
u8_t ptp_version:4;
|
|
|
|
/** Reserved field. */
|
|
u8_t reserved0:4;
|
|
|
|
/** Total length of the message from the header to the last TLV. */
|
|
u16_t message_length;
|
|
|
|
/** Domain number, always 0. */
|
|
u8_t domain_number;
|
|
|
|
/** Reserved field. */
|
|
u8_t reserved1;
|
|
|
|
/** Message flags. */
|
|
struct gptp_flags flags;
|
|
|
|
/** Correction Field. The content depends of the message type. */
|
|
s64_t correction_field;
|
|
|
|
/** Reserved field. */
|
|
u32_t reserved2;
|
|
|
|
/** Port Identity of the sender. */
|
|
struct gptp_port_identity port_id;
|
|
|
|
/** Sequence Id. */
|
|
u16_t sequence_id;
|
|
|
|
/** Control value. Sync: 0, Follow-up: 2, Others: 5. */
|
|
u8_t control;
|
|
|
|
/** Message Interval in Log2 for Sync and Announce messages. */
|
|
s8_t log_msg_interval;
|
|
} __packed;
|
|
|
|
/** @cond INTERNAL_HIDDEN */
|
|
|
|
#define GPTP_GET_CURRENT_TIME_USCALED_NS(port, uscaled_ns_ptr) \
|
|
do { \
|
|
(uscaled_ns_ptr)->low = \
|
|
gptp_get_current_time_nanosecond(port) << 16; \
|
|
(uscaled_ns_ptr)->high = 0; \
|
|
} while (false)
|
|
|
|
/** @endcond */
|
|
|
|
/**
|
|
* @typedef gptp_phase_dis_callback_t
|
|
* @brief Define callback that is called after a phase discontinuity has been
|
|
* sent by the grandmaster.
|
|
* @param "u8_t *gm_identity" A pointer to first element of a
|
|
* ClockIdentity array. The size of the array is GPTP_CLOCK_ID_LEN.
|
|
* @param "u16_t *gm_time_base" A pointer to the value of timeBaseIndicator
|
|
* of the current grandmaster.
|
|
* @param "struct scaled_ns *last_gm_ph_change" A pointer to the value of
|
|
* lastGmPhaseChange received from grandmaster.
|
|
* @param "double *last_gm_freq_change" A pointer to the value of
|
|
* lastGmFreqChange received from the grandmaster.
|
|
*/
|
|
typedef void (*gptp_phase_dis_callback_t)(
|
|
u8_t *gm_identity,
|
|
u16_t *time_base,
|
|
struct gptp_scaled_ns *last_gm_ph_change,
|
|
double *last_gm_freq_change);
|
|
|
|
/**
|
|
* @brief Phase discontinuity callback structure.
|
|
*
|
|
* Stores the phase discontinuity callback information. Caller must make sure
|
|
* that the variable pointed by this is valid during the lifetime of
|
|
* registration. Typically this means that the variable cannot be
|
|
* allocated from stack.
|
|
*/
|
|
struct gptp_phase_dis_cb {
|
|
/** Node information for the slist. */
|
|
sys_snode_t node;
|
|
|
|
/** Phase discontinuity callback. */
|
|
gptp_phase_dis_callback_t cb;
|
|
};
|
|
|
|
/**
|
|
* @brief ClockSourceTime.invoke function parameters
|
|
*
|
|
* Parameters passed by ClockSourceTime.invoke function.
|
|
*/
|
|
struct gptp_clk_src_time_invoke_params {
|
|
/** Frequency change on the last Time Base Indicator Change. */
|
|
double last_gm_freq_change;
|
|
|
|
/** The time this function is invoked. */
|
|
struct net_ptp_extended_time src_time;
|
|
|
|
/** Phase change on the last Time Base Indicator Change. */
|
|
struct gptp_scaled_ns last_gm_phase_change;
|
|
|
|
/** Time Base - changed only if Phase or Frequency changes. */
|
|
u16_t time_base_indicator;
|
|
};
|
|
|
|
/**
|
|
* @brief Register a phase discontinuity callback.
|
|
*
|
|
* @param phase_dis Caller specified handler for the callback.
|
|
* @param cb Callback to register.
|
|
*/
|
|
void gptp_register_phase_dis_cb(struct gptp_phase_dis_cb *phase_dis,
|
|
gptp_phase_dis_callback_t cb);
|
|
|
|
/**
|
|
* @brief Unregister a phase discontinuity callback.
|
|
*
|
|
* @param phase_dis Caller specified handler for the callback.
|
|
*/
|
|
void gptp_unregister_phase_dis_cb(struct gptp_phase_dis_cb *phase_dis);
|
|
|
|
/**
|
|
* @brief Call a phase discontinuity callback function.
|
|
*/
|
|
void gptp_call_phase_dis_cb(void);
|
|
|
|
/**
|
|
* @brief Get gPTP time.
|
|
*
|
|
* @param slave_time A pointer to structure where timestamp will be saved.
|
|
* @param gm_present A pointer to a boolean where status of the
|
|
* presence of a grand master will be saved.
|
|
*
|
|
* @return Error code. 0 if no error.
|
|
*/
|
|
int gptp_event_capture(struct net_ptp_time *slave_time, bool *gm_present);
|
|
|
|
/**
|
|
* @brief Utility function to print clock id to a user supplied buffer.
|
|
*
|
|
* @param clk_id Clock id
|
|
* @param output Output buffer
|
|
* @param output_len Output buffer len
|
|
*
|
|
* @return Pointer to output buffer
|
|
*/
|
|
char *gptp_sprint_clock_id(const u8_t *clk_id, char *output,
|
|
size_t output_len);
|
|
|
|
/**
|
|
* @typedef gptp_port_cb_t
|
|
* @brief Callback used while iterating over gPTP ports
|
|
*
|
|
* @param port Port number
|
|
* @param iface Pointer to network interface
|
|
* @param user_data A valid pointer to user data or NULL
|
|
*/
|
|
typedef void (*gptp_port_cb_t)(int port, struct net_if *iface,
|
|
void *user_data);
|
|
|
|
/**
|
|
* @brief Go through all the gPTP ports and call callback for each of them.
|
|
*
|
|
* @param cb User-supplied callback function to call
|
|
* @param user_data User specified data
|
|
*/
|
|
void gptp_foreach_port(gptp_port_cb_t cb, void *user_data);
|
|
|
|
/**
|
|
* @brief Get gPTP domain.
|
|
* @details This contains all the configuration / status of the gPTP domain.
|
|
*
|
|
* @return Pointer to domain or NULL if not found.
|
|
*/
|
|
struct gptp_domain *gptp_get_domain(void);
|
|
|
|
/**
|
|
* @brief This interface is used by the ClockSource entity to provide time to
|
|
* the ClockMaster entity of a time-aware system.
|
|
*
|
|
* @param arg Current state and parameters of the ClockSource entity.
|
|
*/
|
|
void gptp_clk_src_time_invoke(struct gptp_clk_src_time_invoke_params *arg);
|
|
|
|
/**
|
|
* @brief Return pointer to gPTP packet header in network packet.
|
|
*
|
|
* @param pkt Network packet (received or sent)
|
|
*
|
|
* @return Pointer to gPTP header.
|
|
*/
|
|
struct gptp_hdr *gptp_get_hdr(struct net_pkt *pkt);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
#endif /* ZEPHYR_INCLUDE_NET_GPTP_H_ */
|