Part 1 was about the hardware, now for the software
Step 1: pps-gpio-poll package
This architecture doesn't support device tree yet, so it has a special pps driver. The repo for the driver package is at https://github.com/mlichvar/openwrt-pps-gpio-poll
I downloaded the lede-sdk for the ar71xx platform, and put the above git repo under the sdk's package/ dir.
# update the packages ./scripts/feeds update # create a local signing key ./staging_dir/host/bin/usign -G -s ./key-build -p ./key-build.pub -c "Local build key" # build the new package make # new package should be in this dir ls bin/targets/ar71xx/generic/packages/*pps*
Step 2: build openwrt/lede image
Then I downloaded the lede-imagebuilder and built a sysupgrade image for my router. I already had openwrt on my TL-MR3020, so I'll be using sysupgrade to write the image to flash.
# change __LEDE_IMAGEBUILDER_DIR__ to whatever dir you put it in cd __LEDE_IMAGEBUILDER_DIR__ # change __LEDE_SDK_DIR__ to whatever dir you put that in cp __LEDE_SDK_DIR__/bin/targets/ar71xx/generic/packages/kmod-pps-gpio-poll*.ipk packages/ # build a TL-MR3020 image make image PROFILE=tl-mr3020-v1 DEVICE_TYPE=lowrouter PACKAGES="kmod-pps chrony kmod-nbd nbd pps-tools kmod-pps-gpio-poll gpsd gpsd-clients kmod-usb-acm -iw -hostapd-common -kmod-ath -kmod-ath9k -kmod-ath9k-common -kmod-cfg80211 -kmod-mac80211 -swconfig -wpad-mini" # check the image size ls -l bin/targets/ar71xx/generic/*sysupgrade* # copy the image to my router's ramdisk scp bin/targets/ar71xx/generic/lede-17.01.6-ar71xx-generic-tl-mr3020-v1-squashfs-sysupgrade.bin email@example.com:/tmp/
I've removed all wireless to make room for gpsd and chrony. My GPS shows up as a usb-acm serial device, you might need a different kmod-usb-* package for different modules. Even with those changes, I only have 896kb free on the 4MB flash. I included nbd so I could use network storage for other packages and logging.
Step 3: apply image
After using sysupgrade to apply the image, I waited for it to reboot.
Step 4: configure sysntpd & gpsd
After it came back, I disabled sysntpd in
section config timeserver ntp with
option enabled 0. I configured gpsd in
/etc/config/gpsd to auto start and listen on
/dev/ttyACM0. I started gpsd and verified that it was working with
Step 5: enable and test pps
I then loaded the pps module with
insmod pps-gpio-poll gpio=29.
Kernel messages: [ 146.578832] pps pps0: new PPS source pps_gpio_poll [ 146.582189] pps-gpio-poll: Registered GPIO 29 as PPS source (precision 85 ns) Verify pps is returning results: # ppstest /dev/pps0 .. source 0 - assert 1544389003.000044807, sequence: 33 - clear 0.000000000, sequence: 0
Step 6: chronyd
configure chrony in
refclock PPS /dev/pps0 refid PPS poll 4 prefer refclock SHM 0 delay 0.2 refid NMEA noselect poll 6 dpoll 0
Start chronyd and verify that the PPS source is working with
MS Name/IP address Stratum Poll Reach LastRx Last sample =============================================================================== #* PPS 0 4 377 22 +62ns[ -264ns] +/- 16ns
Step 7: results
After setting up logging to the nbd drive and graphing with chrony-graph (instructions skipped because it'd make this long article even longer), this system stays in very close sync with the gps (+/- 60ns 50% of the time, +/-440ns 99% of the time):
Interestingly, there's a 55us offset between my two local clocks. I am still figuring out where this is coming from.