From: Vincent Cheng <vincent.cheng...@renesas.com> When clock stepping is unable to happen instantaneously the subsequent timestamps after a clock step does not reflect the step result and undesired clock freq and step adjustments will occur.
When using ts2phc to synchronize timestamping clock using external 1 PPS, it could take up to 1 second for the timestamps to reflect the clock step. step_window, when set, indicates the number of Sync events after a clock step in which the clock servo will not do any frequency or step adjustments. Signed-off-by: Vincent Cheng <vincent.cheng...@renesas.com> --- clock.c | 17 +++++++++++++++++ config.c | 1 + ptp4l.8 | 8 ++++++++ 3 files changed, 26 insertions(+) diff --git a/clock.c b/clock.c index a66d189..783a241 100644 --- a/clock.c +++ b/clock.c @@ -132,6 +132,8 @@ struct clock { struct interface *udsif; LIST_HEAD(clock_subscribers_head, clock_subscriber) subscribers; struct monitor *slave_event_monitor; + int step_window; + int step_window_counter; }; struct clock the_clock; @@ -1193,6 +1195,9 @@ struct clock *clock_create(enum clock_type type, struct config *config, return NULL; } + c->step_window = config_get_int(config, NULL, "step_window"); + c->step_window_counter = 0; + /* Create the ports. */ STAILQ_FOREACH(iface, &config->interfaces, list) { if (clock_add_port(c, phc_device, phc_index, timestamping, iface)) { @@ -1695,6 +1700,15 @@ int clock_switch_phc(struct clock *c, int phc_index) return 0; } +static void clock_step_window(struct clock *c) +{ + if (!c->step_window) + return; + + c->step_window_counter = c->step_window; + c->free_running = 1; +} + static void clock_synchronize_locked(struct clock *c, double adj) { clockadj_set_freq(c->clkid, -adj); @@ -1731,6 +1745,8 @@ enum servo_state clock_synchronize(struct clock *c, tmv_t ingress, tmv_t origin) c->cur.offsetFromMaster = tmv_to_TimeInterval(c->master_offset); if (c->free_running) { + if (c->step_window && !(--c->step_window_counter)) + c->free_running = 0; return clock_no_adjust(c, ingress, origin); } @@ -1747,6 +1763,7 @@ enum servo_state clock_synchronize(struct clock *c, tmv_t ingress, tmv_t origin) case SERVO_JUMP: clockadj_set_freq(c->clkid, -adj); clockadj_step(c->clkid, -tmv_to_nanoseconds(c->master_offset)); + clock_step_window(c); c->ingress_ts = tmv_zero(); if (c->sanity_check) { clockcheck_set_freq(c->sanity_check, -adj); diff --git a/config.c b/config.c index d237de9..65be360 100644 --- a/config.c +++ b/config.c @@ -302,6 +302,7 @@ struct config_item config_tab[] = { GLOB_ITEM_INT("slaveOnly", 0, 0, 1), GLOB_ITEM_INT("socket_priority", 0, 0, 15), GLOB_ITEM_DBL("step_threshold", 0.0, 0.0, DBL_MAX), + GLOB_ITEM_INT("step_window", 0, 0, INT_MAX), GLOB_ITEM_INT("summary_interval", 0, INT_MIN, INT_MAX), PORT_ITEM_INT("syncReceiptTimeout", 0, 0, UINT8_MAX), GLOB_ITEM_INT("tc_spanning_tree", 0, 0, 1), diff --git a/ptp4l.8 b/ptp4l.8 index b179b81..66504ef 100644 --- a/ptp4l.8 +++ b/ptp4l.8 @@ -694,6 +694,14 @@ one-second offset slowly by changing the clock frequency (unless the option is set to correct such offset by stepping). Relevant only with software time stamping. The default is 1 (enabled). .TP +.B step_window +When set, indicates the number of Sync events after a clock step that +the clock will not do any frequency or step adjustments. +This is used in situations where clock stepping is unable to happen +instantaneously so there is a lag before the timestamps can settle +properly to reflect the clock step. +The default is 0 (disabled). +.TP .B timeSource The time source is a single byte code that gives an idea of the kind of local clock in use. The value is purely informational, having no -- 2.7.4 _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel