[LinuxPPS] termios et all

William S. Brasher billb958 at door.net
Wed Jun 17 21:34:11 CEST 2009


On Wed, 17 Jun 2009, Udo van den Heuvel wrote:

> Hello,
> 
> I am trying to incorporate the patch to ldattach in refclock_nmea so we
> can use a 'stock' ldattach.
> 
> But I am having no success.
> Also I am seeing strange (?) things.
> 
> An unpatched ldattach logs this when debugging:
> 
> # ./ldattach 18 /dev/ttyS0
> ldattach:opened /dev/ttyS0
> ldattach:get to raw 0 ---: cflag=0x8bc
> ldattach:get to raw 0 ---: iflag=0x105
> ldattach:set to raw 0 ---: cflag=0x8bc
> ldattach:set to raw 0 ---: iflag=0x4
> ldattach:line discipline set to 18
> 
> Notice the change that the unpatched ldattach makes.
> 
> But ntpd starting immediately after that says:
> 
> Jun 17 17:35:28 epia klogd: new PPS source serial0 at ID 0
> Jun 17 17:35:28 epia klogd: PPS source #0 "/dev/ttyS0" added
> Jun 17 17:35:33 epia ntpd[28198]: ntpd 4.2.4p6 at 1.1549-o Wed Jun 17
> 14:20:07 UTC 2009 (1)
> Jun 17 17:35:33 epia ntpd[28199]: precision = 1.554 usec
> Jun 17 17:35:33 epia ntpd[28199]: Listening on interface #0 wildcard,
> 0.0.0.0#123 Disabled
> (....)
> Jun 17 17:35:33 epia ntpd[28199]: Listening on routing socket on fd #27
> for interface updates
> Jun 17 17:35:33 epia ntpd[28199]: kernel time sync status 2040
> Jun 17 17:35:33 epia ntpd[28199]: refclock_nmea: found GPS source
> "/dev/gps0"
> Jun 17 17:35:33 epia ntpd[28199]: get cflag=0x8bc
> Jun 17 17:35:33 epia ntpd[28199]: get iflag=0x105
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ termios ts read from port
> 
> Jun 17 17:35:33 epia ntpd[28199]: set cflag=0x8bc
> Jun 17 17:35:33 epia ntpd[28199]: set iflag=0x105
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ termios ts set to port
> 
> Jun 17 17:35:33 epia ntpd[28199]: refclock_nmea: try "/dev/gpspps0" for PPS
> Jun 17 17:35:33 epia ntpd[28199]: refclock_nmea: found PPS source
> "/dev/gpspps0"
> Jun 17 17:35:33 epia ntpd[28199]: refclock_atom: time_pps_kcbind failed:
> Operation not supported
> Jun 17 17:35:33 epia ntpd[28199]: frequency initialized -114.205 PPM
> from /var/lib/ntp/drift
> 
> So after opening the port the flags cflag/iflag are already like they
> are needed to be.
> So changing them following the patch that William posted appears not
> necessary. (!?)
> 
> But ldattach only works well with ntpd when ldattach HAS the patch that
> William made.
> 
> Who can explain why this stuff works like it does?
> 

Explain?  Termios???  Oh, I don't know about that. :)  But the following 
is what I see on my box.  (This box is a via C3 533 Mhz Epia, 10w board 
running glibc-2.10.1, with util-linux-ng-2.15.1, gcc-4.4.0, and 
linux-2.6.30.)



First, ldattach uses cfmakeraw to set the flags, which does something like
the following to c_iflag (see libc.info, non-canonical input):

   c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON)

which should clear the bits in the structure.  It does this "properly"; 
that is, it grabs of copy of the flags from the port and changes the ones 
it wants to change.  It does change the flags:  there is no way to set 
these particular flags before calling ldattach and have them left alone.



Ntpd refclock_nmea then does something like:

   ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL;

which sets the three bits in c_iflag.  Note that c_flag is set, with no 
concern for what might have been there before.



On my box, "stty -a -F /dev/ttyS0"  shows the following flags changed 
after first running ldattach and then ntpd:

After running "ldattach 18 /dev/ttyS0":
    -ignbrk
    -ignpar
    -icrnl
    min = 1
    -icanon

(At this point," ppstest /dev/pps0" will indicate the presence of pps pulses.)


After running "ntpd -g" the flags are changed to:
     ignbrk
     ignpar
     icrnl
     min = 0
     icanon

Now, ppstest /dev/pps0 will time out.

I do not pretend to understand why changing some flags (by ntpd) after 
ldattach sets up the line discipline kills pps.  Ldattach will start, and 
provide pps pulses, with flags set either way.  It is only when ntpd 
changes the flags that pps pulses stop.



Finally, I am using stty to set the serial port to what ntpd will set it 
before I run ldattach. This ensures that /dev/pps0 will provide a pps 
signal, and that it won't be killed when ntpd is started. Otherwise, the 
pps signal will stop and I have to restart ntpd manually after the box 
boots. 

The following script has, so far, started ntpd under all conditions I've 
left the serial port in:

   /bin/setserial -v /dev/ttyS0 low_latency
   sleep 1
   /bin/stty -F /dev/ttyS0 ispeed 4800 ospeed 4800 \
        -parenb -parodd cs8 -hupcl -cstopb cread clocal -crtscts \
        ignbrk -brkint ignpar -parmrk -inpck -istrip -inlcr -igncr \
        icrnl -ixon -ixoff -iuclc -ixany -imaxbel -iutf8 \
        -opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill \
        -ofdel nl0 cr0 tab0 bs0 vt0 ff0 -isig icanon -iexten \
        -echo -echoe -echok -echonl -noflsh -xcase -tostop \
        -echoprt -echoctl -echoke
   /usr/sbin/ldattach 18 /dev/ttyS0
   /usr/sbin/ntpd -g










More information about the LinuxPPS mailing list