phc2sys: read PHC with each PPS sample.

In the PPS loop, instead of setting the system clock from the PHC only
once on start, read PHC with each PPS sample and use the time stamp to
get the whole number of seconds in the offset. This will prevent phc2sys
from losing track of the system clock.

Also, check if the PPS is synchronized to the PHC.

Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
master
Miroslav Lichvar 2013-01-17 18:31:39 +01:00 committed by Richard Cochran
parent f09b4bb7e3
commit c5ce4ef764
2 changed files with 29 additions and 13 deletions

View File

@ -60,8 +60,8 @@ option should be used too.
Specify the master clock by device (e.g. /dev/ptp0) or name (e.g. CLOCK_REALTIME Specify the master clock by device (e.g. /dev/ptp0) or name (e.g. CLOCK_REALTIME
for the system clock). When this option is used together with the for the system clock). When this option is used together with the
.B \-d .B \-d
option, the master clock is read only on start to fix an offset over 0.5 option, the master clock is used only to correct the offset by whole number of
seconds which cannot be fixed with PPS alone. seconds, which cannot be fixed with PPS alone.
.TP .TP
.BI \-i " interface" .BI \-i " interface"
Similar to the Similar to the

View File

@ -46,6 +46,8 @@
#define max_ppb 512000 #define max_ppb 512000
#define PHC_PPS_OFFSET_LIMIT 10000000
static clockid_t clock_open(char *device) static clockid_t clock_open(char *device)
{ {
int fd; int fd;
@ -198,8 +200,8 @@ static int read_pps(int fd, int64_t *offset, uint64_t *ts)
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) clockid_t src, int n_readings, int sync_offset)
{ {
int64_t pps_offset; int64_t pps_offset, phc_offset;
uint64_t pps_ts; uint64_t pps_ts, phc_ts;
int fd; int fd;
clock->source_label = "pps"; clock->source_label = "pps";
@ -210,19 +212,33 @@ static int do_pps_loop(struct clock *clock, char *pps_device,
return -1; 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) { while (1) {
if (!read_pps(fd, &pps_offset, &pps_ts)) { if (!read_pps(fd, &pps_offset, &pps_ts)) {
continue; continue;
} }
/* If a PHC is available, use it to get the whole number
of seconds in the offset and PPS for the rest. */
if (src != CLOCK_INVALID) {
if (!read_phc(src, clock->clkid, n_readings,
&phc_offset, &phc_ts))
return -1;
/* Convert the time stamp to the PHC time. */
phc_ts -= phc_offset;
/* Check if it is close to the start of the second. */
if (phc_ts % NS_PER_SEC > PHC_PPS_OFFSET_LIMIT) {
fprintf(stderr, "PPS is not in sync with PHC"
" (0.%09lld)\n", phc_ts % NS_PER_SEC);
continue;
}
phc_ts = phc_ts / NS_PER_SEC * NS_PER_SEC;
pps_offset = pps_ts - phc_ts;
pps_offset -= sync_offset * NS_PER_SEC;
}
update_clock(clock, pps_offset, pps_ts); update_clock(clock, pps_offset, pps_ts);
} }
close(fd); close(fd);