[LinuxPPS] Something Funny going on with linuxPPS (again).

clemens at dwf.com clemens at dwf.com
Thu Oct 18 22:02:28 CEST 2007


Rodolfo:-

I guess I dont understand why my statement that there is something wrong is
so hard to understand.  But perhaps we are working from different directions.

My assumption about the kernel code is that the pps driver has one location 
each
to save the most recent ASSERT and CLEAR time stamps.  When either of these
events takes place the timestamp is updated.

My assumption is that when the user code calls time_pps_fetch, he is presented
with the contents of these two locations.

Thus, if either timestamp CHANGES it has to be at a LATER time than any 
previous
timestamp.

Here is the code that is producing the output that I showed in my previous
two e-mails.  Its a slight modification of something I have been using for 
years.

---

#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <err.h>
#include <sys/types.h>
#include <time.h>
#include <timepps.h>
#include <string.h>

/* PPSAPI test */

void exit();

int
main(int argc, char **argv)
{
        int i, fd2, mode;
        char *device2, c;
        struct stat stat2;
        u_int olda, oldc;
        pps_info_t pi;
        pps_params_t pp;
        pps_handle_t ph;
        struct timespec timeout;

        olda = oldc = 0;
        if (argc == 2)
                device2 = argv[1];
        else
                device2 = "/dev/pps1";

        if (stat(device2, &stat2)) {
                fprintf(stderr, "Can't stat fd2 (%s)\n", device2);
                exit(1);
        }

        if ((fd2=open(device2, O_RDWR)) < 0) {
                fprintf(stderr, "Can't open fd2 (%s)\n", device2);
                exit(1);
        }

fprintf (stderr, "fd2 = %d\n", fd2);
        if ((i = time_pps_create(fd2, &ph)) < 0) {
                fprintf(stderr, "create returns %d\n", i);
                fprintf(stderr, "FAIL: time_pps_create\n");
                exit(1);
        }

        if ((i = time_pps_getcap(ph, &mode)) < 0) {
                printf("FAIL: getcap %d\n", i);
                exit(1);
        }

        printf("getcap says 0x%x\n", mode);

        if ((i = time_pps_getparams(ph, &pp)) <0) {
                printf("time_pps_getparams\n");
                perror("getparams:");
                exit (1);
        }
        printf("getparam is 0x%x\n", pp.mode);

        mode = mode & PPS_CAPTUREBOTH;     /* */
        pp.mode |= mode;
        pp.mode |= PPS_TSFMT_TSPEC;

        printf("set mode to 0x%x\n", pp.mode);

        if ((i = time_pps_setparams(ph, &pp)) <0) {
                printf("time_pps_setparams\n");
                perror("setparams:");
                exit (1);
        }

        if ((i = time_pps_getparams(ph, &pp)) <0) {
                printf("time_pps_getparams\n");
                perror("getparams:");
                exit (1);
        }

        printf("getparam is 0x%x\n", pp.mode);
        printf("Enter loop\n\n");

        while (1) {
                timeout.tv_sec = 0;
                timeout.tv_nsec = 0;

                i = time_pps_fetch(ph, PPS_TSFMT_TSPEC, &pi, &timeout);
                if (i < 0) {
                        err(1, "time_pps_fetch");
                        perror("fetch:");
                }

                if (olda != pi.assert_sequence) {
                        printf("A: %lu.%09lu #%lu\n",
                                pi.assert_timestamp.tv_sec,
                                pi.assert_timestamp.tv_nsec,
                        olda = pi.assert_sequence;
                }
                if (oldc != pi.clear_sequence) {
                        printf("                           C: %lu.%09lu 
#%lu\n",
                                pi.clear_timestamp.tv_sec,
                                pi.clear_timestamp.tv_nsec,
                                pi.clear_sequence);
                        oldc = pi.clear_sequence;
                }
                usleep(25000);
        }

        exit(0);
}

---

The only significant thing is the print loop at the very end.
You will note that I loop forever, with a usleep of 25ms in the loop.
In the printouts, the Assert and Clear timestamps are separated by 100ms, so
I am picking up these timestamps INDIVIDUALLY, with 3 wasted passes thru the
loop between the closest pair.

My code only prints a timestamp if its sequence number has changed, and then
goes on to test the other timestamp.

BUT, LET ME SIMPLIFY THE PRINT LOOP ABOVE TO READ:

---

        while (1) {
                timeout.tv_sec = 0;
                timeout.tv_nsec = 0;

                i = time_pps_fetch(ph, PPS_TSFMT_TSPEC, &pi, &timeout);
                if (i < 0) {
                        err(1, "time_pps_fetch");
                        perror("fetch:");
                }

                if (olda != pi.assert_sequence || oldc != pi.clear_sequence) {
                        printf("A: %lu.%09lu #%lu     C: %lu.%09lu #%lu\n",
                            pi.assert_timestamp.tv_sec,
                            pi.assert_timestamp.tv_nsec,
                            pi.assert_sequence,

                            pi.clear_timestamp.tv_sec,
                            pi.clear_timestamp.tv_nsec,
                            pi.clear_sequence);

                        olda = pi.assert_sequence;
                        oldc = pi.clear_sequence;
                }
                usleep(25000);
        }

---

Now there can be no question about what is being printed.
If EITHER sequence number changes, BOTH the timestamps are printed.

>From my model of what is going on back in paragraph #2 and #3, then
if the timestamps for assert or clear changes that has to be at a LATER
time than any previous timestamp.  I assume we could miss a timestamp
but TIME CANT GO BACKWARD.

OK, with the revised code, here is what I see:

---

[root at deneb Testing]# a.out
fd2 = 3
getcap says 0x1133
getparam is 0x1113
set mode to 0x1113
getparam is 0x1113
Enter loop

A: 1192735322.3294920979 #519275     C: 1192735320.199030176 #519273
A: 1192735322.3294920979 #519275     C: 1192735321.198078199 #519274
A: 1192735323.3294920022 #519276     C: 1192735321.198078199 #519274
A: 1192735323.3294920022 #519276     C: 1192735322.198128892 #519275
A: 1192735324.3294921470 #519277     C: 1192735322.198128892 #519275
A: 1192735324.3294921470 #519277     C: 1192735323.198182237 #519276
A: 1192735325.3294920164 #519278     C: 1192735323.198182237 #519276
A: 1192735325.3294920164 #519278     C: 1192735324.198232809 #519277
A: 1192735326.3294921868 #519279     C: 1192735324.198232809 #519277
A: 1192735326.3294921868 #519279     C: 1192735325.198283561 #519278
A: 1192735327.3294920505 #519280     C: 1192735325.198283561 #519278
A: 1192735327.3294920505 #519280     C: 1192735326.198334891 #519279
A: 1192735328.3294922290 #519281     C: 1192735326.198334891 #519279
A: 1192735328.3294922290 #519281     C: 1192735327.198387674 #519280
A: 1192735329.3294920361 #519282     C: 1192735327.198387674 #519280
A: 1192735329.3294920361 #519282     C: 1192735328.198438926 #519281

---

Let me extract the (tens of seconds) from the timestamps from lines 2-6

        22.3    21.1*
        23.3*   21.1
        23.3    22.1*
        24.3*   22.1
        24.3    23.1*

Time is increasing from top to bottom, the '*' show which item changed.
We see the assert timestamp in Col 1 change from 22.3->23.3.
Then how can the next change be for the Clear timestamp to change
from 21.1->22.1 ????  If it changes it has to be LATER than the 23.3 time
we have already seen.

This is what doesn't make any sense to me.

And this comes after seeing some VERY strange results in NTP.
I would find the NTP on Linux running choosing the LOCAL clock
and a remote machine running FreeBSD as its standard rather than
the LinuxPPS interfaced GPS unit.  It would be showing an offset of
-2sec from the GPS unit.  At the same time everything was running fine with
the ntp on FreeBSD.

I finally backed it up to these problems with the times of changes not
being in increasing order.

I really gota' look at that kernel code.

Sorry for the long explanation, but I just couldnt figure out how to
say it any more compactly.

                                        Reg.Clemens
                                        reg at dwf.com





More information about the LinuxPPS mailing list