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 // Refuse a non-finite tuning value. Converting NaN or infinity to an integer is
36 // unpredictable (ARM yields 0, x86 yields INT64_MIN), so a single poisoned sample
37 // would either freeze the addend for ever or destroy it outright.
38 if (!isfinite(tuning_ppb)) {
39 return;
40 }
41
42#ifdef PTP_ADDEND_INTERFACE
43 int64_t compAddend = (int64_t)S.hwclock.addend + (int64_t)(tuning_ppb * PTP_ADDEND_CORR_PER_PPB_F); // compute addend value
44 S.hwclock.addend = MIN(compAddend, 0xFFFFFFFF); // limit to 32-bit range
45 PTP_SET_ADDEND(S.hwclock.addend); // write addend into hardware
46#elif defined(PTP_HLT_INTERFACE)
47 S.hwclock.tuning_ppb += tuning_ppb;
48 PTP_SET_TUNING(S.hwclock.tuning_ppb);
49#endif
50}
51
52#define PTP_FC_SKEW_CORRECTION_CYCLES (4)
53#define PTP_FC_TIME_CORRECTION_CYCLES (1)
54#define PTP_FC_TIME_PROPAGATION_CYCLES (2) //< Fast compensation: no. of time propagation cycles
55
60 // don't do any processing if no delay_request data is present
61 if (!nonZeroI(&S.network.meanPathDelay)) {
62 return;
63 }
64
65 // timestamps and time intervals
66 TimestampI d, syncMa, syncSl, delReqSl, delReqMa;
67
68 // copy timestamps to assign them with meaningful names
69 syncMa = S.slave.scd.t[T1];
70 syncSl = S.slave.scd.t[T2];
71 delReqSl = S.slave.scd.t[T3];
72 delReqMa = S.slave.scd.t[T4];
73
74 // prepare LOGID printing
75 const char * logIdStr = S.logging.logid ? "[LOG-TS:S] " : ""; // timestamp logging : slave
76
77 // log timestamps (if enabled)
78 if (S.profile.delayMechanism == PTP_DM_E2E) {
79 CLILOG(S.logging.timestamps,
80 "%sseqID: %u\n"
81 "%sT1: %d.%09d <- Sync TX (master)\n"
82 "%sT2: %d.%09d <- Sync RX (slave) \n"
83 "%sT3: %d.%09d <- Del_Req TX (slave) \n"
84 "%sT4: %d.%09d <- Del_Req RX (master)\n\n",
85 logIdStr, (uint32_t)S.slave.messaging.sequenceID,
86 logIdStr, (int32_t)syncMa.sec, syncMa.nanosec,
87 logIdStr, (int32_t)syncSl.sec, syncSl.nanosec,
88 logIdStr, (int32_t)delReqSl.sec, delReqSl.nanosec,
89 logIdStr, (int32_t)delReqMa.sec, delReqMa.nanosec);
90 } else if (S.profile.delayMechanism == PTP_DM_P2P) {
91 CLILOG(S.logging.timestamps,
92 "%sseqID: %u\n"
93 "%sT1: %d.%09d <- Sync TX (master)\n"
94 "%sT2: %d.%09d <- Sync RX (slave)\n"
95 "%st1: %d.%09d <- PDel_Req TX (our clock)\n"
96 "%st2: %d.%09d <- PDel_Req RX (their clock)\n"
97 "%st3: %d.%09d <- PDel_Resp TX (their clock)\n"
98 "%st4: %d.%09d <- PDel_Resp RX (our clock)\n\n",
99 logIdStr, (uint32_t)S.slave.messaging.sequenceID,
100 logIdStr, (int32_t)S.slave.scd.t[0].sec, S.slave.scd.t[0].nanosec,
101 logIdStr, (int32_t)S.slave.scd.t[1].sec, S.slave.scd.t[1].nanosec,
102 logIdStr, (int32_t)S.slave.scd.t[2].sec, S.slave.scd.t[2].nanosec,
103 logIdStr, (int32_t)S.slave.scd.t[3].sec, S.slave.scd.t[3].nanosec,
104 logIdStr, (int32_t)S.slave.scd.t[4].sec, S.slave.scd.t[4].nanosec,
105 logIdStr, (int32_t)S.slave.scd.t[5].sec, S.slave.scd.t[5].nanosec);
106 }
107
108 // ------------------------------
109
110 // variable for later substraction of summed correction fields
111 TimestampI cf = {0, 0};
112 nsToTsI(&cf, S.slave.scd.cf[T1] + S.slave.scd.cf[T2]);
113
114 // compute difference between master and slave clocks
115 subTime(&d, &syncSl, &syncMa); // t2 - t1 ...
116 subTime(&d, &d, &S.network.meanPathDelay); // - MPD
117 subTime(&d, &d, &cf); // - CF of (Sync + Follow_Up)
118
119 // substract offset
120 subTime(&d, &d, &S.hwoptions.offset);
121
122 // normalize time difference (eliminate malformed time value issues)
123 normTime(&d);
124
125 // ------------------------------
126
127 // fill the previous state variables
128 if (!nonZeroI(&S.slave.prevSyncMa) || !nonZeroI(&S.slave.prevSyncSl)) {
129 goto retain_cycle_data;
130 }
131
132 // ------------------------------
133
134 // determine the Sync period
135 TimestampI measSyncPeriod;
136 subTime(&measSyncPeriod, &syncMa, &(S.slave.prevSyncMa));
137 int64_t measSyncPeriod_ns = nsI(&measSyncPeriod);
138
139 // A Sync cycle that did not advance in master time - the same Sync processed twice, or
140 // two Syncs bearing the same originTimestamp - gives a zero or negative measured period.
141 // Every servo divides by this value, so passing it on produces NaN and, because NaN
142 // propagates through the filter state, silently disables clock correction from then on.
143 if (measSyncPeriod_ns <= 0) {
144 CLILOG(S.logging.info, "Sync cycle did not advance in master time; cycle skipped.\n");
145 goto retain_cycle_data;
146 }
147
148 // ------------------------------
149
150 // if time difference is greater than the predefined threshold then jump the clock
151 int64_t d_ns = nsI(&d);
152 PtpFastCompState fcs = S.slave.fastCompState;
153 if ((llabs(d_ns) > S.slave.coarseLimit) || (fcs != PTP_FC_IDLE)) {
154 if (fcs == PTP_FC_IDLE) {
155 // reset the servo
157
158 // print info
159 CLILOG(S.logging.logid && S.logging.info, "[LOG-INFO] ");
160 CLILOG(S.logging.info, "Time difference has exceeded the coarse correction threshold [%" __PRI64_PREFIX "dns], compensation commenced!\n", d_ns);
161 }
162
163 uint8_t fccntr = S.slave.fastCompCntr;
164 switch (fcs) {
165 case PTP_FC_IDLE:
167 fccntr = 0;
169 if (fccntr == PTP_FC_SKEW_CORRECTION_CYCLES) {
171 fccntr = 0;
172 }
173 break;
175 if (fccntr == PTP_FC_TIME_CORRECTION_CYCLES) {
177 fccntr = 0;
178 }
179 break;
181 if (fccntr == PTP_FC_TIME_PROPAGATION_CYCLES) {
182 fcs = PTP_FC_IDLE;
183 fccntr = 0;
184 }
185 break;
186 }
187
188 // skew correction
189 if (fcs == PTP_FC_SKEW_CORRECTION) {
190 // calculate clock skew
191 TimestampI dt2;
192 subTime(&dt2, &syncSl, &S.slave.prevSyncSl);
193 int64_t dt2_ns = nsI(&dt2);
194 double skew = (double)(dt2_ns - measSyncPeriod_ns) / (double)(measSyncPeriod_ns);
195 double skew_compensation_ppb = -skew * 1E+09;
196
197 // compensate the clock skew
198 ptp_tune_clock(skew_compensation_ppb);
199
200 // log skew compensation
201 CLILOG(S.logging.logid && S.logging.info, "[LOG-INFO] ");
202 CLILOG(S.logging.info, "[%u/%u] Skew compensation: % 6.4f ppb\n", fccntr + 1, PTP_FC_SKEW_CORRECTION_CYCLES, skew_compensation_ppb);
203 } else if (fcs == PTP_FC_TIME_CORRECTION) { // time correction
204 // compensate time error
205 TimestampU tu;
206 PTP_HW_GET_TIME(&tu);
207 uint64_t t_ns = nsU(&tu);
208 t_ns -= d_ns;
209 TimestampI ti;
210 nsToTsI(&ti, t_ns);
211 PTP_SET_CLOCK((uint32_t)ti.sec, ti.nanosec);
212
213 // log time compensation
214 CLILOG(S.logging.logid && S.logging.info, "[LOG-INFO] ");
215 CLILOG(S.logging.info, "[%u/%u] Time compensation: %" __PRI64_PREFIX "d ns\n", fccntr + 1, PTP_FC_TIME_CORRECTION_CYCLES, d_ns);
216 } else if (fcs == PTP_FC_TIME_CORRECTION_PROPAGATION) {
217 CLILOG(S.logging.logid && S.logging.info, "[LOG-INFO] ");
218 CLILOG(S.logging.info, "[%u/%u] Waiting for time compensation to propagate.\n", fccntr + 1, PTP_FC_TIME_PROPAGATION_CYCLES);
219 }
220
221 // maintain FC state
222 S.slave.fastCompState = fcs;
223 S.slave.fastCompCntr = fccntr + 1;
224
225 // retain sync cycle data
226 goto retain_cycle_data;
227 }
228
229 // ------------------------------
230
231 // prepare data to pass to the controller
232 PtpServoAuxInput saux = {S.slave.scd,
233 S.slave.messaging.logSyncPeriod,
234 S.slave.messaging.syncPeriodMs,
235 measSyncPeriod_ns};
236
237 // run controller
238 float corr_ppb = PTP_SERVO_RUN(nsI(&d), &saux);
239
240 // set clock tuning
241 ptp_tune_clock(corr_ppb);
242
243 // collect statistics
245
246 // log on cli (if enabled)
247#ifdef PTP_ADDEND_INTERFACE
248 CLILOG(S.logging.logid && S.logging.def, "[LOG-DEF:S:A] ") // default log : slave : addend interface
249 int32_t d_ticks = tsToTick(&d, PTP_CLOCK_TICK_FREQ_HZ);
250 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",
251 (int32_t)syncMa.sec, syncMa.nanosec, (int32_t)delReqMa.sec, delReqMa.nanosec,
252 (int32_t)d.sec, d.nanosec, d_ticks,
253 S.hwclock.addend, corr_ppb, nsI(&S.network.meanPathDelay), (uint64_t)measSyncPeriod_ns);
254#elif defined(PTP_HLT_INTERFACE)
255 CLILOG(S.logging.logid && S.logging.def, "[LOG-DEF:S:H] ") // default log : slave : HLT interface
256 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",
257 (int32_t)syncMa.sec, syncMa.nanosec, (int32_t)delReqMa.sec, delReqMa.nanosec,
258 (int32_t)d.sec, d.nanosec,
259 S.hwclock.tuning_ppb, corr_ppb, nsI(&S.network.meanPathDelay), (uint64_t)measSyncPeriod_ns);
260#endif
261
262 // call sync callback if defined
263 if (S.slave.syncCb != NULL) {
264#ifdef PTP_ADDEND_INTERFACE
265 S.slave.syncCb(nsI(&d), &S.slave.scd, S.hwclock.addend);
266#elif defined(PTP_HLT_INTERFACE)
267 S.slave.syncCb(nsI(&d), &S.slave.scd, S.hwclock.tuning_ppb);
268#endif
269 }
270
271 // ---------------------
272
273retain_cycle_data:
274 S.slave.prevSyncMa = syncMa;
275 S.slave.prevSyncSl = syncSl;
276 S.slave.prevTimeError = d;
277}
278
284 // send Delay_Req message
285 if (S.profile.logDelayReqPeriod == PTP_LOGPER_SYNCMATCHED) {
286 // send (P)Delay_Req message
288
289 // dispatch (P)DELAY_REQ_SENT event
290 PTP_IUEV((S.profile.delayMechanism == PTP_DM_E2E) ? PTP_UEV_DELAY_REQ_SENT : PTP_UEV_PDELAY_REQ_SENT);
291 }
292
293 // jump the clock if error is way too big...
294 TimestampI d;
295 subTime(&d, &S.slave.scd.t[T2], &S.slave.scd.t[T1]);
296 if (d.sec != 0) {
297 PTP_SET_CLOCK((int32_t)S.slave.scd.t[T1].sec, S.slave.scd.t[T1].nanosec);
298 }
299
300 // run servo only if issuing Delay_Requests is not syncmatched
301 if (S.profile.logDelayReqPeriod != PTP_LOGPER_SYNCMATCHED) {
303 }
304}
305
312static void ptp_commence_p2p_correction(uint32_t pdelRespSeqId) {
313 // compute mean path delay
314 ptp_compute_mean_path_delay_p2p(S.slave.scd.t + 2, S.slave.scd.cf + 2, &S.network.meanPathDelay);
315
316 // store last response ID
317 S.slave.messaging.lastRespondedDelReqId = pdelRespSeqId;
318
319 if (S.profile.logDelayReqPeriod == PTP_LOGPER_SYNCMATCHED) {
321 }
322}
323
324// packet processing
326 PtpMessageType mt = pHeader->messageType;
327 PtpDelayMechanism dm = S.profile.delayMechanism;
328
329 // process non-Announce messages
330 if (mt == PTP_MT_Sync || mt == PTP_MT_Follow_Up) {
331 switch (S.slave.messaging.m2sState) {
332 // wait for Sync message
333 case SIdle: {
334 // switch into next state if Sync packet has arrived
335 if (mt == PTP_MT_Sync) {
336 // save sync interval
337 S.slave.messaging.logSyncPeriod = pHeader->logMessagePeriod;
338 S.slave.messaging.syncPeriodMs = ptp_logi2ms(pHeader->logMessagePeriod);
339
340 // MSG("%d\n", header.logMessagePeriod);
341
342 // save reception time
343 S.slave.scd.t[T2] = pRawMsg->ts;
344
345 // switch to next syncState
346 S.slave.messaging.sequenceID = pHeader->sequenceID;
347
348 // save correction field
349 S.slave.scd.cf[T1] = pHeader->correction_ns;
350
351 // handle two step/one step messaging
352 if (pHeader->flags.PTP_TWO_STEP) {
353 S.slave.messaging.m2sState = SWaitFollowUp;
354 } else {
355 ptp_extract_timestamps(&S.slave.scd.t[T1], pRawMsg->data, 1); // extract t1
356 S.slave.scd.cf[T2] = 0; // clear Follow_Up correction field, since no Follow_Up is expected
357 ptp_commence_e2e_correction(); // commence executing the E2E correction
358 }
359
360 // dispatch SYNC_RECVED event
362 }
363
364 break;
365 }
366 // wait for Follow_Up message
367 case SWaitFollowUp:
368 if (mt == PTP_MT_Follow_Up) {
369 // check sequence ID if the response is ours
370 if (pHeader->sequenceID == S.slave.messaging.sequenceID) {
371 ptp_extract_timestamps(&S.slave.scd.t[T1], pRawMsg->data, 1); // read t1
372 S.slave.scd.cf[T2] = pHeader->correction_ns; // retain correction field
373
374 // initiate the correction
376
377 // log correction field (if enabled)
378 CLILOG(S.logging.logid && S.logging.corr, "[LOG-CORR] ");
379 CLILOG(S.logging.corr, "C [Follow_Up]: %09" __PRI64_PREFIX "u\n", pHeader->correction_ns);
380
381 // dispatch FOLLOW_UP_RECVED event
383 }
384
385 // on ID mismatch, just skip the cycle, and expect a new Sync coming
386
387 // switch to next syncState
388 S.slave.messaging.m2sState = SIdle;
389 }
390
391 break;
392 }
393 }
394
395 // ------ (P)DELAY_RESPONSE PROCESSING --------
396
397 // wait for (P)Delay_Resp message
398 if (((mt == PTP_MT_Delay_Resp) && (dm == PTP_DM_E2E)) ||
399 (((mt == PTP_MT_PDelay_Resp) || (mt == PTP_MT_PDelay_Resp_Follow_Up)) && (dm == PTP_DM_P2P))) {
400 if (pHeader->sequenceID == S.slave.messaging.delay_reqSequenceID) { // read clock ID of requester
401 PtpDelay_RespIdentification delay_respID; // identification received in every Delay_Resp packet
402
403 if (mt == PTP_MT_Delay_Resp) { // Delay_Resp processing
404
405 // try fetching Delay_Req timestamp
407 return;
408 }
409
410 ptp_read_delay_resp_id_data(&delay_respID, pRawMsg->data);
411
412 // if the response was sent to us as a response to our Delay_Req then continue processing
413 if (delay_respID.requestingSourceClockIdentity == S.hwoptions.clockIdentity &&
415
416 ptp_extract_timestamps(&S.slave.scd.t[T4], pRawMsg->data, 1); // store t4
417 S.slave.scd.cf[T4] = pHeader->correction_ns; // store correction field
418
419 // compute mean path delay
420 ptp_compute_mean_path_delay_e2e(S.slave.scd.t, S.slave.scd.cf, &S.network.meanPathDelay);
421
422 // store last response ID
423 S.slave.messaging.lastRespondedDelReqId = pHeader->sequenceID;
424
425 // perform correction if operating on syncmatched mode
426 if (S.profile.logDelayReqPeriod == PTP_LOGPER_SYNCMATCHED) {
428 }
429
430 // dispatch DELAY_RESP_RECVED event
432
433 // log correction field (if enabled)
434 CLILOG(S.logging.logid && S.logging.corr, "[LOG-CORR] ");
435 CLILOG(S.logging.corr, "C [Del_Resp]: %09" __PRI64_PREFIX "u\n", pHeader->correction_ns);
436 }
437
438 } else if (mt == PTP_MT_PDelay_Resp) { // PDelay_Resp processing
439 // try fetching Delay_Req timestamp
441 return;
442 }
443
444 TimestampI *pT = &S.slave.scd.t[2]; // skip the first 2 timestamps
445 uint64_t *cf = &S.slave.scd.cf[2]; // skip the first 2 correction fields
446
447 pT[T4] = pRawMsg->ts; // save t4 (P2P)
448 cf[T2] = pHeader->correction_ns; // save correction field of the PDelay_Resp
449
450 // if the responder is a one-step clock, then...
451 if (!pHeader->flags.PTP_TWO_STEP) {
452 // no t2 and t3 will be involved with the calculations
453 pT[T3] = pT[T2] = zeroTs;
454 ptp_commence_p2p_correction(pHeader->sequenceID); // commence correction
455 } else {
456 ptp_extract_timestamps(&(pT[T2]), pRawMsg->data, 1); // retrieve t2 (P2P)
457 S.slave.expectPDelRespFollowUp = true; // expect a PDelay_Resp_Follow_Up coming
458 }
459
460 // dispatch PDELAY_RESP_RECVED event
462
463 // log correction field (if enabled)
464 CLILOG(S.logging.logid && S.logging.corr, "[LOG-CORR] ");
465 CLILOG(S.logging.corr, "C [PDel_Resp]: %09" __PRI64_PREFIX "u\n", pHeader->correction_ns);
466
467 } else if (mt == PTP_MT_PDelay_Resp_Follow_Up) { // PDelay_Resp_Follow_Up processing
468 // don't fall for rogue messages
469 if (!S.slave.expectPDelRespFollowUp) {
470 return;
471 }
472
473 ptp_read_delay_resp_id_data(&delay_respID, pRawMsg->data);
474
475 // if sent to us as a response to our Delay_Req then continue processing
476 if (delay_respID.requestingSourceClockIdentity == S.hwoptions.clockIdentity &&
478
479 TimestampI *pT = &S.slave.scd.t[2]; // skip the first 2 timestamps
480 uint64_t *cf = &S.slave.scd.cf[2]; // skip the first 2 correction fields
481
482 ptp_extract_timestamps(&(pT[T3]), pRawMsg->data, 1); // retrieve t3 (P2P)
483 cf[T3] = pHeader->correction_ns; // retain correction field from the PDelay_Resp_Follow_Up
484
485 // commence correction
487
488 // dispatch PDELAY_RESP_FOLLOW_UP_RECVED event
490
491 // log correction field (if enabled)
492 CLILOG(S.logging.logid && S.logging.corr, "[LOG-CORR] ");
493 CLILOG(S.logging.corr, "C [PDel_Resp_Follow_Up]: %09" __PRI64_PREFIX "u\n", pHeader->correction_ns);
494 }
495
496 // no other messages are accepted
497 S.slave.expectPDelRespFollowUp = false;
498 }
499 }
500 }
501}
502
503// ------------------------
504
506 // initialize coarse threshold
508
509 // reset the slave module
511}
512
514 return;
515}
516
518 // disable slave module
519 S.slave.enabled = false;
520
521 // clear Sync cycle data
522 memset(&S.slave.scd, 0, sizeof(PtpSyncCycleData));
523 S.slave.prevSyncMa = zeroTs;
524 S.slave.prevTimeError = zeroTs;
525
526 // reset messaging state
527 memset(&S.slave.messaging, 0, sizeof(PtpSlaveMessagingState));
528
529 // reset addend/tuning
530#ifdef PTP_ADDEND_INTERFACE
531 S.hwclock.addend = PTP_ADDEND_INIT; // HW clock state
532 PTP_SET_ADDEND(S.hwclock.addend);
533#elif defined(PTP_HLT_INTERFACE)
534 S.hwclock.tuning_ppb = 0.0;
535 PTP_SET_TUNING(0.0);
536#endif
537
538 // reset the controller
540
541 // reset fast correction state
542 S.slave.fastCompState = PTP_FC_IDLE;
543 S.slave.fastCompCntr = 0;
544
545 // don't expect a Delay_Resp_Follow_Up message
546 S.slave.expectPDelRespFollowUp = false;
547}
548
550 if (!S.slave.enabled) {
551 return;
552 }
553
554 // Delay_Req transmission
555 if (S.profile.logDelayReqPeriod != PTP_LOGPER_SYNCMATCHED) {
556 if (++S.slave.delReqTmr > S.slave.delReqTickPeriod) {
557 S.slave.delReqTmr = 0;
558
559 // check that our last Delay_Req has been responded
560 if (S.profile.logDelayReqPeriod != PTP_LOGPER_SYNCMATCHED) {
561 if (S.slave.messaging.delay_reqSequenceID != S.slave.messaging.lastRespondedDelReqId) {
562 CLILOG(S.logging.logid && S.logging.info, "[LOG-INFO] ");
563 CLILOG(S.logging.info, "(P)Del_Req #%d: no response received!\n", S.slave.messaging.delay_reqSequenceID);
564 PTP_IUEV(PTP_UEV_NETWORK_ERROR); // dispatch network error event
565 }
566
567 // transmit (P)Delay_Req message
569
570 // dispatch (P)DELAY_REQ_SENT message
571 PTP_IUEV((S.profile.delayMechanism == PTP_DM_E2E) ? PTP_UEV_DELAY_REQ_SENT : PTP_UEV_PDELAY_REQ_SENT);
572 }
573 }
574 }
575}
576
578 S.slave.enabled = true;
579
580 if (S.profile.logDelayReqPeriod != PTP_LOGPER_SYNCMATCHED) {
581 S.slave.delReqTickPeriod = ptp_logi2ms(S.profile.logDelayReqPeriod) / PTP_HEARTBEAT_TICKRATE_MS;
582 }
583}
584
586 S.slave.enabled = false;
587}
void ptp_compute_mean_path_delay_p2p(const TimestampI *pTs, const uint64_t *pCf, TimestampI *pMPD)
Definition: common.c:155
void ptp_compute_mean_path_delay_e2e(const TimestampI *pTs, const uint64_t *pCf, TimestampI *pMPD)
Definition: common.c:142
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:188
void ptp_read_delay_resp_id_data(PtpDelay_RespIdentification *pDRData, void *pPayload)
Definition: msg_utils.c:213
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:307
PtpFastCompState
Definition: ptp_types.h:500
@ PTP_FC_TIME_CORRECTION_PROPAGATION
Waiting for the effects of time correction to propagate.
Definition: ptp_types.h:503
@ PTP_FC_SKEW_CORRECTION
Skew correction is running.
Definition: ptp_types.h:501
@ PTP_FC_TIME_CORRECTION
Time correction is running.
Definition: ptp_types.h:502
@ PTP_FC_IDLE
Fast correction algorithm is IDLE.
Definition: ptp_types.h:500
@ SWaitFollowUp
Waiting for a Follow_Up message.
Definition: ptp_types.h:281
@ SIdle
Idle.
Definition: ptp_types.h:280
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:312
void ptp_slave_destroy()
Definition: slave.c:513
void ptp_slave_init()
Definition: slave.c:505
#define PTP_FC_TIME_CORRECTION_CYCLES
Fast compensation: no. of time correction cycles.
Definition: slave.c:53
void ptp_slave_process_message(RawPtpMessage *pRawMsg, PtpHeader *pHeader)
Definition: slave.c:325
void ptp_slave_enable()
Definition: slave.c:577
void ptp_slave_tick()
Definition: slave.c:549
#define PTP_FC_SKEW_CORRECTION_CYCLES
Fast compensation: no. of skew correction cycles.
Definition: slave.c:52
void ptp_slave_reset()
Definition: slave.c:517
#define PTP_FC_TIME_PROPAGATION_CYCLES
Definition: slave.c:54
void ptp_slave_disable()
Definition: slave.c:585
static void ptp_tune_clock(float tuning_ppb)
Definition: slave.c:34
static void ptp_commence_e2e_correction()
Definition: slave.c:283
static void ptp_perform_correction()
Definition: slave.c:59
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:415
PTP synchronization cycle data.
TimestampI ts
Timestamp.
Definition: ptp_types.h:187
uint8_t data[(128)]
raw packet data
Definition: ptp_types.h:199
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:649
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.