Signed-off-by: Jürgen Appel <j...@dfm.dk> --- 1pps2phc.service | 42 ++++++++++++++++++++++++++++++++++++++++++ config.c | 1 + servo.c | 4 ++++ ts2phc.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- ts2phc.h | 2 ++ 5 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 1pps2phc.service
diff --git a/1pps2phc.service b/1pps2phc.service new file mode 100644 index 0000000..00e5fda --- /dev/null +++ b/1pps2phc.service @@ -0,0 +1,42 @@ +[Unit] + +# This example unit file shows how to configure a systemd-service that keeps +# ptp3 locked to an external 100ms-hardware-1PPS pulse connected to ptp3.SDP0 + +Description=Lock phc3 to 1pps + +After=network.target + +# This service roughly sets the PHC clock to within 1 s of the intended offset +After=initializePHC.service + +# Optional: As soon as we are locked, we want to use chrony to use /dev/ptp3 as time source +# Add the line "BindsTo=1pps2phc.service" to the [Unit] section in +# chrony's chrony.service configuration, and you are guaranteed that +# chrony is only running as long as your PHC is actually locked and is restarted when lock is lost. +#Wants=chrony.service + +[Service] +Type=forking +PIDFile=/run/ts2phc_1pps%i.pid + +# We start up ts2phc and give the process up to 3 minutes to lock to within 100 ns +TimeoutStartSec=180 +ExecStart=/usr/local/sbin/ts2phc -l 5 -c eth3 -s extpps \ + --ts2phc.extts_correction=-35 \ + --ts2phc.pin_index=0 \ + --ts2phc.channel=0 \ + --ts2phc.extts_polarity=both \ + --ts2phc.pulsewidth=100000000 \ + --message_tag=1pps \ + --servo_offset_threshold=100 \ + --systemd_pidfile=/run/ts2phc_1pps%i.pid + +Restart=on-failure + +# Optional: Enable an external Hardware-1PPS-output on ptp3.SDP1 as long as the lock is stable +ExecStartPost=/usr/local/sbin/testptp -d /dev/ptp3 -i 0 -L 1,2 -p 1000000000 +ExecStopPost=/usr/local/sbin/testptp -d /dev/ptp3 -i 0 -L 1,0 + +[Install] +WantedBy=multi-user.target diff --git a/config.c b/config.c index cb4421f..76a1056 100644 --- a/config.c +++ b/config.c @@ -329,6 +329,7 @@ struct config_item config_tab[] = { 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_STR("systemd_pidfile", NULL), 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/servo.c b/servo.c index ea171cd..85fe665 100644 --- a/servo.c +++ b/servo.c @@ -107,6 +107,10 @@ static int check_offset_threshold(struct servo *s, int64_t offset) if (s->curr_offset_values) s->curr_offset_values--; } else { + if (! s->curr_offset_values) { + // lock became unstable after having been stable + pr_info("servo got unlocked"); + } s->curr_offset_values = s->num_offset_values; } return s->curr_offset_values ? 0 : 1; diff --git a/ts2phc.c b/ts2phc.c index 6a8cad9..13bf474 100644 --- a/ts2phc.c +++ b/ts2phc.c @@ -436,6 +436,9 @@ static void ts2phc_synchronize_clocks(struct ts2phc_private *priv, int autocfg) struct ts2phc_clock *c; int valid, err; + pid_t pid; + FILE *pid_file; + if (autocfg) { if (!priv->ref_clock) { pr_debug("no reference clock, skipping"); @@ -499,8 +502,45 @@ static void ts2phc_synchronize_clocks(struct ts2phc_private *priv, int autocfg) goto servo_unlock; } break; - case SERVO_LOCKED: case SERVO_LOCKED_STABLE: + if (priv->pidfile && !priv->is_forked) { + priv->is_forked = true; + pid = fork(); + switch (pid) { + case -1: + pr_crit("fork failed"); + exit(EXIT_FAILURE); + case 0: /* child */ + chdir("/"); + close(0); + fopen("/dev/null", "r+"); + dup2(0,1); + dup2(0,2); + setsid(); + break; + pr_info("forked & detached (pid=%d)", + pid); + pid_file = fopen(priv- >pidfile, "w"); + if (!pid_file) { + pr_err("cannot create pidfile"); + _exit(EXIT_FAILURE); + } else { + fprintf(pid_file,"%d\n", pid); + fclose(pid_file); + _exit(EXIT_SUCCESS); + } + if (clockadj_set_freq(c->clkid, -adj)) { + goto servo_unlock; + } + case SERVO_LOCKED: + if (priv->is_forked) { + // servo has relocked + exit(EXIT_FAILURE); + } if (clockadj_set_freq(c->clkid, -adj)) { goto servo_unlock; } @@ -670,6 +710,9 @@ int main(int argc, char *argv[]) print_set_syslog(config_get_int(cfg, NULL, "use_syslog")); print_set_level(config_get_int(cfg, NULL, "logging_level")); + priv.pidfile = config_get_string(cfg, NULL, "systemd_pidfile"); + priv.is_forked = false; + STAILQ_INIT(&priv.sinks); priv.cfg = cfg; diff --git a/ts2phc.h b/ts2phc.h index 4833ded..6529f34 100644 --- a/ts2phc.h +++ b/ts2phc.h @@ -55,6 +55,8 @@ struct ts2phc_private { bool state_changed; LIST_HEAD(port_head, ts2phc_port) ports; LIST_HEAD(clock_head, ts2phc_clock) clocks; + char *pidfile; + bool is_forked; }; struct ts2phc_clock *ts2phc_clock_add(struct ts2phc_private *priv, -- _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel