Dear linuxptp-devel, thanks for providing my with this nice program, allowing me to lock my PHC to an external SDP-input on my i211 NICs. :-)
As many of you might recall, this particular NIC does not discriminate between rising and falling edges, and in ts2phc_pps_sink.c there already exists code to partly cope with this problem. When a -ts2phc.pulsewidth=tau is specified, only transitions happening with a timestamp within an interval of ±tau/2 with respect to CLOCK_REALTIME are retained, other transitions are ignored. But this requires a) CLOCK_REALTIME to be stable and never to make jumps anywhere close to tau/2 b) the external 1PPS-pulse to be aligned to CLOCK-REALTIME within tau/2 for the lock to work. Whereas the NIC can cope with pulses as short as 1ms reliably, it's unfeasible to get the clocks aligned with sufficient precision to start with, and other events fiddling with the system time (such as restarting an NTP server) easily can throw the lock off balance and lead to locking of the wrong edge of the 1PPS-pulse. Also, this can 'kick' the pulse outside the ±tau detection window completely, which leaves the clock unlocked potentially for a long time. I therefore suggest to change the edge-detection to use the pulse-width: Unless pulsewidth=NS_PER_SEC/2, from the time-interval relative to the previous event the edge can be determined uniquely, making involvement of the system time into acquiring a lock of the PHC unnecessary, completely avoid locking on the wrong edge and increase the capturing range. ======================================= diff --git a/ts2phc_pps_sink.c b/ts2phc_pps_sink.c index d25bc89..4ca46d3 100644 --- a/ts2phc_pps_sink.c +++ b/ts2phc_pps_sink.c @@ -30,8 +30,8 @@ struct ts2phc_pps_sink { struct ptp_pin_desc pin_desc; unsigned int polarity; tmv_t correction; - uint32_t ignore_lower; - uint32_t ignore_upper; + int pulsewidth; + tmv_t last; struct ts2phc_clock *clock; }; @@ -175,9 +175,8 @@ static struct ts2phc_pps_sink *ts2phc_pps_sink_create(struct ts2phc_private *pri sink->correction = nanoseconds_to_tmv(correction); pulsewidth = config_get_int(cfg, device, "ts2phc.pulsewidth"); - pulsewidth /= 2; - sink->ignore_upper = 1000000000 - pulsewidth; - sink->ignore_lower = pulsewidth; + sink->pulsewidth = pulsewidth; + sink->last.ns = 0; sink->clock = ts2phc_clock_add(priv, device); if (!sink->clock) { @@ -238,15 +237,36 @@ static void ts2phc_pps_sink_destroy(struct ts2phc_pps_sink *sink) static bool ts2phc_pps_sink_ignore(struct ts2phc_private *priv, struct ts2phc_pps_sink *sink, + struct ptp_extts_event event, struct timespec source_ts) { - tmv_t source_tmv = timespec_to_tmv(source_ts); - - source_tmv = tmv_sub(source_tmv, priv->perout_phase); - source_ts = tmv_to_timespec(source_tmv); - - return source_ts.tv_nsec > sink->ignore_lower && - source_ts.tv_nsec < sink->ignore_upper; + tmv_t event_tmv, source_tmv, dt; + + if (sink->pulsewidth == NS_PER_SEC/2) { + // 1pps has exactly 50% duty cycle: discriminate edges + // by CLOCK_REALTIME timestamp, requires CLOCK_REALTIME + // to be approximately correct and stable + source_tmv = timespec_to_tmv(source_ts); + source_tmv = tmv_sub(source_tmv, priv->perout_phase); + source_ts = tmv_to_timespec(source_tmv); + + return (source_ts.tv_nsec > NS_PER_SEC/4) && + (source_ts.tv_nsec < NS_PER_SEC/4*3); + } else { + // use pulse-width to discriminate rising/falling edges, + // does not require CLOCK_REALTIME to run correctly, + // tolerates jumps there + event_tmv = pct_to_tmv(event.t); + if (sink->last.ns) { + dt = tmv_sub(event_tmv, sink->last); + sink->last = event_tmv; + return ((dt.ns < (NS_PER_SEC / 2)) ^ + (sink->pulsewidth > (NS_PER_SEC / 2))); + } else { // ignore first event + sink->last = event_tmv; + return true; + } + } } static enum extts_result ts2phc_pps_sink_event(struct ts2phc_private *priv, @@ -277,7 +297,7 @@ static enum extts_result ts2phc_pps_sink_event(struct ts2phc_private *priv, } if (sink->polarity == (PTP_RISING_EDGE | PTP_FALLING_EDGE) && - ts2phc_pps_sink_ignore(priv, sink, source_ts)) { + ts2phc_pps_sink_ignore(priv, sink, event, source_ts)) { pr_debug("%s SKIP extts index %u at %lld.%09u src %" PRIi64 ".%ld", sink->name, event.index, event.t.sec, event.t.nsec, ==================================== Best regards, Jürgen Appel _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel