[LinuxPPS] Re: [Bug 610] Generic NMEA GPS Receiver driver w/ PPS expects PPS after NMEA data

Udo van den Heuvel udovdh at xs4all.nl
Sun Oct 28 13:32:29 CET 2007


Udo van den Heuvel wrote:
>> So first open /dev/gpspps0 to get PPS there
>> 	- if it fails, use /dev/gps0 next
>> 	- if it succeeds get PPS
>> Then open /dev/gps0 to get NMEA and *optionally* PPS
>>
>>
>> Is this the right approach?
> 
> So I coded:
(cut)

Nobody replied so far, so I tried:

Oct 28 13:25:00 epia ntpd[10304]: ntpd 4.2.4p2 at 1.1495-o Sat Oct 27
13:36:00 UTC 2007 (1)
Oct 28 13:25:00 epia ntpd[10305]: precision = 1.000 usec
Oct 28 13:25:00 epia ntpd[10305]: Listening on interface #0 wildcard,
0.0.0.0#123 Disabled
(...)
Oct 28 13:25:01 epia ntpd[10305]: Listening on interface #11 ppp0,
82.92.197.115#123 Enabled
Oct 28 13:25:01 epia ntpd[10305]: kernel time sync status 0040
Oct 28 13:25:01 epia ntpd[10305]: refclock_nmea: found GPS source
"/dev/gps0"
Oct 28 13:25:01 epia ntpd[10305]: refclock_nmea: try "/dev/gpspps0" for PPS
Oct 28 13:25:01 epia ntpd[10305]: refclock_nmea: found PPS source
"/dev/gpspps0"
Oct 28 13:25:01 epia ntpd[10305]: refclock_nmea: time_pps_kcbind failed:
Operation not supported
Oct 28 13:25:01 epia ntpd[10305]: refclock_atom: time_pps_kcbind failed:
Operation not supported
Oct 28 13:25:02 epia ntpd[10305]: frequency initialized -144.226 PPM
from /var/lib/ntp/drift

Giving after a short while:

# ntpq -pn
     remote           refid      st t when poll reach   delay   offset
jitter
==============================================================================
 127.127.1.0     .LOCL.          10 l   29   64    7    0.000    0.000
 0.001
+127.127.20.0    .GPS.            0 l    8   16  377    0.000    0.734
 0.056
o127.127.22.0    .PPS.            0 l   13   16   37    0.000    0.743
 0.013
 194.109.22.18   193.79.237.14    2 u   30   64    7    8.088    0.776
 1.948

I attached the patch.
For this patch I made a link in /dev since we need to able to
distinguish a specific NMEA driver PPS source (and optionally fall back
to /dev/gps0 for PPS):

# ls -al /dev/*pps*
lrwxrwxrwx 1 root root      9 2007-10-28 13:24 /dev/gpspps0 -> /dev/pps0
crw------- 1 root root 254, 0 2007-10-23 19:30 /dev/pps0

Please comment.

-------------- next part --------------
--- /usr/src/redhat/ntp-4.2.4p2/ntpd/refclock_nmea.c	2006-06-06 22:16:53.000000000 +0200
+++ refclock_nmea.c	2007-10-28 11:00:37.000000000 +0100
@@ -61,6 +61,7 @@
 # define DEVICE "COM%d:" 	/* COM 1 - 3 supported */
 #else
 # define DEVICE	"/dev/gps%d"	/* name of radio device */
+# define DEVICEPPS "/dev/gpspps%d" /* name of alternate PPS radio device */
 #endif
 #define	SPEED232	B4800	/* uart speed (4800 bps) */
 #define	PRECISION	(-9)	/* precision assumed (about 2 ms) */
@@ -71,6 +72,7 @@
 #define RANGEGATE	500000	/* range gate (ns) */
 
 #define LENNMEA		75	/* min timecode length */
+#define LENPPS		PPS_MAX_NAME_LEN
 
 /*
  * Tables to compute the ddd of year form icky dd/mm timecode. Viva la
@@ -230,16 +232,35 @@
 	 * Start the PPSAPI interface if it is there. Default to use
 	 * the assert edge and do not enable the kernel hardpps.
 	 */
-	if (time_pps_create(fd, &up->handle) < 0) {
-		up->handle = 0;
-		msyslog(LOG_ERR,
-		    "refclock_nmea: time_pps_create failed: %m");
-		return (1);
+	msyslog(LOG_ERR, "refclock_nmea: found GPS source \"%s\"", device);
+        (void) sprintf(device, DEVICEPPS, unit);
+        fd = open(device, O_RDWR);
+        if (fd < 0) { /* no /dev/gpspps0 */
+		/* Try the /dev/gps device for PPS */
+                (void) sprintf(device, DEVICE, unit);
+		msyslog(LOG_ERR, "refclock_nmea: try GPS device \"%s\" for PPS", device);
+		if (time_pps_create(pp->io.fd, &up->handle) < 0)
+               		goto pps_error;
+	} else {  /* /dev/gpspps0 exists */
+		msyslog(LOG_ERR, "refclock_nmea: try \"%s\" for PPS", device);
+		if (time_pps_create(fd, &up->handle) < 0) { 
+			/* no PPS on /dev/gpspps0 */
+			if (time_pps_create(pp->io.fd, &up->handle) < 0)
+       				goto pps_error; /* no PPS on /dev/gps0 */
+			else (void) sprintf(device, DEVICE, unit);
+		}
 	}
+	msyslog(LOG_INFO, "refclock_nmea: found PPS source \"%s\"", device);
 	return(nmea_ppsapi(peer, 0, 0));
 #else
 	return (1);
 #endif /* HAVE_PPSAPI */
+
+pps_error:
+	/* No luck, no PPS unit available! */
+	up->handle = -1;
+	msyslog(LOG_ERR, "refclock_nmea: no PPS devices found at " DEVICE " nor " DEVICEPPS ": %m", unit, unit);
+	return (1);
 }
 
 /*
@@ -257,8 +278,7 @@
 	pp = peer->procptr;
 	up = (struct nmeaunit *)pp->unitptr;
 #ifdef HAVE_PPSAPI
-	if (up->handle != 0)
-		time_pps_destroy(up->handle);
+	time_pps_destroy(up->handle);
 #endif /* HAVE_PPSAPI */
 	io_closeclock(&pp->io);
 	free(up);
@@ -366,7 +386,7 @@
 	/*
 	 * Convert the timespec nanoseconds field to ntp l_fp units.
 	 */ 
-	if (up->handle == 0)
+	if (up->handle == -1)
 		return (0);
 	timeout.tv_sec = 0;
 	timeout.tv_nsec = 0;


More information about the LinuxPPS mailing list