flexPTP 1.0
An IEEE 1588 PTP implementation designed for microcontrollers
Loading...
Searching...
No Matches
slave.c
Go to the documentation of this file.
1#include "slave.h"
2
3#include <math.h>
4#include <string.h>
5#include <stdlib.h>
6#include <inttypes.h>
7
8#include "common.h"
9
10#include "format_utils.h"
11#include "msg_utils.h"
12#include "ptp_types.h"
13#include "settings_interface.h"
14#include "stats.h"
15#include "task_ptp.h"
16#include "timeutils.h"
17
18#include "ptp_core.h"
19#include "ptp_defs.h"
20
21#include "minmax.h"
22
24#define S (gPtpCoreState)
26
27// --------------
28
34static void ptp_tune_clock(float tuning_ppb) {
35#ifdef PTP_ADDEND_INTERFACE
36 int64_t compAddend = (int64_t)S.hwclock.addend + (int64_t)(tuning_ppb * PTP_ADDEND_CORR_PER_PPB_F); // compute addend value
37 S.hwclock.addend = MIN(compAddend, 0xFFFFFFFF); // limit to 32-bit range
38 PTP_SET_ADDEND(S.hwclock.addend); // write addend into hardware
39#elif defined(PTP_HLT_INTERFACE)
40 S.hwclock.tuning_ppb += tuning_ppb;
41 PTP_SET_TUNING(S.hwclock.tuning_ppb);
42#endif
43}
44
45#define PTP_FC_SKEW_CORRECTION_CYCLES (4)
46#define PTP_FC_TIME_CORRECTION_CYCLES (1)
47#define PTP_FC_TIME_PROPAGATION_CYCLES (2) //< Fast compensation: no. of time propagation cycles
48
53 // don't do any processing if no delay_request data is present
54 if (!nonZeroI(&S.network.meanPathDelay)) {
55 return;
56 }
57
58 // timestamps and time intervals
59 TimestampI d, syncMa, syncSl, delReqSl, delReqMa;
60
61 // copy timestamps to assign them with meaningful names
62 syncMa = S.slave.scd.t[T1];
63 syncSl = S.slave.scd.t[T2];
64 delReqSl = S.slave.scd.t[T3];
65 delReqMa = S.slave.scd.t[T4];
66
67 // log timestamps (if enabled)
68 if (S.profile.delayMechanism == PTP_DM_E2E) {
69 CLILOG(S.logging.timestamps,
70 "seqID: %u\n"
71 "T1: %d.%09d <- Sync TX (master)\n"
72 "T2: %d.%09d <- Sync RX (slave) \n"
73 "T3: %d.%09d <- Del_Req TX (slave) \n"
74 "T4: %d.%09d <- Del_Req RX (master)\n\n",
75 (uint32_t)S.slave.messaging.sequenceID,
76 (int32_t)syncMa.sec, syncMa.nanosec,
77 (int32_t)syncSl.sec, syncSl.nanosec,
78 (int32_t)delReqSl.sec, delReqSl.nanosec,
79 (int32_t)delReqMa.sec, delReqMa.nanosec);
80 } else if (S.profile.delayMechanism == PTP_DM_P2P) {
81 CLILOG(S.logging.timestamps,
82 "seqID: %u\n"
83 "T1: %d.%09d <- Sync TX (master)\n"
84 "T2: %d.%09d <- Sync RX (slave)\n"
85 "t1: %d.%09d <- PDel_Req TX (our clock)\n"
86 "t2: %d.%09d <- PDel_Req RX (their clock)\n"
87 "t3: %d.%09d <- PDel_Resp TX (their clock)\n"
88 "t4: %d.%09d <- PDel_Resp RX (our clock)\n\n",
89 (uint32_t)S.slave.messaging.sequenceID,
90 (int32_t)S.slave.scd.t[0].sec, S.slave.scd.t[0].nanosec,
91 (int32_t)S.slave.scd.t[1].sec, S.slave.scd.t[1].nanosec,
92 (int32_t)S.slave.scd.t[2].sec, S.slave.scd.t[2].nanosec,
93 (int32_t)S.slave.scd.t[3].sec, S.slave.scd.t[3].nanosec,
94 (int32_t)S.slave.scd.t[4].sec, S.slave.scd.t[4].nanosec,
95 (int32_t)S.slave.scd.t[5].sec, S.slave.scd.t[5].nanosec);
96 }
97
98 // ------------------------------
99
100 // variable for later substraction of summed correction fields
101 TimestampI cf = {0, 0};
102 nsToTsI(&cf, S.slave.scd.cf[T1] + S.slave.scd.cf[T2]);
103
104 // compute difference between master and slave clocks
105 subTime(&d, &syncSl, &syncMa); // t2 - t1 ...
106 subTime(&d, &d, &S.network.meanPathDelay); // - MPD
107 subTime(&d, &d, &cf); // - CF of (Sync + Follow_Up)
108
109 // substract offset
110 subTime(&d, &d, &S.hwoptions.offset);
111
112 // normalize time difference (eliminate malformed time value issues)
113 normTime(&d);
114
115 // ------------------------------
116
117 // fill the previous state variables
118 if (!nonZeroI(&S.slave.prevSyncMa) || !nonZeroI(&S.slave.prevSyncSl)) {
119 goto retain_cycle_data;
120 }
121
122 // ------------------------------
123
124 // determine the Sync period
125 TimestampI measSyncPeriod;
126 subTime(&measSyncPeriod, &syncMa, &(S.slave.prevSyncMa));
127 int64_t measSyncPeriod_ns = nsI(&measSyncPeriod);
128
129 // ------------------------------
130
131 // if time difference is greater than the predefined threshold then jump the clock
132 int64_t d_ns = nsI(&d);
133 PtpFastCompState fcs = S.slave.fastCompState;
134 if ((llabs(d_ns) > S.slave.coarseLimit) || (fcs != PTP_FC_IDLE)) {
135 if (fcs == PTP_FC_IDLE) {
136 // reset the servo
138
139 // print info
140 CLILOG(S.logging.info, "Time difference has exceeded the coarse correction threshold [%" __PRI64_PREFIX "dns], compensation commenced!\n", d_ns);
141 }
142
143 uint8_t fccntr = S.slave.fastCompCntr;
144 switch (fcs) {
145 case PTP_FC_IDLE:
147 fccntr = 0;
149 if (fccntr == PTP_FC_SKEW_CORRECTION_CYCLES) {
151 fccntr = 0;
152 }
153 break;
155 if (fccntr == PTP_FC_TIME_CORRECTION_CYCLES) {
157 fccntr = 0;
158 }
159 break;
161 if (fccntr == PTP_FC_TIME_PROPAGATION_CYCLES) {
162 fcs = PTP_FC_IDLE;
163 fccntr = 0;
164 }
165 break;
166 }
167
168 // skew correction
169 if (fcs == PTP_FC_SKEW_CORRECTION) {
170 // calculate clock skew
171 TimestampI dt2;
172 subTime(&dt2, &syncSl, &S.slave.prevSyncSl);
173 int64_t dt2_ns = nsI(&dt2);
174 double skew = (double)(dt2_ns - measSyncPeriod_ns) / (double)(measSyncPeriod_ns);
175 double skew_compensation_ppb = -skew * 1E+09;
176
177 // compensate the clock skew
178 ptp_tune_clock(skew_compensation_ppb);
179
180 // log skew compensation
181 CLILOG(S.logging.info, "[%u/%u] Skew compensation: % 6.4f ppb\n", fccntr + 1, PTP_FC_SKEW_CORRECTION_CYCLES, skew_compensation_ppb);
182 } else if (fcs == PTP_FC_TIME_CORRECTION) { // time correction
183 // compensate time error
184 TimestampU tu;
185 PTP_HW_GET_TIME(&tu);
186 uint64_t t_ns = nsU(&tu);
187 t_ns -= d_ns;
188 TimestampI ti;
189 nsToTsI(&ti, t_ns);
190 PTP_SET_CLOCK((uint32_t)ti.sec, ti.nanosec);
191
192 // log time compensation
193 CLILOG(S.logging.info, "[%u/%u] Time compensation: %" __PRI64_PREFIX "d ns\n", fccntr + 1, PTP_FC_TIME_CORRECTION_CYCLES, d_ns);
194 } else if (fcs == PTP_FC_TIME_CORRECTION_PROPAGATION) {
195 CLILOG(S.logging.info, "[%u/%u] Waiting for time compensation to propagate.\n", fccntr + 1, PTP_FC_TIME_PROPAGATION_CYCLES);
196 }
197
198 // maintain FC state
199 S.slave.fastCompState = fcs;
200 S.slave.fastCompCntr = fccntr + 1;
201
202 // retain sync cycle data
203 goto retain_cycle_data;
204 }
205
206 // ------------------------------
207
208 // prepare data to pass to the controller
209 PtpServoAuxInput saux = {S.slave.scd,
210 S.slave.messaging.logSyncPeriod,
211 S.slave.messaging.syncPeriodMs,
212 measSyncPeriod_ns};
213
214 // run controller
215 float corr_ppb = PTP_SERVO_RUN(nsI(&d), &saux);
216
217 // set clock tuning
218 ptp_tune_clock(corr_ppb);
219
220 // collect statistics
222
223 // log on cli (if enabled)
224#ifdef PTP_ADDEND_INTERFACE
225 int32_t d_ticks = tsToTick(&d, PTP_CLOCK_TICK_FREQ_HZ);
226 CLILOG(S.logging.def, "%d %09d %d %09d %d " PTP_COLOR_BYELLOW "% 9d" PTP_COLOR_RESET " % 9d % 12u % 8.4f % 9" __PRI64_PREFIX "d % 9" __PRI64_PREFIX "u\n",
227 (int32_t)syncMa.sec, syncMa.nanosec, (int32_t)delReqMa.sec, delReqMa.nanosec,
228 (int32_t)d.sec, d.nanosec, d_ticks,
229 S.hwclock.addend, corr_ppb, nsI(&S.network.meanPathDelay), (uint64_t)measSyncPeriod_ns);
230#elif defined(PTP_HLT_INTERFACE)
231 CLILOG(S.logging.def, "%d %09d %d %09d %d " PTP_COLOR_BYELLOW "% 9d" PTP_COLOR_RESET " % 8.4f % 8.4f % 9" __PRI64_PREFIX "d % 9" __PRI64_PREFIX "u\n",
232 (int32_t)syncMa.sec, syncMa.nanosec, (int32_t)delReqMa.sec, delReqMa.nanosec,
233 (int32_t)d.sec, d.nanosec,
234 S.hwclock.tuning_ppb, corr_ppb, nsI(&S.network.meanPathDelay), (uint64_t)measSyncPeriod_ns);
235#endif
236
237 // call sync callback if defined
238 if (S.slave.syncCb != NULL) {
239#ifdef PTP_ADDEND_INTERFACE
240 S.slave.syncCb(nsI(&d), &S.slave.scd, S.hwclock.addend);
241#elif defined(PTP_HLT_INTERFACE)
242 S.slave.syncCb(nsI(&d), &S.slave.scd, S.hwclock.tuning_ppb);
243#endif
244 }
245
246 // ---------------------
247
248retain_cycle_data:
249 S.slave.prevSyncMa = syncMa;
250 S.slave.prevSyncSl = syncSl;
251 S.slave.prevTimeError = d;
252}
253
259 // send Delay_Req message
260 if (S.profile.logDelayReqPeriod == PTP_LOGPER_SYNCMATCHED) {
261 // send (P)Delay_Req message
263
264 // dispatch (P)DELAY_REQ_SENT event
265 PTP_IUEV((S.profile.delayMechanism == PTP_DM_E2E) ? PTP_UEV_DELAY_REQ_SENT : PTP_UEV_PDELAY_REQ_SENT);
266 }
267
268 // jump the clock if error is way too big...
269 TimestampI d;
270 subTime(&d, &S.slave.scd.t[T2], &S.slave.scd.t[T1]);
271 if (d.sec != 0) {
272 PTP_SET_CLOCK((int32_t)S.slave.scd.t[T1].sec, S.slave.scd.t[T1].nanosec);
273 }
274
275 // run servo only if issuing Delay_Requests is not syncmatched
276 if (S.profile.logDelayReqPeriod != PTP_LOGPER_SYNCMATCHED) {
278 }
279}
280
287static void ptp_commence_p2p_correction(uint32_t pdelRespSeqId) {
288 // compute mean path delay
289 ptp_compute_mean_path_delay_p2p(S.slave.scd.t + 2, S.slave.scd.cf + 2, &S.network.meanPathDelay);
290
291 // store last response ID
292 S.slave.messaging.lastRespondedDelReqId = pdelRespSeqId;
293
294 if (S.profile.logDelayReqPeriod == PTP_LOGPER_SYNCMATCHED) {
296 }
297}
298
299// packet processing
301 PtpMessageType mt = pHeader->messageType;
302 PtpDelayMechanism dm = S.profile.delayMechanism;
303
304 // process non-Announce messages
305 if (mt == PTP_MT_Sync || mt == PTP_MT_Follow_Up) {
306 switch (S.slave.messaging.m2sState) {
307 // wait for Sync message
308 case SIdle: {
309 // switch into next state if Sync packet has arrived
310 if (mt == PTP_MT_Sync) {
311 // save sync interval
312 S.slave.messaging.logSyncPeriod = pHeader->logMessagePeriod;
313 S.slave.messaging.syncPeriodMs = ptp_logi2ms(pHeader->logMessagePeriod);
314
315 // MSG("%d\n", header.logMessagePeriod);
316
317 // save reception time
318 S.slave.scd.t[T2] = pRawMsg->ts;
319
320 // switch to next syncState
321 S.slave.messaging.sequenceID = pHeader->sequenceID;
322
323 // save correction field
324 S.slave.scd.cf[T1] = pHeader->correction_ns;
325
326 // handle two step/one step messaging
327 if (pHeader->flags.PTP_TWO_STEP) {
328 S.slave.messaging.m2sState = SWaitFollowUp;
329 } else {
330 ptp_extract_timestamps(&S.slave.scd.t[T1], pRawMsg->data, 1); // extract t1
331 S.slave.scd.cf[T2] = 0; // clear Follow_Up correction field, since no Follow_Up is expected
332 ptp_commence_e2e_correction(); // commence executing the E2E correction
333 }
334
335 // dispatch SYNC_RECVED event
337 }
338
339 break;
340 }
341 // wait for Follow_Up message
342 case SWaitFollowUp:
343 if (mt == PTP_MT_Follow_Up) {
344 // check sequence ID if the response is ours
345 if (pHeader->sequenceID == S.slave.messaging.sequenceID) {
346 ptp_extract_timestamps(&S.slave.scd.t[T1], pRawMsg->data, 1); // read t1
347 S.slave.scd.cf[T2] = pHeader->correction_ns; // retain correction field
348
349 // initiate the correction
351
352 // log correction field (if enabled)
353 CLILOG(S.logging.corr, "C [Follow_Up]: %09" __PRI64_PREFIX "u\n", pHeader->correction_ns);
354
355 // dispatch FOLLOW_UP_RECVED event
357 }
358
359 // on ID mismatch, just skip the cycle, and expect a new Sync coming
360
361 // switch to next syncState
362 S.slave.messaging.m2sState = SIdle;
363 }
364
365 break;
366 }
367 }
368
369 // ------ (P)DELAY_RESPONSE PROCESSING --------
370
371 // wait for (P)Delay_Resp message
372 if (((mt == PTP_MT_Delay_Resp) && (dm == PTP_DM_E2E)) ||
373 (((mt == PTP_MT_PDelay_Resp) || (mt == PTP_MT_PDelay_Resp_Follow_Up)) && (dm == PTP_DM_P2P))) {
374 if (pHeader->sequenceID == S.slave.messaging.delay_reqSequenceID) { // read clock ID of requester
375 PtpDelay_RespIdentification delay_respID; // identification received in every Delay_Resp packet
376
377 if (mt == PTP_MT_Delay_Resp) { // Delay_Resp processing
378
379 // try fetching Delay_Req timestamp
381 return;
382 }
383
384 ptp_read_delay_resp_id_data(&delay_respID, pRawMsg->data);
385
386 // if the response was sent to us as a response to our Delay_Req then continue processing
387 if (delay_respID.requestingSourceClockIdentity == S.hwoptions.clockIdentity &&
389
390 ptp_extract_timestamps(&S.slave.scd.t[T4], pRawMsg->data, 1); // store t4
391 S.slave.scd.cf[T4] = pHeader->correction_ns; // store correction field
392
393 // compute mean path delay
394 ptp_compute_mean_path_delay_e2e(S.slave.scd.t, S.slave.scd.cf, &S.network.meanPathDelay);
395
396 // store last response ID
397 S.slave.messaging.lastRespondedDelReqId = pHeader->sequenceID;
398
399 // perform correction if operating on syncmatched mode
400 if (S.profile.logDelayReqPeriod == PTP_LOGPER_SYNCMATCHED) {
402 }
403
404 // dispatch DELAY_RESP_RECVED event
406
407 // log correction field (if enabled)
408 CLILOG(S.logging.corr, "C [Del_Resp]: %09" __PRI64_PREFIX "u\n", pHeader->correction_ns);
409 }
410
411 } else if (mt == PTP_MT_PDelay_Resp) { // PDelay_Resp processing
412 // try fetching Delay_Req timestamp
414 return;
415 }
416
417 TimestampI *pT = &S.slave.scd.t[2]; // skip the first 2 timestamps
418 uint64_t *cf = &S.slave.scd.cf[2]; // skip the first 2 correction fields
419
420 pT[T4] = pRawMsg->ts; // save t4 (P2P)
421 cf[T2] = pHeader->correction_ns; // save correction field of the PDelay_Resp
422
423 // if the responder is a one-step clock, then...
424 if (!pHeader->flags.PTP_TWO_STEP) {
425 // no t2 and t3 will be involved with the calculations
426 pT[T3] = pT[T2] = zeroTs;
427 ptp_commence_p2p_correction(pHeader->sequenceID); // commence correction
428 } else {
429 ptp_extract_timestamps(&(pT[T2]), pRawMsg->data, 1); // retrieve t2 (P2P)
430 S.slave.expectPDelRespFollowUp = true; // expect a PDelay_Resp_Follow_Up coming
431 }
432
433 // dispatch PDELAY_RESP_RECVED event
435
436 // log correction field (if enabled)
437 CLILOG(S.logging.corr, "C [PDel_Resp]: %09" __PRI64_PREFIX "u\n", pHeader->correction_ns);
438
439 } else if (mt == PTP_MT_PDelay_Resp_Follow_Up) { // PDelay_Resp_Follow_Up processing
440 // don't fall for rogue messages
441 if (!S.slave.expectPDelRespFollowUp) {
442 return;
443 }
444
445 ptp_read_delay_resp_id_data(&delay_respID, pRawMsg->data);
446
447 // if sent to us as a response to our Delay_Req then continue processing
448 if (delay_respID.requestingSourceClockIdentity == S.hwoptions.clockIdentity &&
450
451 TimestampI *pT = &S.slave.scd.t[2]; // skip the first 2 timestamps
452 uint64_t *cf = &S.slave.scd.cf[2]; // skip the first 2 correction fields
453
454 ptp_extract_timestamps(&(pT[T3]), pRawMsg->data, 1); // retrieve t3 (P2P)
455 cf[T3] = pHeader->correction_ns; // retain correction field from the PDelay_Resp_Follow_Up
456
457 // commence correction
459
460 // dispatch PDELAY_RESP_FOLLOW_UP_RECVED event
462
463 // log correction field (if enabled)
464 CLILOG(S.logging.corr, "C [PDel_Resp_Follow_Up]: %09" __PRI64_PREFIX "u\n", pHeader->correction_ns);
465 }
466
467 // no other messages are accepted
468 S.slave.expectPDelRespFollowUp = false;
469 }
470 }
471 }
472}
473
474// ------------------------
475
477 // initialize coarse threshold
479
480 // reset the slave module
482}
483
485 return;
486}
487
489 // disable slave module
490 S.slave.enabled = false;
491
492 // clear Sync cycle data
493 memset(&S.slave.scd, 0, sizeof(PtpSyncCycleData));
494 S.slave.prevSyncMa = zeroTs;
495 S.slave.prevTimeError = zeroTs;
496
497 // reset messaging state
498 memset(&S.slave.messaging, 0, sizeof(PtpSlaveMessagingState));
499
500 // reset addend/tuning
501#ifdef PTP_ADDEND_INTERFACE
502 S.hwclock.addend = PTP_ADDEND_INIT; // HW clock state
503 PTP_SET_ADDEND(S.hwclock.addend);
504#elif defined(PTP_HLT_INTERFACE)
505 S.hwclock.tuning_ppb = 0.0;
506 PTP_SET_TUNING(0.0);
507#endif
508
509 // reset the controller
511
512 // reset fast correction state
513 S.slave.fastCompState = PTP_FC_IDLE;
514 S.slave.fastCompCntr = 0;
515
516 // don't expect a Delay_Resp_Follow_Up message
517 S.slave.expectPDelRespFollowUp = false;
518}
519
521 if (!S.slave.enabled) {
522 return;
523 }
524
525 // Delay_Req transmission
526 if (S.profile.logDelayReqPeriod != PTP_LOGPER_SYNCMATCHED) {
527 if (++S.slave.delReqTmr > S.slave.delReqTickPeriod) {
528 S.slave.delReqTmr = 0;
529
530 // check that our last Delay_Req has been responded
531 if (S.profile.logDelayReqPeriod != PTP_LOGPER_SYNCMATCHED) {
532 if (S.slave.messaging.delay_reqSequenceID != S.slave.messaging.lastRespondedDelReqId) {
533 CLILOG(S.logging.info, "(P)Del_Req #%d: no response received!\n", S.slave.messaging.delay_reqSequenceID);
534 PTP_IUEV(PTP_UEV_NETWORK_ERROR); // dispatch network error event
535 }
536
537 // transmit (P)Delay_Req message
539
540 // dispatch (P)DELAY_REQ_SENT message
541 PTP_IUEV((S.profile.delayMechanism == PTP_DM_E2E) ? PTP_UEV_DELAY_REQ_SENT : PTP_UEV_PDELAY_REQ_SENT);
542 }
543 }
544 }
545}
546
548 S.slave.enabled = true;
549
550 if (S.profile.logDelayReqPeriod != PTP_LOGPER_SYNCMATCHED) {
551 S.slave.delReqTickPeriod = ptp_logi2ms(S.profile.logDelayReqPeriod) / PTP_HEARTBEAT_TICKRATE_MS;
552 }
553}
554
556 S.slave.enabled = false;
557}
void ptp_compute_mean_path_delay_p2p(const TimestampI *pTs, const uint64_t *pCf, TimestampI *pMPD)
Definition: common.c:152
void ptp_compute_mean_path_delay_e2e(const TimestampI *pTs, const uint64_t *pCf, TimestampI *pMPD)
Definition: common.c:139
void ptp_send_delay_req_message()
Definition: common.c:44
This module defines messaging functions for both the slave and master modules.
@ PTP_UEV_DELAY_RESP_RECVED
A Delay_Resp had been received (slave)
Definition: event.h:56
@ PTP_UEV_DELAY_REQ_SENT
A Delay_Req had been sent (slave)
Definition: event.h:55
@ PTP_UEV_PDELAY_RESP_FOLLOW_UP_RECVED
A PDelay_Resp_Follow_Up had been received (master/slave)
Definition: event.h:62
@ PTP_UEV_PDELAY_REQ_SENT
A PDelay_Req had been sent (master/slave)
Definition: event.h:59
@ PTP_UEV_PDELAY_RESP_RECVED
A PDelay_Resp had been received (master/slave)
Definition: event.h:60
@ PTP_UEV_SYNC_RECVED
A Sync message has been received (slave)
Definition: event.h:50
@ PTP_UEV_FOLLOW_UP_RECVED
A Follow_Up message has been received (slave)
Definition: event.h:52
@ PTP_UEV_NETWORK_ERROR
Indication of lost messages or the absence of expected responses.
Definition: event.h:72
#define PTP_IUEV(uev)
Definition: event.h:83
#define PTP_SET_CLOCK(s, ns)
#define PTP_SET_ADDEND(addend)
#define CLILOG(en,...)
#define PTP_SERVO_RESET()
#define PTP_HW_GET_TIME(pt)
#define PTP_SERVO_RUN(d, pscd)
#define PTP_SET_TUNING(tuning)
uint16_t ptp_logi2ms(int8_t logi)
Definition: format_utils.c:14
This module defines format conversion functions between network and host byte order and conversion fu...
#define MIN(a, b)
Definition: minmax.h:8
void ptp_extract_timestamps(TimestampI *ts, void *pPayload, uint8_t n)
Definition: msg_utils.c:189
void ptp_read_delay_resp_id_data(PtpDelay_RespIdentification *pDRData, void *pPayload)
Definition: msg_utils.c:214
This module defines functions that deal with actual PTP messages; they can extract or insert headers,...
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:128
#define PTP_CLOCK_TICK_FREQ_HZ
Rated clock tick frequency.
Definition: ptp_defs.h:81
#define PTP_ADDEND_CORR_PER_PPB_F
Addend/ppb ratio.
Definition: ptp_defs.h:78
#define PTP_COLOR_BYELLOW
Bright yellow.
Definition: ptp_defs.h:209
#define PTP_ADDEND_INIT
Initial addend value.
Definition: ptp_defs.h:77
#define PTP_PORT_ID
PTP port ID on the device.
Definition: ptp_defs.h:132
#define PTP_DEFAULT_COARSE_TRIGGER_NS
Coarse correction kick-in threshold.
Definition: ptp_defs.h:144
#define PTP_COLOR_RESET
Reset colors.
Definition: ptp_defs.h:214
#define T2
#define T3
#define T4
#define T1
This module defines the fundamental PTP message and state machine type, flags, bitfields and the PTP ...
@ PTP_LOGPER_SYNCMATCHED
Messaging occurs whenever a Sync arrives.
Definition: ptp_types.h:306
PtpFastCompState
Definition: ptp_types.h:492
@ PTP_FC_TIME_CORRECTION_PROPAGATION
Waiting for the effects of time correction to propagate.
Definition: ptp_types.h:495
@ PTP_FC_SKEW_CORRECTION
Skew correction is running.
Definition: ptp_types.h:493
@ PTP_FC_TIME_CORRECTION
Time correction is running.
Definition: ptp_types.h:494
@ PTP_FC_IDLE
Fast correction algorithm is IDLE.
Definition: ptp_types.h:492
@ SWaitFollowUp
Waiting for a Follow_Up message.
Definition: ptp_types.h:280
@ SIdle
Idle.
Definition: ptp_types.h:279
PtpMessageType
PTP packet type enumeration.
Definition: ptp_types.h:37
@ PTP_MT_Delay_Resp
Delay Response.
Definition: ptp_types.h:43
@ PTP_MT_PDelay_Resp
Peer Delay Response.
Definition: ptp_types.h:41
@ PTP_MT_Sync
Sync.
Definition: ptp_types.h:38
@ PTP_MT_PDelay_Resp_Follow_Up
Peer Delay Response Follow Up.
Definition: ptp_types.h:44
@ PTP_MT_Follow_Up
Follow Up.
Definition: ptp_types.h:42
PtpDelayMechanism
PTP Delay mechanism enumeration.
Definition: ptp_types.h:144
@ PTP_DM_E2E
End-to-End Delay Mechanism.
Definition: ptp_types.h:145
@ PTP_DM_P2P
Peer-to-Peer Delay Mechanism.
Definition: ptp_types.h:146
@ RPMT_DELAY_REQ
(P)Delay_Req tag
Definition: ptp_types.h:183
void ptp_set_coarse_threshold(uint64_t ns)
This module features functions to tweak around the PTP engine's almost every property.
static void ptp_commence_p2p_correction(uint32_t pdelRespSeqId)
Definition: slave.c:287
void ptp_slave_destroy()
Definition: slave.c:484
void ptp_slave_init()
Definition: slave.c:476
#define PTP_FC_TIME_CORRECTION_CYCLES
Fast compensation: no. of time correction cycles.
Definition: slave.c:46
void ptp_slave_process_message(RawPtpMessage *pRawMsg, PtpHeader *pHeader)
Definition: slave.c:300
void ptp_slave_enable()
Definition: slave.c:547
void ptp_slave_tick()
Definition: slave.c:520
#define PTP_FC_SKEW_CORRECTION_CYCLES
Fast compensation: no. of skew correction cycles.
Definition: slave.c:45
void ptp_slave_reset()
Definition: slave.c:488
#define PTP_FC_TIME_PROPAGATION_CYCLES
Definition: slave.c:47
void ptp_slave_disable()
Definition: slave.c:555
static void ptp_tune_clock(float tuning_ppb)
Definition: slave.c:34
static void ptp_commence_e2e_correction()
Definition: slave.c:258
static void ptp_perform_correction()
Definition: slave.c:52
This module implements the slave clock functionality.
void ptp_collect_stats(int64_t d)
Definition: stats.c:32
This is the statistics module that gathers data of the operating PTP-engine.
Identification carrying Delay_Resp message.
Definition: ptp_types.h:128
uint64_t requestingSourceClockIdentity
Requesting Source Clock Identity.
Definition: ptp_types.h:129
uint16_t requestingSourcePortIdentity
Requesting Source Port Identity.
Definition: ptp_types.h:130
bool PTP_TWO_STEP
Two Step.
Definition: ptp_types.h:67
PTP message header structure.
Definition: ptp_types.h:81
int8_t logMessagePeriod
Definition: ptp_types.h:122
uint8_t messageType
ID.
Definition: ptp_types.h:83
uint16_t sequenceID
Sequence ID.
Definition: ptp_types.h:116
PtpFlags flags
Flags.
Definition: ptp_types.h:100
uint64_t correction_ns
Correction nanoseconds.
Definition: ptp_types.h:103
Data to perform a full synchronization.
PtpSyncCycleData scd
Sync cycle data.
PTP slave messaging state structure.
Definition: ptp_types.h:412
PTP synchronization cycle data.
TimestampI ts
Timestamp.
Definition: ptp_types.h:187
uint8_t data[(128)]
raw packet data
Definition: ptp_types.h:198
Timestamp (signed)
Definition: timeutils.h:33
int32_t nanosec
nanoseconds
Definition: timeutils.h:35
int64_t sec
seconds
Definition: timeutils.h:34
Timestamp (unsigned)
Definition: timeutils.h:24
bool ptp_read_and_clear_transmit_timestamp(uint32_t tag, TimestampI *pTs)
Definition: task_ptp.c:564
The entry point of the whole PTP-implementation. Calling reg_task_ptp() initializes the PTP-engine,...
uint64_t nsU(const TimestampU *t)
Definition: timeutils.c:47
void normTime(TimestampI *t)
Definition: timeutils.c:57
int64_t tsToTick(const TimestampI *ts, uint32_t tps)
Definition: timeutils.c:63
TimestampI * nsToTsI(TimestampI *r, int64_t ns)
Definition: timeutils.c:69
TimestampI * subTime(TimestampI *r, const TimestampI *a, const TimestampI *b)
Definition: timeutils.c:32
bool nonZeroI(const TimestampI *a)
Definition: timeutils.c:75
int64_t nsI(const TimestampI *t)
Definition: timeutils.c:52
This module defines storage classes for timestamps and operations on time values.