[LinuxPPS] More on problem with the PPS Device.

clemens at dwf.com clemens at dwf.com
Sun Jun 29 00:10:08 CEST 2008


I have followed up on a suggestion by Rodolfo, but it hasn't clarified
anything in my mind.  Attached is my version of ppsapitest.c, which
has two commented out lines at about line 60.  You can run it with
either both lines commented out, or uncomment one or the other.

As it stands it does not run with the current patch and 2.6.24.4, and dies
with the message

	Can't open fd2 (/dev/pps1)

So, it opens /dev/ttyS0, does the set of the line discipline, but then cant
(immediately) open /dev/pps1.

My solution was to put a 

	sleep(5)

between the open of the line distribution and the open of /dev/pps1
and this works.  My assumption is that something that Rodolfo is
doing in the kernel to create /dev/pps1 is NOT being done immediately
but is rather being put on a kernel queue, and being done later.  With
the 5second delay, we outwait it.

With the 5 second delay inserted, there is a 5sec delay, and then the
program starts returning timestamps.

Rodolfo's suggestion was that it might be a udev problem and suggested
that I try to build /dev/pps1 by hand.  OK, removed the sleep, and
replaced it with

	system("mknod /dev/pps1 c 254 1");

if udev is still running, and the code has the above line in it, I see the
error message

	mknod: `/dev/pps1': File exists

and I start receiving timestamps.

If I kill udev, and run the test program, then it runs, giving timestamps,
WITHOUT giving any error message.

If I run it AGAIN then I get the 'File exists' error message, and /dev/pps1
still exists after the process terminates.  It would seem to me that when
the process ends that /dev/pps1 would go away, but mabe thats something
that udev does... Strange.

So thats the story as I see it.
There appears to be some sort of timing problem with the current code.
    * A wait of 5 seconds will out-wait the problem
    * The mknod system call seems to hang and wait for the device to be made

It would seem, that, finding and fixing the place where the code should be 
waiting
for something to complete is the correct solution.

I would suggest that showing the above sequence of events to Alan Cox would
probably be enough for him to say, 'Oh Yes...' and come up with a solution.

-- 
                                        Reg.Clemens
                                        reg at dwf.com

-------------- next part --------------
#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>
#include <sys/types.h>
#include <sys/stat.h>
#include <termios.h>
#include <errno.h>
#include <sys/ioctl.h>

/* PPSAPI test */

void exit();

int
main(int argc, char **argv)
{
	int i, fd2, mode, fd1, ldisc;
	char *device2, c, Msg[200];
	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 ((fd1=open("/dev/ttyS0", B9600, O_RDWR))< 0) {
		fprintf(stderr, "Cant open ttyS0, error = %d\n", i);
		perror("aa");
		exit(1);
	}

#define N_PPS 17
	fprintf(stderr, ">>>> Inside ifdef\n");
	/* linuxPPS specific Code */

	stat2.st_dev = stat2.st_ino = -1;
	ldisc = N_PPS;
	if (!ioctl(fd1, TIOCSETD, &ldisc))
		goto test_fd2;  /* was able to set N_PPS line discipline */

	/* here could not set the line discipline, treat as tty */

	sprintf(Msg, "unable to set line discipline \"%d\" for device /dev/ttyS0\n", ldisc);
	fprintf(stderr, Msg);
	fprintf(stderr, "hope it's ok\n");

test_fd2:
/*      sleep(5);       */
/* system("mknod /dev/pps1 c 254 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);

	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_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 || oldc != pi.clear_sequence) {
			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("getparam assert is %ld  %07ld\n", pp.assert_offset.tv_sec, pp.assert_offset.tv_nsec);
			printf("getparam clear  is %ld  %07ld\n", pp.clear_offset.tv_sec, pp.clear_offset.tv_nsec);

			printf("A: %lu.%09ld #%lu     C: %lu.%09ld #%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;
		}
	}

	exit(0);
}


More information about the LinuxPPS mailing list