flexPTP 1.0
An IEEE 1588 PTP implementation designed for microcontrollers
Loading...
Searching...
No Matches
ptp_core.c
Go to the documentation of this file.
1/* (C) AndrĂ¡s Wiesner, 2020-2022 */
2
3#include "ptp_core.h"
4
5#include <math.h>
6#include <stdint.h>
7#include <string.h>
8
9#include "FreeRTOS.h"
10
11#include "common.h"
12#include "event.h"
13#include "logging.h"
14#include "master.h"
15#include "portmacro.h"
16#include "slave.h"
17#include "timers.h"
18
19#include "bmca.h"
20#include "cli_cmds.h"
21#include "clock_utils.h"
22#include "format_utils.h"
23#include "msg_utils.h"
25#include "ptp_defs.h"
26#include "ptp_types.h"
27#include "settings_interface.h"
28#include "stats.h"
29#include "task_ptp.h"
30#include "timeutils.h"
31
32#include <flexptp_options.h>
33
34// --------------------------------------
35
36// provide our own MIN implementation
37#ifdef MIN
38#undef MIN
39#endif
40
41#define MIN(a, b) (((a) < (b)) ? (a) : (b))
42
44// global state
45PtpCoreState gPtpCoreState;
46#define S (gPtpCoreState)
47
48const TimestampI zeroTs = {0, 0}; // a zero timestamp
50
51// --------------------------------------
52
58static void ptp_heartbeat_tmr_cb(TimerHandle_t timer) {
59 PtpCoreEvent event = {.code = PTP_CEV_HEARTBEAT, .w = 0, .dw = 0};
60 ptp_event_enqueue(&event);
61}
62
67 // create smbc timer
68 S.timers.heartbeat = xTimerCreate("ptp_heartbeat", pdMS_TO_TICKS(PTP_HEARTBEAT_TICKRATE_MS), // timeout
69 true, // timer operates in repeat mode
70 NULL, // ID
71 ptp_heartbeat_tmr_cb); // callback-function
72}
73
78 xTimerStop(S.timers.heartbeat, 0);
79 xTimerDelete(S.timers.heartbeat, 0);
80}
81
83 xTimerStart(S.timers.heartbeat, 0);
84}
85
87 xTimerStop(S.timers.heartbeat, 0);
88}
89
90// --------------------------------------
91
92static void ptp_common_init(const uint8_t *hwa) {
93 // create clock identity
95
96 // seed the randomizer
97 srand(S.hwoptions.clockIdentity);
98
99 // reset options
100 nsToTsI(&S.hwoptions.offset, PTP_DEFAULT_SERVO_OFFSET);
101
102 // initialize hardware
104
105 // initialize controller
107
108 // initialize the heartbeat timer
110}
111
112// initialize PTP module
113void ptp_init(const uint8_t *hwa) {
114 /* ---- COMMON ----- */
115 ptp_common_init(hwa);
116
117 /* ----- SBMC ------ */
119
120 /* ----- SLAVE ----- */
122
123 /* ---- MASTER --- */
125
126 // ---------------------
127
128 ptp_reset(); // reset all PTP systems
129
130#ifdef CLI_REG_CMD
131 // register cli commands
133#endif // CLI_REG_CMD
134
135 // dispatch INIT_DONE event
137}
138
139// deinit PTP module
141 /* ---- COMMON ----- */
142
143 // remove the heartbeat timer
145
146#ifdef CLI_REG_CMD
147 // remove cli commands
149#endif // CLI_REG_CMD
150
151 // deinitialize controller
153
154 /* ----- SBMC ------ */
156
157 /* ----- SLAVE ----- */
159
160 /* ---- MASTER --- */
162}
163
164// reset PTP subsystem
165void ptp_reset() {
166 // pause the heartbeat timer
168
169 // ------------------------
170
171 /* ---- COMMON ---- */
172
173 // reset subsystem states...
174 S.hwclock.addend = PTP_ADDEND_INIT; // HW clock state
175 PTP_SET_ADDEND(S.hwclock.addend);
176 memset(&S.network, 0, sizeof(PtpNetworkState)); // network state
177
178 // reset controller
180
181 // reinitialize the Network Stack Driver
183
184 // reset statistics
186
187 // reset common functionality
189
190 /* ---- SBMC ----- */
192
193 /* ---- SLAVE ---- */
195
196 /* ---- MASTER --- */
198
199 // ------------------------
200
201 // resume the heartbeat timer
203
204 // dispatch RESET event
206}
207
208// packet processing
210 PtpHeader header;
211
212 // header readout
213 ptp_extract_header(&header, pRawMsg->data);
214
215 // consider only messages in our domain
216 if (header.domainNumber != S.profile.domainNumber ||
217 header.transportSpecific != S.profile.transportSpecific) {
218 return;
219 }
220
221 // process Announce messages and halt further processing
222 PtpMessageType mt = header.messageType;
223 if (mt == PTP_MT_Announce) {
224 PtpMasterProperties newMstProp;
225 ptp_extract_announce_message(&newMstProp, pRawMsg->data);
226 ptp_handle_announce_msg(&newMstProp, &header);
227 PTP_IUEV(PTP_UEV_ANNOUNCE_RECVED); // dispatch ANNOUNCE_RECVED event
228 return;
229 }
230
231 // PDelay_Req messages should always be processed
232 if ((header.messageType == PTP_MT_PDelay_Req) && (S.profile.delayMechanism == PTP_DM_P2P)) {
233 PTP_IUEV(PTP_UEV_PDELAY_REQ_RECVED); // dispatch PDELAY_REQ_RECVED event
234 ptp_send_pdelay_resp(pRawMsg); // sent the PDelay_Resp message
235 PTP_IUEV(PTP_UEV_PDELAY_RESP_SENT); // dispatch PDELAY_RESP_SENT event
236 return;
237 }
238
239 // if operating in slave mode
240 PtpBmcaFsmState bmcaState = S.bmca.state;
241 if (bmcaState == PTP_BMCA_SLAVE) {
242 ptp_slave_process_message(pRawMsg, &header);
243 return;
244 } else if (bmcaState == PTP_BMCA_MASTER) { // if operating in Master mode
245 ptp_master_process_message(pRawMsg, &header);
246 return;
247 }
248}
249
250void ptp_process_event(const PtpCoreEvent *event) {
251 switch (event->code) {
252 case PTP_CEV_HEARTBEAT: { // heartbeat event
256 } break;
258 PtpBmcaFsmState bmcaState = event->w.w;
259 if (bmcaState == PTP_BMCA_SLAVE) {
261 } else if (bmcaState == PTP_BMCA_MASTER) {
263 } else {
266 }
267
268 // dispatch BMCA_STATE_CHANGED event
270 }
271 default:
272 break;
273 }
274}
275
276// -----------------------------------------------
277
279 S.slave.syncCb = syncCb;
280}
281
283 S.userEventCb = userEventCb;
284}
void ptp_bmca_destroy()
Definition: bmca.c:205
void ptp_bmca_tick()
Definition: bmca.c:72
void ptp_bmca_init()
Definition: bmca.c:191
void ptp_bmca_reset()
Definition: bmca.c:209
void ptp_handle_announce_msg(PtpAnnounceBody *pAnn, PtpHeader *pHeader)
Definition: bmca.c:135
This module implements the Best Master Clock Algorithm.
void ptp_register_cli_commands()
Definition: cli_cmds.c:353
void ptp_remove_cli_commands()
Definition: cli_cmds.c:376
This module handles and registers CLI commands. Commands:
void ptp_create_clock_identity(const uint8_t *hwa)
Definition: clock_utils.c:25
This module defines clock identity related operations.
void ptp_common_reset()
Definition: common.c:156
void ptp_send_pdelay_resp(const RawPtpMessage *pMsg)
Definition: common.c:91
This module defines messaging functions for both the slave and master modules.
In this module are the core and user events defined.
@ PTP_UEV_RESET_DONE
The flexPTP module has been reset.
Definition: event.h:42
@ PTP_UEV_PDELAY_RESP_SENT
A PDelay_Resp had been sent (master/slave)
Definition: event.h:55
@ PTP_UEV_INIT_DONE
The flexPTP core has been initialized.
Definition: event.h:41
@ PTP_UEV_BMCA_STATE_CHANGED
The BMCA state has changed.
Definition: event.h:64
@ PTP_UEV_ANNOUNCE_RECVED
An Announce message has been received (master/slave)
Definition: event.h:59
@ PTP_UEV_PDELAY_REQ_RECVED
A PDelay_Req had been received (master/slave)
Definition: event.h:52
#define PTP_IUEV(uev)
Definition: event.h:77
@ PTP_CEV_HEARTBEAT
Definition: event.h:15
@ PTP_CEV_BMCA_STATE_CHANGED
Definition: event.h:16
#define PTP_SET_ADDEND(addend)
#define PTP_HW_INIT(increment, addend)
#define PTP_SERVO_DEINIT()
#define PTP_SERVO_RESET()
#define PTP_SERVO_INIT()
#define PTP_INCREMENT_NSEC
This module defines format conversion functions between network and host byte order and conversion fu...
This module handles various logging capabilities.
void ptp_master_disable()
Definition: master.c:417
void ptp_master_enable()
Definition: master.c:393
void ptp_master_tick()
Definition: master.c:421
void ptp_master_reset()
Definition: master.c:373
void ptp_master_init()
Definition: master.c:364
void ptp_master_destroy()
Definition: master.c:369
void ptp_master_process_message(RawPtpMessage *pRawMsg, PtpHeader *pHeader)
Definition: master.c:304
This module implements the master clock functionality.
void ptp_extract_header(PtpHeader *pHeader, const void *pPayload)
Definition: msg_utils.c:55
void ptp_extract_announce_message(PtpAnnounceBody *pAnnounce, void *pPayload)
Definition: msg_utils.c:122
This module defines functions that deal with actual PTP messages; they can extract or insert headers,...
This file is a header for the employed Network Stack Driver (NSD). A NSD must define ALL four functio...
void ptp_nsd_init(PtpTransportType tp, PtpDelayMechanism dm)
Definition: nsd_etherlib.c:50
void ptp_deinit()
Definition: ptp_core.c:140
void ptp_process_event(const PtpCoreEvent *event)
Definition: ptp_core.c:250
void ptp_init(const uint8_t *hwa)
Definition: ptp_core.c:113
static void ptp_common_init(const uint8_t *hwa)
Definition: ptp_core.c:92
void ptp_process_packet(RawPtpMessage *pRawMsg)
Definition: ptp_core.c:209
void ptp_set_sync_callback(PtpSyncCallback syncCb)
Definition: ptp_core.c:278
void ptp_reset()
Definition: ptp_core.c:165
static void ptp_create_heartbeat_tmr()
Definition: ptp_core.c:66
static void ptp_start_heartbeat_tmr()
Definition: ptp_core.c:82
void ptp_set_user_event_callback(PtpUserEventCallback userEventCb)
Definition: ptp_core.c:282
static void ptp_stop_heartbeat_tmr()
Definition: ptp_core.c:86
static void ptp_heartbeat_tmr_cb(TimerHandle_t timer)
Definition: ptp_core.c:58
static void ptp_remove_heartbeat_tmr()
Definition: ptp_core.c:77
Core of the PTP implementation. Defines functions for message processing, clock tuning,...
In here reside a multitude of fundamental PTP-related constants and definitions.
#define PTP_HEARTBEAT_TICKRATE_MS
Heartbeat ticking period.
Definition: ptp_defs.h:69
#define PTP_DEFAULT_SERVO_OFFSET
Default servo offset in nanoseconds.
Definition: ptp_defs.h:81
#define PTP_ADDEND_INIT
Initial addend value.
Definition: ptp_defs.h:63
This module defines the fundamental PTP message and state machine type, flags, bitfields and the PTP ...
void(* PtpUserEventCallback)(PtpUserEventCode uev)
Definition: ptp_types.h:452
void(* PtpSyncCallback)(int64_t time_error, const PtpSyncCycleData *pSCD, uint32_t freqCodeWord)
Definition: ptp_types.h:447
PtpBmcaFsmState
Definition: ptp_types.h:284
@ PTP_BMCA_MASTER
Definition: ptp_types.h:288
@ PTP_BMCA_SLAVE
Definition: ptp_types.h:289
PtpMessageType
PTP packet type enumeration.
Definition: ptp_types.h:29
@ PTP_MT_PDelay_Req
Peer Delay Request.
Definition: ptp_types.h:32
@ PTP_MT_Announce
Announce.
Definition: ptp_types.h:37
@ PTP_DM_P2P
Peer-to-Peer Delay Mechanism.
Definition: ptp_types.h:138
PtpDelayMechanism ptp_get_delay_mechanism()
PtpTransportType ptp_get_transport_type()
This module features functions to tweak around the PTP engine's almost every property.
void ptp_slave_destroy()
Definition: slave.c:365
void ptp_slave_init()
Definition: slave.c:357
void ptp_slave_process_message(RawPtpMessage *pRawMsg, PtpHeader *pHeader)
Definition: slave.c:200
void ptp_slave_enable()
Definition: slave.c:408
void ptp_slave_tick()
Definition: slave.c:381
void ptp_slave_reset()
Definition: slave.c:369
void ptp_slave_disable()
Definition: slave.c:416
This module implements the slave clock functionality.
void ptp_clear_stats()
Definition: stats.c:17
This is the statistics module that gathers data of the operating PTP-engine.
Contents of a PTP Announce message without the common PTP header.
Definition: ptp_types.h:236
uint16_t code
Event code.
Definition: event.h:21
Giant PTP core state object.
Definition: ptp_types.h:457
PTP message header structure.
Definition: ptp_types.h:73
uint8_t messageType
ID.
Definition: ptp_types.h:75
uint8_t domainNumber
Domain.
Definition: ptp_types.h:86
uint8_t transportSpecific
Transport Specific.
Definition: ptp_types.h:76
Network state.
Definition: ptp_types.h:432
Raw PTP message structure.
Definition: ptp_types.h:162
uint8_t data[(128)]
raw packet data
Definition: ptp_types.h:173
Timestamp (signed)
Definition: timeutils.h:29
bool ptp_event_enqueue(const PtpCoreEvent *event)
Definition: task_ptp.c:136
The entry point of the whole PTP-implementation. Calling reg_task_ptp() initializes the PTP-engine,...
TimestampI * nsToTsI(TimestampI *r, int64_t ns)
Definition: timeutils.c:61
This module defines storage classes for timestamps and operations on time values.