diff --git a/userspace/tools/Makefile b/userspace/tools/Makefile index c1b464deb556786491e2f8a7111e782f514f61d6..37671652512a0feed84e0f3b1a9b04c8412593d1 100644 --- a/userspace/tools/Makefile +++ b/userspace/tools/Makefile @@ -96,6 +96,7 @@ nmea/nmea.o: nmea/nmea.h wr_irig.o: wr_irig.h wr_date: nmea/wr_nmea.o nmea/nmea.o nmea/serial_linux.o wr_date: wr_irig.o +wr_date: LDFLAGS+=-lrt wr_date: wr_date.o time_lib.o ${CC} -o $@ $^ $(LDFLAGS) diff --git a/userspace/tools/wr_date.c b/userspace/tools/wr_date.c index 553e1b80f62ad8791c9174e6dda157203fc42f48..e1f281eafc766a8bdecaa4ad319fa8440b022966 100644 --- a/userspace/tools/wr_date.c +++ b/userspace/tools/wr_date.c @@ -172,6 +172,9 @@ static int wrdate_get_nmea_utc(int64_t *t_out) static int wrdate_get_irig_utc(int64_t *t_out) { + if (irig_wait_sec_transition(&wr_irig) < 0) + return -1; + if(irig_read_utc(&wr_irig, t_out) < 0){ fprintf(stderr, "wr_date: %s: error reading irig\n", __func__); return -1; @@ -199,6 +202,7 @@ static int wrdate_gettimeofday(struct timeval *tv) tv->tv_usec = 1000000 - (ret - 1)*1000000/opt_nmea_baud; return ret; }else if(opt_irig_en){ + /* Is blocking! */ return wrdate_get_irig_utc((int64_t *)&tv->tv_sec); } else { return gettimeofday(tv, NULL); @@ -229,7 +233,7 @@ int wrdate_get(volatile struct PPSG_WB *pps, int tohost) tmp2 = pps->CNTR_UTCLO; } while((tmp1 != taih) || (tmp2 != tail)); - /* Note for NMEA this function is blocking! */ + /* Note for NMEA and IRIG-B function is blocking! */ if (wrdate_gettimeofday(&tv) < 0) return 1; @@ -638,10 +642,11 @@ int wrdate_stat(volatile struct PPSG_WB *pps) { int udiff_ref=0,udiff_last; int stat_sample_count = STAT_SAMPLE_COUNT; + struct timeval tv_tai,tv_host; - if (opt_nmea_en) { - /* wrdate_gettimeofday for NMEA is blocking till the boundary - * of a second (+some time) */ + if (opt_nmea_en || opt_irig_en) { + /* wrdate_gettimeofday for NMEA and IRIG-B is blocking till + * the boundary of a second (+some time) */ stat_sample_count = 1; } @@ -651,7 +656,6 @@ int wrdate_stat(volatile struct PPSG_WB *pps) printf("Diff_TAI_UTC[sec] Diff_with_last[usec] Diff_with_ref[usec]\n"); while ( 1 ) { int64_t udiff_arr[STAT_SAMPLE_COUNT]; // Diff in useconds - struct timeval tv_tai,tv_host; int i; int64_t udiff_sum=0, udiff; @@ -685,8 +689,9 @@ int wrdate_stat(volatile struct PPSG_WB *pps) ); udiff_last=udiff; - /* Readout for NMEA will wait till the boundary of a second anyway */ - if (!opt_nmea_en) { + /* Readout for NMEA or IRIG-B will wait till the boundary of + * a second anyway */ + if (!opt_nmea_en && !opt_irig_en) { sleep(1); } } diff --git a/userspace/tools/wr_irig.c b/userspace/tools/wr_irig.c index 8a86ef111214d1a9eb763e37a4cc536c3947b7db..97817b8ebff9bc53d537a481c4880ef53316d3b6 100644 --- a/userspace/tools/wr_irig.c +++ b/userspace/tools/wr_irig.c @@ -4,12 +4,81 @@ #include <unistd.h> #include <string.h> #include <errno.h> +#include <time.h> +#include <signal.h> #include <fcntl.h> #include <sys/mman.h> #include <libwr/wrs-msg.h> #include "wr_irig.h" +#define IRIGB_TIMEOUT_MS 10 * 1000 + +static int init_alarm_done = 0; +static volatile int alarmDetected = 0; +static timer_t timer_irigb; + +static void sched_handler(int sig, siginfo_t *si, void *uc) +{ + alarmDetected = 1; +} + +static void init_alarm(timer_t *timerid) +{ + struct sigevent sev; + struct sigaction sa; + + /* Set the signal handler */ + sa.sa_flags = SA_SIGINFO; + sa.sa_sigaction = sched_handler; + sigemptyset(&sa.sa_mask); + if (sigaction(SIGALRM, &sa, NULL) == -1) { + fprintf(stderr, "wr_irigb: cannot set signal handler\n"); + exit(1); + } + + /* Create the timer */ + sev.sigev_notify = SIGEV_SIGNAL; + sev.sigev_signo = SIGALRM; + sev.sigev_value.sival_ptr = timerid; + if (timer_create(CLOCK_MONOTONIC, &sev, timerid) == -1) { + fprintf(stderr, "wr_irig: Cannot create timer\n"); + exit(1); + } +} + +static void start_alarm(timer_t *timerid, unsigned int delay_ms) +{ + struct itimerspec its; + + its.it_value.tv_sec = delay_ms/1000; + its.it_value.tv_nsec = (delay_ms%1000) * 1000000; + its.it_interval.tv_sec = 0; + its.it_interval.tv_nsec = 0; + + if (timer_settime(*timerid, 0, &its, NULL) == -1){ + fprintf(stderr, "wr_irig: Cannot start timer. DelayMs=%u. Errno=%d\n",delay_ms, errno); + } +} + +static unsigned int stop_alarm(timer_t *timerid) +{ + struct itimerspec its; + struct itimerspec ito; + + its.it_value.tv_sec = 0; + its.it_value.tv_nsec = 0; + its.it_interval.tv_sec = 0; + its.it_interval.tv_nsec = 0; + + if (timer_settime(*timerid, 0, &its, &ito) == -1){ + fprintf(stderr, "wr_irig: Cannot stop timer\n"); + return 0; + } + return (int) (ito.it_value.tv_sec*1000+ito.it_value.tv_nsec/1000000); +} + + static int irig_get_time(struct irig_slave *irig, struct irig_time *t) { uint32_t tod = irig->TOD; @@ -194,6 +263,49 @@ int irig_read_utc(struct wr_irig *wr_irig, int64_t *t_out) return 0; } +int irig_wait_sec_transition(volatile struct wr_irig *wr_irig) +{ + uint32_t new_tod; + uint32_t ref_tod = 0; + + uint32_t valid = 0; + + if (!init_alarm_done) { + init_alarm(&timer_irigb); + init_alarm_done = 1; + } + + start_alarm(&timer_irigb, IRIGB_TIMEOUT_MS); + /* Wait until get valid TOD */ + while (!valid && !alarmDetected) { + ref_tod = wr_irig->irig->TOD; + valid = (ref_tod & IRIG_SLAVE_TOD_VALID); + } + + if (alarmDetected) { + printf("Timeout on waiting for valid IRIG-B signal\n"); + return -1; + } + + alarmDetected = 0; + start_alarm(&timer_irigb, IRIGB_TIMEOUT_MS); + valid = 0; + new_tod = ref_tod; + while (!valid || (new_tod & IRIG_SLAVE_TOD_SECONDS_MASK) == (ref_tod & IRIG_SLAVE_TOD_SECONDS_MASK)) { + new_tod = wr_irig->irig->TOD; + valid = (new_tod & IRIG_SLAVE_TOD_VALID); + } + + stop_alarm(&timer_irigb); + + if (alarmDetected) { + printf("Timeout on waiting for new IRIG-B second\n"); + return -2; + } + + return 0; +} + int irig_enable(struct wr_irig *wr_irig, int en) { wr_irig->irig->CR = (en ? IRIG_SLAVE_CR_ENABLE : 0); diff --git a/userspace/tools/wr_irig.h b/userspace/tools/wr_irig.h index 19998df7e17c322a6bfad8b41211dc7233ada8f2..9774dfdfc00c20e898b7019306738090d1bef485 100644 --- a/userspace/tools/wr_irig.h +++ b/userspace/tools/wr_irig.h @@ -21,5 +21,6 @@ struct wr_irig{ int irig_enable(struct wr_irig *wr_irig, int en); int irig_enable_status(struct wr_irig *wr_irig); int irig_read_utc(struct wr_irig *wr_irig, int64_t *t_out); +int irig_wait_sec_transition(volatile struct wr_irig *wr_irig); #endif