Discussion:
[Linuxptp-devel] [PATCH 0/8] Merge phc2sys and ptp4l servos
Miroslav Lichvar
2013-01-14 16:09:07 UTC
Permalink
I thought it would be useful to merge the PI servo implementations in ptp4l and
phc2sys. They are very similar, but there are some improvements and bugs which
were made in one but not the other. This patchset fixes the bugs and adds the
missing features to the ptp4l servo and makes phc2sys use it. Some cleanup is
included.

Miroslav Lichvar (8):
Fix initial drift calculation in PI servo.
Modify servo_sample() to accept integer values.
Modify PI servo to set frequency when jumping.
Remove unnecessary states in PI servo.
phc2sys: use servo code from ptp4l.
phc2sys: move phc loop to its own function.
phc2sys: don't zero clock frequency on start.
phc2sys: remove unnecessary clock step with non-PPS loops.

clock.c | 1 +
makefile | 2 +-
phc2sys.c | 192 ++++++++++++++++++++++++++++++--------------------------
pi.c | 29 +++++----
servo.c | 4 +-
servo.h | 6 +-
servo_private.h | 2 +-
7 files changed, 127 insertions(+), 109 deletions(-)
--
1.7.11.7
Miroslav Lichvar
2013-01-14 16:09:10 UTC
Permalink
Similarly to the servo in phc2sys, when clock is stepped, set
immediately also its frequency. This significantly improves the initial
convergence with large frequency offsets.

Signed-off-by: Miroslav Lichvar <***@redhat.com>
---
clock.c | 1 +
pi.c | 1 +
2 files changed, 2 insertions(+)

diff --git a/clock.c b/clock.c
index 5a475f2..b0a4de6 100644
--- a/clock.c
+++ b/clock.c
@@ -867,6 +867,7 @@ enum servo_state clock_synchronize(struct clock *c,
case SERVO_UNLOCKED:
break;
case SERVO_JUMP:
+ clock_ppb(c->clkid, -adj);
clock_step(c->clkid, -c->master_offset);
c->t1 = tmv_zero();
c->t2 = tmv_zero();
diff --git a/pi.c b/pi.c
index 5fbce38..934fff6 100644
--- a/pi.c
+++ b/pi.c
@@ -87,6 +87,7 @@ static double pi_sample(struct servo *servo,
break;
case 3:
*state = SERVO_JUMP;
+ ppb = s->drift;
s->count = 4;
break;
case 4:
--
1.7.11.7
Miroslav Lichvar
2013-01-14 16:09:08 UTC
Permalink
Convert the calculated drift to ppb and also clamp it.

Signed-off-by: Miroslav Lichvar <***@redhat.com>
---
pi.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/pi.c b/pi.c
index b2d1470..9b3b09e 100644
--- a/pi.c
+++ b/pi.c
@@ -76,8 +76,12 @@ static double pi_sample(struct servo *servo,
s->count = 2;
break;
case 2:
- s->drift += (s->offset[1] - s->offset[0]) /
+ s->drift += (s->offset[1] - s->offset[0]) * 1e9 /
(s->local[1] - s->local[0]);
+ if (s->drift < -s->maxppb)
+ s->drift = -s->maxppb;
+ else if (s->drift > s->maxppb)
+ s->drift = s->maxppb;
*state = SERVO_UNLOCKED;
s->count = 3;
break;
--
1.7.11.7
Richard Cochran
2013-01-15 09:48:39 UTC
Permalink
Post by Miroslav Lichvar
diff --git a/pi.c b/pi.c
index b2d1470..9b3b09e 100644
--- a/pi.c
+++ b/pi.c
@@ -76,8 +76,12 @@ static double pi_sample(struct servo *servo,
s->count = 2;
break;
- s->drift += (s->offset[1] - s->offset[0]) /
+ s->drift += (s->offset[1] - s->offset[0]) * 1e9 /
(s->local[1] - s->local[0]);
So this expression always yielded nearly zero ppb. That stinks.

This kind of fix might deserve a 1.1 release. What do you think?

Thanks,
Richard
Miroslav Lichvar
2013-01-15 12:37:13 UTC
Permalink
Post by Richard Cochran
Post by Miroslav Lichvar
diff --git a/pi.c b/pi.c
index b2d1470..9b3b09e 100644
--- a/pi.c
+++ b/pi.c
@@ -76,8 +76,12 @@ static double pi_sample(struct servo *servo,
s->count = 2;
break;
- s->drift += (s->offset[1] - s->offset[0]) /
+ s->drift += (s->offset[1] - s->offset[0]) * 1e9 /
(s->local[1] - s->local[0]);
So this expression always yielded nearly zero ppb. That stinks.
This kind of fix might deserve a 1.1 release. What do you think?
I'm not sure if it's that serious. I think the servo will just need
more time to settle down after start. A "worst case" simulation with
error of 100 ppm and the default software time stamping PI constants
(kp = 0.1, ki = 0.001) shows that it will take about 15 minutes to
settle down. With the default hardware time stamping constants (kp =
0.7, ki = 0.3) it might not even be noticeable.
--
Miroslav Lichvar
Miroslav Lichvar
2013-01-14 16:09:09 UTC
Permalink
Current date stored in nanoseconds doesn't fit in 64-bit double format.
Keep the offset and the time stamp in integer nanoseconds.

Signed-off-by: Miroslav Lichvar <***@redhat.com>
---
pi.c | 8 ++++----
servo.c | 4 ++--
servo.h | 6 ++++--
servo_private.h | 2 +-
4 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/pi.c b/pi.c
index 9b3b09e..5fbce38 100644
--- a/pi.c
+++ b/pi.c
@@ -38,8 +38,8 @@ double configured_pi_offset = 0.0;

struct pi_servo {
struct servo servo;
- double offset[2];
- double local[2];
+ int64_t offset[2];
+ uint64_t local[2];
double drift;
double maxppb;
double kp;
@@ -55,8 +55,8 @@ static void pi_destroy(struct servo *servo)
}

static double pi_sample(struct servo *servo,
- double offset,
- double local_ts,
+ int64_t offset,
+ uint64_t local_ts,
enum servo_state *state)
{
double ki_term, ppb = 0.0;
diff --git a/servo.c b/servo.c
index 97c2e60..a312ad1 100644
--- a/servo.c
+++ b/servo.c
@@ -35,8 +35,8 @@ void servo_destroy(struct servo *servo)
}

double servo_sample(struct servo *servo,
- double offset,
- double local_ts,
+ int64_t offset,
+ uint64_t local_ts,
enum servo_state *state)
{
return servo->sample(servo, offset, local_ts, state);
diff --git a/servo.h b/servo.h
index 0d2ab71..4d4a8e7 100644
--- a/servo.h
+++ b/servo.h
@@ -20,6 +20,8 @@
#ifndef HAVE_SERVO_H
#define HAVE_SERVO_H

+#include <stdint.h>
+
/** Opaque type */
struct servo;

@@ -80,8 +82,8 @@ void servo_destroy(struct servo *servo);
* @return The clock adjustment in parts per billion.
*/
double servo_sample(struct servo *servo,
- double offset,
- double local_ts,
+ int64_t offset,
+ uint64_t local_ts,
enum servo_state *state);

#endif
diff --git a/servo_private.h b/servo_private.h
index 2c710e5..f9c151f 100644
--- a/servo_private.h
+++ b/servo_private.h
@@ -26,7 +26,7 @@ struct servo {
void (*destroy)(struct servo *servo);

double (*sample)(struct servo *servo,
- double offset, double local_ts,
+ int64_t offset, uint64_t local_ts,
enum servo_state *state);
};
--
1.7.11.7
Miroslav Lichvar
2013-01-14 16:09:11 UTC
Permalink
Step the clock as soon as the second sample is collected.

Signed-off-by: Miroslav Lichvar <***@redhat.com>
---
pi.c | 14 ++++----------
1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/pi.c b/pi.c
index 934fff6..825ec22 100644
--- a/pi.c
+++ b/pi.c
@@ -72,25 +72,19 @@ static double pi_sample(struct servo *servo,
case 1:
s->offset[1] = offset;
s->local[1] = local_ts;
- *state = SERVO_UNLOCKED;
- s->count = 2;
- break;
- case 2:
+
s->drift += (s->offset[1] - s->offset[0]) * 1e9 /
(s->local[1] - s->local[0]);
if (s->drift < -s->maxppb)
s->drift = -s->maxppb;
else if (s->drift > s->maxppb)
s->drift = s->maxppb;
- *state = SERVO_UNLOCKED;
- s->count = 3;
- break;
- case 3:
+
*state = SERVO_JUMP;
ppb = s->drift;
- s->count = 4;
+ s->count = 2;
break;
- case 4:
+ case 2:
/*
* reset the clock servo when offset is greater than the max
* offset value. Note that the clock jump will be performed in
--
1.7.11.7
Miroslav Lichvar
2013-01-14 16:09:12 UTC
Permalink
Signed-off-by: Miroslav Lichvar <***@redhat.com>
---
makefile | 2 +-
phc2sys.c | 132 ++++++++++++++++++++++++++++----------------------------------
2 files changed, 61 insertions(+), 73 deletions(-)

diff --git a/makefile b/makefile
index 53b9e4d..d144949 100644
--- a/makefile
+++ b/makefile
@@ -51,7 +51,7 @@ ptp4l: $(OBJ)

pmc: pmc.o msg.o print.o raw.o sk.o tlv.o transport.o udp.o udp6.o uds.o util.o version.o

-phc2sys: phc2sys.o sk.o sysoff.o print.o version.o
+phc2sys: phc2sys.o pi.o servo.o sk.o sysoff.o print.o version.o

hwstamp_ctl: hwstamp_ctl.o version.o

diff --git a/phc2sys.c b/phc2sys.c
index 2beddf3..9e8d217 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -34,6 +34,8 @@
#include <linux/ptp_clock.h>

#include "missing.h"
+#include "pi.h"
+#include "servo.h"
#include "sk.h"
#include "sysoff.h"
#include "version.h"
@@ -43,7 +45,6 @@
#define NS_PER_SEC 1000000000LL

#define max_ppb 512000
-#define min_ppb -512000

static clockid_t clock_open(char *device)
{
@@ -129,62 +130,35 @@ static int read_phc(clockid_t clkid, clockid_t sysclk, int readings,
return 1;
}

-struct servo {
- uint64_t saved_ts;
- int64_t saved_offset;
- double drift;
- enum {
- SAMPLE_0, SAMPLE_1, SAMPLE_2, SAMPLE_3, SAMPLE_N
- } state;
+struct clock {
+ clockid_t clkid;
+ struct servo *servo;
+ FILE *log_file;
+ const char *source_label;
};

-static struct servo servo;
-
-static void show_servo(FILE *fp, const char *label, int64_t offset, uint64_t ts)
+static void update_clock(struct clock *clock, int64_t offset, uint64_t ts)
{
- fprintf(fp, "%s %9" PRId64 " s%d %lld.%09llu drift %.2f\n", label, offset,
- servo.state, ts / NS_PER_SEC, ts % NS_PER_SEC, servo.drift);
- fflush(fp);
-}
+ enum servo_state state;
+ double ppb;

-static void do_servo(struct servo *srv, clockid_t dst,
- int64_t offset, uint64_t ts, double kp, double ki)
-{
- double ki_term, ppb;
-
- switch (srv->state) {
- case SAMPLE_0:
- clock_ppb(dst, 0.0);
- srv->saved_offset = offset;
- srv->saved_ts = ts;
- srv->state = SAMPLE_1;
- break;
- case SAMPLE_1:
- srv->state = SAMPLE_2;
- break;
- case SAMPLE_2:
- srv->state = SAMPLE_3;
- break;
- case SAMPLE_3:
- srv->drift = (offset - srv->saved_offset) * 1e9 /
- (ts - srv->saved_ts);
- clock_ppb(dst, -srv->drift);
- clock_step(dst, -offset);
- srv->state = SAMPLE_N;
+ ppb = servo_sample(clock->servo, offset, ts, &state);
+
+ switch (state) {
+ case SERVO_UNLOCKED:
break;
- case SAMPLE_N:
- ki_term = ki * offset;
- ppb = kp * offset + srv->drift + ki_term;
- if (ppb < min_ppb) {
- ppb = min_ppb;
- } else if (ppb > max_ppb) {
- ppb = max_ppb;
- } else {
- srv->drift += ki_term;
- }
- clock_ppb(dst, -ppb);
+ case SERVO_JUMP:
+ clock_step(clock->clkid, -offset);
+ /* Fall through. */
+ case SERVO_LOCKED:
+ clock_ppb(clock->clkid, -ppb);
break;
}
+
+ fprintf(clock->log_file, "%s %9" PRId64 " s%d %lld.%09llu adj %.2f\n",
+ clock->source_label, offset, state,
+ ts / NS_PER_SEC, ts % NS_PER_SEC, ppb);
+ fflush(clock->log_file);
}

static int read_pps(int fd, int64_t *offset, uint64_t *ts)
@@ -209,12 +183,14 @@ static int read_pps(int fd, int64_t *offset, uint64_t *ts)
return 1;
}

-static int do_pps_loop(char *pps_device, double kp, double ki, clockid_t dst)
+static int do_pps_loop(struct clock *clock, char *pps_device)
{
int64_t pps_offset;
uint64_t pps_ts;
int fd;

+ clock->source_label = "pps";
+
fd = open(pps_device, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "cannot open '%s': %m\n", pps_device);
@@ -224,20 +200,21 @@ static int do_pps_loop(char *pps_device, double kp, double ki, clockid_t dst)
if (!read_pps(fd, &pps_offset, &pps_ts)) {
continue;
}
- do_servo(&servo, dst, pps_offset, pps_ts, kp, ki);
- show_servo(stdout, "pps", pps_offset, pps_ts);
+ update_clock(clock, pps_offset, pps_ts);
}
close(fd);
return 0;
}

-static int do_sysoff_loop(clockid_t src, clockid_t dst,
- int rate, int n_readings, int sync_offset,
- double kp, double ki)
+static int do_sysoff_loop(struct clock *clock, clockid_t src,
+ int rate, int n_readings, int sync_offset)
{
uint64_t ts;
int64_t offset;
int err = 0, fd = CLOCKID_TO_FD(src);
+
+ clock->source_label = "sys";
+
while (1) {
usleep(1000000 / rate);
if (sysoff_measure(fd, n_readings, &offset, &ts)) {
@@ -245,8 +222,7 @@ static int do_sysoff_loop(clockid_t src, clockid_t dst,
break;
}
offset -= sync_offset * NS_PER_SEC;
- do_servo(&servo, dst, offset, ts, kp, ki);
- show_servo(stdout, "sys", offset, ts);
+ update_clock(clock, offset, ts);
}
return err;
}
@@ -273,12 +249,18 @@ static void usage(char *progname)

int main(int argc, char *argv[])
{
- double kp = KP, ki = KI;
char *device = NULL, *progname, *ethdev = NULL;
- clockid_t src = CLOCK_INVALID, dst = CLOCK_REALTIME;
+ clockid_t src = CLOCK_INVALID;
uint64_t phc_ts;
int64_t phc_offset;
int c, phc_readings = 5, phc_rate = 1, sync_offset = 0;
+ struct clock dst_clock = {
+ .clkid = CLOCK_REALTIME,
+ .log_file = stdout
+ };
+
+ configured_pi_kp = KP;
+ configured_pi_ki = KI;

/* Process the command line arguments. */
progname = strrchr(argv[0], '/');
@@ -286,7 +268,7 @@ int main(int argc, char *argv[])
while (EOF != (c = getopt(argc, argv, "c:d:hs:P:I:R:N:O:i:v"))) {
switch (c) {
case 'c':
- dst = clock_open(optarg);
+ dst_clock.clkid = clock_open(optarg);
break;
case 'd':
device = optarg;
@@ -295,10 +277,10 @@ int main(int argc, char *argv[])
src = clock_open(optarg);
break;
case 'P':
- kp = atof(optarg);
+ configured_pi_kp = atof(optarg);
break;
case 'I':
- ki = atof(optarg);
+ configured_pi_ki = atof(optarg);
break;
case 'R':
phc_rate = atoi(optarg);
@@ -338,7 +320,8 @@ int main(int argc, char *argv[])
sprintf(phc_device, "/dev/ptp%d", ts_info.phc_index);
src = clock_open(phc_device);
}
- if (!(device || src != CLOCK_INVALID) || dst == CLOCK_INVALID) {
+ if (!(device || src != CLOCK_INVALID) ||
+ dst_clock.clkid == CLOCK_INVALID) {
usage(progname);
return -1;
}
@@ -347,26 +330,31 @@ int main(int argc, char *argv[])
if (clock_gettime(src, &now))
perror("clock_gettime");
now.tv_sec += sync_offset;
- if (clock_settime(dst, &now))
+ if (clock_settime(dst_clock.clkid, &now))
perror("clock_settime");
}

+ clock_ppb(dst_clock.clkid, 0.0);
+
+ dst_clock.servo = servo_create(CLOCK_SERVO_PI, 0.0, max_ppb, 0);
+
if (device)
- return do_pps_loop(device, kp, ki, dst);
+ return do_pps_loop(&dst_clock, device);

- if (dst == CLOCK_REALTIME &&
+ if (dst_clock.clkid == CLOCK_REALTIME &&
SYSOFF_SUPPORTED == sysoff_probe(CLOCKID_TO_FD(src), phc_readings))
- return do_sysoff_loop(src, dst, phc_rate,
- phc_readings, sync_offset, kp, ki);
+ return do_sysoff_loop(&dst_clock, src, phc_rate,
+ phc_readings, sync_offset);
+
+ dst_clock.source_label = "phc";

while (1) {
usleep(1000000 / phc_rate);
- if (!read_phc(src, dst, phc_readings, &phc_offset, &phc_ts)) {
+ if (!read_phc(src, dst_clock.clkid, phc_readings, &phc_offset, &phc_ts)) {
continue;
}
phc_offset -= sync_offset * NS_PER_SEC;
- do_servo(&servo, dst, phc_offset, phc_ts, kp, ki);
- show_servo(stdout, "phc", phc_offset, phc_ts);
+ update_clock(&dst_clock, phc_offset, phc_ts);
}
return 0;
}
--
1.7.11.7
Miroslav Lichvar
2013-01-14 16:09:13 UTC
Permalink
Signed-off-by: Miroslav Lichvar <***@redhat.com>
---
phc2sys.c | 34 +++++++++++++++++++++-------------
1 file changed, 21 insertions(+), 13 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 9e8d217..4026986 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -227,6 +227,25 @@ static int do_sysoff_loop(struct clock *clock, clockid_t src,
return err;
}

+static int do_phc_loop(struct clock *clock, clockid_t src,
+ int rate, int n_readings, int sync_offset)
+{
+ uint64_t ts;
+ int64_t offset;
+
+ clock->source_label = "phc";
+
+ while (1) {
+ usleep(1000000 / rate);
+ if (!read_phc(src, clock->clkid, n_readings, &offset, &ts)) {
+ continue;
+ }
+ offset -= sync_offset * NS_PER_SEC;
+ update_clock(clock, offset, ts);
+ }
+ return 0;
+}
+
static void usage(char *progname)
{
fprintf(stderr,
@@ -251,8 +270,6 @@ int main(int argc, char *argv[])
{
char *device = NULL, *progname, *ethdev = NULL;
clockid_t src = CLOCK_INVALID;
- uint64_t phc_ts;
- int64_t phc_offset;
int c, phc_readings = 5, phc_rate = 1, sync_offset = 0;
struct clock dst_clock = {
.clkid = CLOCK_REALTIME,
@@ -346,15 +363,6 @@ int main(int argc, char *argv[])
return do_sysoff_loop(&dst_clock, src, phc_rate,
phc_readings, sync_offset);

- dst_clock.source_label = "phc";
-
- while (1) {
- usleep(1000000 / phc_rate);
- if (!read_phc(src, dst_clock.clkid, phc_readings, &phc_offset, &phc_ts)) {
- continue;
- }
- phc_offset -= sync_offset * NS_PER_SEC;
- update_clock(&dst_clock, phc_offset, phc_ts);
- }
- return 0;
+ return do_phc_loop(&dst_clock, src, phc_rate,
+ phc_readings, sync_offset);
}
--
1.7.11.7
Miroslav Lichvar
2013-01-14 16:09:14 UTC
Permalink
Instead of always starting at zero frequency offset, read the currently
stored value on start and pass it to the servo. As the read may silently
fail and return zero, set the clock frequency back to the read value to
make sure it's always equal to the actual frequency of the clock.

Signed-off-by: Miroslav Lichvar <***@redhat.com>
---
phc2sys.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 4026986..452a611 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -76,6 +76,18 @@ static void clock_ppb(clockid_t clkid, double ppb)
fprintf(stderr, "failed to adjust the clock: %m\n");
}

+static double clock_ppb_read(clockid_t clkid)
+{
+ double f = 0.0;
+ struct timex tx;
+ memset(&tx, 0, sizeof(tx));
+ if (clock_adjtime(clkid, &tx) < 0)
+ fprintf(stderr, "failed to read out the clock frequency adjustment: %m\n");
+ else
+ f = tx.freq / 65.536;
+ return f;
+}
+
static void clock_step(clockid_t clkid, int64_t ns)
{
struct timex tx;
@@ -271,6 +283,7 @@ int main(int argc, char *argv[])
char *device = NULL, *progname, *ethdev = NULL;
clockid_t src = CLOCK_INVALID;
int c, phc_readings = 5, phc_rate = 1, sync_offset = 0;
+ double ppb;
struct clock dst_clock = {
.clkid = CLOCK_REALTIME,
.log_file = stdout
@@ -351,9 +364,12 @@ int main(int argc, char *argv[])
perror("clock_settime");
}

- clock_ppb(dst_clock.clkid, 0.0);
+ ppb = clock_ppb_read(dst_clock.clkid);
+ /* The reading may silently fail and return 0, reset the frequency to
+ make sure ppb is the actual frequency of the clock. */
+ clock_ppb(dst_clock.clkid, ppb);

- dst_clock.servo = servo_create(CLOCK_SERVO_PI, 0.0, max_ppb, 0);
+ dst_clock.servo = servo_create(CLOCK_SERVO_PI, -ppb, max_ppb, 0);

if (device)
return do_pps_loop(&dst_clock, device);
--
1.7.11.7
Miroslav Lichvar
2013-01-14 16:09:15 UTC
Permalink
With non-PPS loops let the servo make the inital correction. Move the
code to the PPS loop and change it to use the sample filtering to reduce
the error in the initial correction.

Signed-off-by: Miroslav Lichvar <***@redhat.com>
---
phc2sys.c | 24 ++++++++++++++----------
1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 452a611..466cc0b 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -195,7 +195,8 @@ static int read_pps(int fd, int64_t *offset, uint64_t *ts)
return 1;
}

-static int do_pps_loop(struct clock *clock, char *pps_device)
+static int do_pps_loop(struct clock *clock, char *pps_device,
+ clockid_t src, int n_readings, int sync_offset)
{
int64_t pps_offset;
uint64_t pps_ts;
@@ -208,6 +209,16 @@ static int do_pps_loop(struct clock *clock, char *pps_device)
fprintf(stderr, "cannot open '%s': %m\n", pps_device);
return -1;
}
+
+ /* Make the initial sync from PHC if available. */
+ if (src != CLOCK_INVALID) {
+ if (!read_phc(src, clock->clkid, n_readings,
+ &pps_offset, &pps_ts))
+ return -1;
+ pps_offset -= sync_offset * NS_PER_SEC;
+ clock_step(clock->clkid, -pps_offset);
+ }
+
while (1) {
if (!read_pps(fd, &pps_offset, &pps_ts)) {
continue;
@@ -355,14 +366,6 @@ int main(int argc, char *argv[])
usage(progname);
return -1;
}
- if (src != CLOCK_INVALID) {
- struct timespec now;
- if (clock_gettime(src, &now))
- perror("clock_gettime");
- now.tv_sec += sync_offset;
- if (clock_settime(dst_clock.clkid, &now))
- perror("clock_settime");
- }

ppb = clock_ppb_read(dst_clock.clkid);
/* The reading may silently fail and return 0, reset the frequency to
@@ -372,7 +375,8 @@ int main(int argc, char *argv[])
dst_clock.servo = servo_create(CLOCK_SERVO_PI, -ppb, max_ppb, 0);

if (device)
- return do_pps_loop(&dst_clock, device);
+ return do_pps_loop(&dst_clock, device, src,
+ phc_readings, sync_offset);

if (dst_clock.clkid == CLOCK_REALTIME &&
SYSOFF_SUPPORTED == sysoff_probe(CLOCKID_TO_FD(src), phc_readings))
--
1.7.11.7
Richard Cochran
2013-01-16 19:37:18 UTC
Permalink
Post by Miroslav Lichvar
I thought it would be useful to merge the PI servo implementations in ptp4l and
phc2sys. They are very similar, but there are some improvements and bugs which
were made in one but not the other. This patchset fixes the bugs and adds the
missing features to the ptp4l servo and makes phc2sys use it. Some cleanup is
included.
All applied.

Thanks,
Richard

Loading...