diff --git a/include/netutils/ptpd.h b/include/netutils/ptpd.h index f418e6892..c86f3d647 100644 --- a/include/netutils/ptpd.h +++ b/include/netutils/ptpd.h @@ -54,6 +54,7 @@ struct ptpd_config_s bool bmca; sa_family_t af; int32_t ingress_latency_ns; /* Hardware RX timestamp latency (ns) */ + int32_t egress_latency_ns; /* Hardware TX timestamp latency (ns) */ }; /* PTPD status information structure */ diff --git a/netutils/ptpd/Kconfig b/netutils/ptpd/Kconfig index 371497609..eb560d7b0 100644 --- a/netutils/ptpd/Kconfig +++ b/netutils/ptpd/Kconfig @@ -259,4 +259,25 @@ config NETUTILS_PTPD_INGRESS_LATENCY_NS for example by comparing a physical PPS output against a reference. The default of 0 applies no compensation. +config NETUTILS_PTPD_EGRESS_LATENCY_NS + int "PTP hardware transmit timestamp latency (ns)" + default 0 + range -1000000 1000000 + depends on NET_TIMESTAMP + ---help--- + Fixed delay, in nanoseconds, between the MAC latching a hardware + transmit timestamp and the frame reaching the wire reference + plane. This is the egressLatency port parameter of IEEE 1588: the + clock domain crossing and the PHY make the frame leave later than + the timestamp point. + + The latency is added to every hardware transmit timestamp, so a + positive value moves the timestamps later. It has no effect with + software timestamping or when the driver does not provide + hardware transmit timestamps. It can be overridden at run time + with the -O option. + + The value depends on the PHY and board and has to be measured. + The default of 0 applies no compensation. + endif # NETUTILS_PTPD diff --git a/netutils/ptpd/ptpd.c b/netutils/ptpd/ptpd.c index dcccd2c1f..f10606bf5 100644 --- a/netutils/ptpd/ptpd.c +++ b/netutils/ptpd/ptpd.c @@ -1128,6 +1128,12 @@ static int ptp_sendmsg(FAR struct ptp_state_s *state, FAR const void *buf, if (ptp_get_tx_timestamp(state, sendts) == OK) { state->hwts_tx_failures = 0; + + /* The frame reaches the wire later than the MAC latches the + * timestamp: compensate the egress latency. + */ + + timespec_add_ns(sendts, state->config->egress_latency_ns); } else { diff --git a/system/ptpd/ptpd_main.c b/system/ptpd/ptpd_main.c index 370f915e1..3347f6c2d 100644 --- a/system/ptpd/ptpd_main.c +++ b/system/ptpd/ptpd_main.c @@ -165,6 +165,7 @@ static void usage(FAR const char *progname) " -i [dev] interface device to use, for example 'eth0'\n" " -p [dev] clock device to use\n" " -I [ns] hardware RX timestamp latency to compensate\n" + " -O [ns] hardware TX timestamp latency to compensate\n" " -t [pid] look the status of ptp daemon\n" " -d [pid] stop ptp daemon\n", progname); @@ -197,8 +198,13 @@ int main(int argc, FAR char *argv[]) config.bmca = false; config.af = AF_INET; config.ingress_latency_ns = CONFIG_NETUTILS_PTPD_INGRESS_LATENCY_NS; +#ifdef CONFIG_NET_TIMESTAMP + config.egress_latency_ns = CONFIG_NETUTILS_PTPD_EGRESS_LATENCY_NS; +#else + config.egress_latency_ns = 0; +#endif - while ((option = getopt(argc, argv, "p:i:t:d:I:rs246BEHSP")) != ERROR) + while ((option = getopt(argc, argv, "p:i:t:d:I:O:rs246BEHSP")) != ERROR) { switch (option) { @@ -256,6 +262,9 @@ int main(int argc, FAR char *argv[]) case 'I': config.ingress_latency_ns = atoi(optarg); break; + case 'O': + config.egress_latency_ns = atoi(optarg); + break; case 'r': config.clock = "realtime"; break;