[LinuxPPS] refclock_nmea patch

Rodolfo Giometti giometti at enneenne.com
Tue Oct 23 18:00:39 CEST 2007


On Tue, Oct 23, 2007 at 05:41:07PM +0200, Udo van den Heuvel wrote:
> Rodolfo Giometti wrote:
> > On Tue, Oct 23, 2007 at 05:54:43AM +0200, Udo van den Heuvel wrote:
> >> You mean NMEA when you say 'GPS data source'?
> >> I think both, looking at the code. (where the PPS API interface is started)
> > 
> > But when you talk about /dev/gps0 you point __only__ the GPS data
> > source, while you talk about /dev/pps0 you point __only__ the PPS data
> > source. NMEA is represented by both /dev/gps0 __and__ /dev/pps0.
> 
> Yes, but now what if we have a device with one /dev/bla giving NMEA and
> another /dev/duh giving PPS?
> How is the first /dev/bla passed on to ntpd?
> I don't get this yet.
> 
> In my own situation we have NMEA and PPS on teh same RS232 port.
> I then expect the first link that I apss to LinuxPPS to be used, which
> isn't.

The first (or main) device is the GPS data source (/dev/ttyS0 in your
case) which __could__ be also a PPS data source. If not (as in
LinuxPPS devices) you need the alternate device to get PPS data.

> >>> The former is correct beacuse /dev/gps0 is _not_ a PPS source, it's a
> >>> serial line (points to /dev/ttyS0), the latter I don't know. :)
> >> We open a fd on a device, do time_pps_create and when it fails, we open
> >> the fd on another device, do another time_pps_create...
> >> So the fd is not saved.
> >> So how can ntpd use the first device for NMEA and the second for PPS?
> > 
> > I don't know NMEA code but it seems to me you are working inside a
> > function, 
> 
> Yes.
> 
> > is the fd passed to it? 
> 
> No, it opens a fd on a com port at the start of the function.

See below.

> > If not you have to save fd
> > somewhere, maybe in up->fd?
> 
> So that is the place for the NMEA source?
> And the return(nmea_ppsapi(peer, 0, 0)); is for the PPS?

See below.

> >> Maybe this can help:
> >> When is the /dev entry (pps0) created?
> >> Based on what input?
> > 
> > If you have udev when the pps device is created, otherwise you have to
> > create it by yourself by using mknod.
> 
> It was there, so udev works I guess.
> How is decided what port is to be created?

The system decides the PPS id just the ethernet devices.

> I once had a /dev/gps0 and /dev/pps0 pointing to /dev/ttyS0.
> /dev/pps0 was replaced by the new device entry.
> Why?

No you should have:

	/dev/gps0 -->	/dev/ttyS0
	/dev/pps0

> > I don't know NMEA code but maybe here you are overriding the GPS data
> > source file descriptor... if so you should use different variable
> > (pps_fd?).
> > 
> > Can you please post the whole function you are modifying so I can
> > understand if the fd should be renamed or not?
> 
> /*
>  * nmea_start - open the GPS devices and initialize data for processing
>  */
> static int
> nmea_start(
>         int unit,
>         struct peer *peer
>         )
> {
>         register struct nmeaunit *up;
>         struct refclockproc *pp;
>         int fd;
>         char device[20];
> 
>         /*
>          * Open serial port. Use CLK line discipline, if available.
>          */
>         (void)sprintf(device, DEVICE, unit);
> 
>         fd = refclock_open(device, SPEED232, LDISC_CLK);
>         if (fd <= 0) {
> #ifdef HAVE_READLINK
> (nmead stuff cut)
> #endif
>         }
> 
>         /*
>          * Allocate and initialize unit structure
>          */
>         up = (struct nmeaunit *)emalloc(sizeof(struct nmeaunit));
>         if (up == NULL) {
>                 (void) close(fd);
>                 return (0);
>         }
>         memset((char *)up, 0, sizeof(struct nmeaunit));
>         pp = peer->procptr;
>         pp->io.clock_recv = nmea_receive;
>         pp->io.srcclock = (caddr_t)peer;
>         pp->io.datalen = 0;
>         pp->io.fd = fd;

Here the fs is saved, so everything is ok.

>         if (!io_addclock(&pp->io)) {
>                 (void) close(fd);
>                 free(up);
>                 return (0);
>         }
>         pp->unitptr = (caddr_t)up;
> 
>         /*
>          * Initialize miscellaneous variables
>          */
>         peer->precision = PRECISION;
>         pp->clockdesc = DESCRIPTION;
>         memcpy((char *)&pp->refid, REFID, 4);
>         up->pollcnt = 2;
>         gps_send(pp->io.fd,"$PMOTG,RMC,0000*1D\r\n", peer);
> 
> #ifdef HAVE_PPSAPI
>         /*
>          * 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) {
>                 /* Try the alternate PPS device */
>                 (void) sprintf(device, DEVICEPPS, unit);
>                 msyslog(LOG_ERR, "refclock_nmea: try alternate PPS
> device \"%s\"", device);
>                 fd = open(device, O_RDWR);
>                 if (fd < 0)
>                         goto pps_error;
>                 if (time_pps_create(fd, &up->handle) < 0)
>                         goto pps_error;
>         }
>         else (void) sprintf(device, DEVICE, unit); /* just rebuild
> device's name */
>         msyslog(LOG_INFO, "refclock_nmea: found PPS source \"%s\"", device);
>         return(nmea_ppsapi(peer, 0, 0));
> #else
>         return (1);
> #endif /* HAVE_PPSAPI */

Good! It's ok.

> Here it is.
> I hope we can fix this issue and do some testing and send it to teh ntpd
> folks this weekend?

Yes. I hope so. Please check the /dev/gps0 points to /dev/ttyS0 and
not to /dev/pps0, then consider as main device /dev/gps0 (where you
should get GPS/NMEA data) and as alternate device /dev/pps0 (where you
should get PPS data).

Ciao,

Rodolfo

-- 

GNU/Linux Solutions                  e-mail:    giometti at enneenne.com
Linux Device Driver                             giometti at gnudd.com
Embedded Systems                     		giometti at linux.it
UNIX programming                     phone:     +39 349 2432127



More information about the LinuxPPS mailing list