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

Reply via email to