# NTP, LinuxPPS and Gentoo

## hvengel

I have been thinking of hooking up some sort of stratum 0 time source to discipline the clock on my machine.  Not because I need a time source that accurate but because I get a kick out of doing things like that.  Doing a little research I found this site:

http://time.qnan.org/#hardware

That has a detailed description of connecting a Garmain GPS 18 LVC (available for around $64) to a computers serial port (for the PPS time signal) and the USB port for power.  It also has information on how to patch the Linux kernel and setup the software.

I was wondering if anyone here had setup something like this on a gentoo machine and if so how well it worked and what kinds of issues you ran into.

----------

## hvengel

I have installed the LinuxPPS stuff on my machine. I am currently waiting for my PPS GPS to arrive (I should have it in a few days). But it appears that I have everything setup correctly since all of the things that I can test without PPS hardware are working. This stuff is still under heavy development and there are almost daily changes to the code mostly in the form of pre-commit patches that appear on the linuxpps email list. Getting this working involves several different parts.

Kernel

The kernel needs to be patched to add PPS support. I used gentoo-sources-2.6.25-r4 as my base. This was patched with ntp-pps-2.6.24-ter.diff which is the most recent patch set and is located here:

http://ftp.enneenne.com/pub/misc/linuxpps/patches/

This patch has been tested by others against 2.6.25 and it applied cleanly to gentoo-sources-2.6.25-r4.

In addition there are now a set of low level IRQ patches that can optionally be applied. These currently only support x86 and x86_64 class hardware. But these significantly improve the quality of the interrupt time stamps that are gathered which significantly improves clock accuracy and stability. These are only available by digging through the linuxpps email archives which makes them difficult to find since there is no search function for these archives. But I have these patches sitting in my kernel source tree and I can provide them to anyone who asks. These do apply to the above kernel but for one of them the fuzz factor has to be set higher than default.

The above kernel with the above patches applied build cleanly and is working nicely on my x86_64 machine. After adding these patches you will find several new PSS specific kernel config parameters that will need to be set. The LinuxPPS wiki

http://wiki.enneenne.com/index.php/LinuxPPS_support#The_kernel_code

has the details.

The hardest part about this is figuring out what patches to use. I found applying the patches and building the kernel to be fairly simple.

User Land Tools.

There are three user land tools that need to be created. Two of these are in the patched kernel tree and require doing a bunch of work with moving files in /usr/include and creating symlinks from /usr/include to various locations. There are instructions on the LinuxPPS wiki located here

http://wiki.enneenne.com/index.php/LinuxPPS_support#The_userland_tools

The above symlink steps are ugly but this reflects the developmental nature of the code.

There is also a patch for setserial that is located in the same place as the kernel patches. Setserial is optional and the patched setserial can be used instead of the user land tool ppsctl from the patched kernel.

UDEV

UDEV rules need to be added to create the PPS devices. I created /etc/udev/rules.d/10-pps.rules which looks like this:

```
KERNEL=="ttyS1", RUN+="/bin/setserial -v /dev/%k low_latency hardpps", SYMLINK+="oncore.serial.0"

KERNEL=="pps0", OWNER="root", GROUP="uucp", MODE="0660", SYMLINK+="oncore.pps.0", OPTIONS+="last_rule"
```

In this case I named the simlinks based on the PPS device I will be using which is a Motorola OnCore UT+. Also note that the first line is for device (/dev/) ttyS1 which is the serial port I will be using. This will need to be changed based on your hardware. Try to use a serial port that has it's own interrupt (IE. is not sharing an interrupt). Also notice that I am using a patched version of setserial in the RUN section of the first line of the UDEV rules file (see User Land Tools above).

Testing the Kernel and UDEV Changes

After getting things configured to this point and rebooting you should get something like the following:

```

# ls -l /dev/oncore*

lrwxrwxrwx 1 root root 4 Jun  3 02:34 /dev/oncore.pps.0 -> pps0

lrwxrwxrwx 1 root root 5 Jun  3 02:34 /dev/oncore.serial.0 -> ttyS1
```

Thie above is to check to see if your UDEV rules are working.

```
# tree /sys/class/pps

/sys/class/pps

`-- pps0

    |-- assert

    |-- clear

    |-- dev

    |-- device -> ../../../devices/pnp0/00:0c

    |-- echo

    |-- mode

    |-- name

    |-- path

    |-- power

    |   `-- wakeup

    |-- subsystem -> ../../pps

    `-- uevent
```

If you don't see this then either there is a problem with your udev rules or something wrong with your kernel configuration. If your udev rules are not working you can test the kernel setup by running either setserial <your device> hardpps or ppsctl <your device> enable.

If you enabled the ktimer module and the PPS debugging modules in the kernel you should be able to do

```
modprobe ktimer
```

to start an artificial PPS signal for testing and see something like

```
# dmesg

source ktimer got cdev (254:1)                                                             

new PPS source ktimer at ID 1                                                             

ktimer PPS source registered at 1                                                         

PPS event at 4306730085                                                                   

PPS event on source 1 at 1212463272.668278872                                             

capture assert seq #1 for source 1                                                         

PPS event at 4306730385                                                                   

PPS event on source 1 at 1212463273.668278261                                             

capture assert seq #2 for source 1                                                         

PPS event at 4306730685                                                                   

PPS event on source 1 at 1212463274.668279045

```

You can stop the ktimer by doing this

```
# modprobe -r ktimer
```

For more details on checking your installation see:

http://wiki.enneenne.com/index.php/LinuxPPS_support#Checking_the_new_system

NTP

NTP must be rebuilt to include PPS support. In order for this to work you MUST do the user land /usr/include sym-link stuff from the User Land Tools section above. In addition, you must enable the parse-clocks use variable which will add support for all available PPS devices.

In addition ntp will need to have a new server for the local time source added to the /etc/ntp.conf file. In my case this looks like this:

```
server 127.127.30.0
```

127.127 tells ntp that this is a device on the local host and .30 tells ntp that this will use the ONCORE driver (so this depends on your PPS device 20 is generic NMEA and 22 is the Atom clock for example) and .0 tell ntp that this is the first of this specific type of device on this machine. Depending on the PPS device you may also need to add a device configuration file. In my case I created /etc/net.oncore.0 which looks like this:

```
#

# Oncore UT+ configuration file

#

# mandatory lines

MODE 2

LON -122 0.81666666667 # longitude

LAT 37 57.7833333333 # lattitude

HT 11.0 M # GPS height

# optional lines

DELAY 15 NS # delay is approx 5 ns/m cable

ASSERT # change to CLEAR if PPS signal is inverted

SHMEM /var/log/ntpstats/oncore.0

MASK 0

TRAIM YES

HARDPPS
```

In the case of the OnCore driver most of the documentation for the configuration file is located in the source code and this is about the only place to find most of this info. I am not sure how good the docs are for other PPS drivers.

----------

