Re: [beagleboard] NTP PPS Support

2,178 views
Skip to first unread message

George Lu

unread,
May 5, 2013, 11:55:06 AM5/5/13
to beagl...@googlegroups.com
I have done this in kernel 3.2 (using Robert Nelson's ubuntu). I have not ventured into 3.8 yet. Depending on the specific GPS you use, you may need level converter from 5V to 3.3V, and/or invert the logic on GPS's TX output so that you could read the NMEA sentences correctly through one of the uart ports on beaglebone.

The key to PPS is to register a GPIO pin for the PPS-GPIO kernel driver. in 3.2 kernel menuconfig, enable drivers > PPS and PPS-GPIO.  Then edit the board support package (for beaglebone it is /arch/arm/mach-omap2/board-am335xevm.c) to register the gpio pin that will be used for PPS. I only capture the rising edge of PPS. If you want the falling edge as well, you need to indicate that in pps_gpio_info declaration. I had used gpio1_31 for PPS input.
add around line 40:
#include <linux/pps-gpio.h>

add
/* PPS-GPIO platform data */
static struct pinmux_config pps_pin_mux[] = {
    {"gpmc_csn2.gpio1_31", OMAP_MUX_MODE7 | AM33XX_PIN_INPUT},
    {NULL, 0},
};


static struct pps_gpio_platform_data pps_gpio_info = {
        .assert_falling_edge = false,
        .capture_clear= false,
        .gpio_pin=63,
        .gpio_label="PPS",
};


static struct platform_device pps_gpio_device = {
        .name = "pps-gpio",
        .id = -1,
        .dev = {
                .platform_data = &pps_gpio_info
        },
};

static void pps_init(int evm_id, int profile)
{
        int err;
        setup_pin_mux(pps_pin_mux);
        err = platform_device_register(&pps_gpio_device);
        if (err) {
                pr_warning("Could not register PPS_GPIO device");
        }
}

add the pps_init line
/* Beaglebone Rev A3 and after */
static struct evm_dev_cfg beaglebone_dev_cfg[] = {
        {tps65217_init, DEV_ON_BASEBOARD, PROFILE_NONE},
        {mii1_init,     DEV_ON_BASEBOARD, PROFILE_NONE},
        {usb0_init,     DEV_ON_BASEBOARD, PROFILE_NONE},
        {usb1_init,     DEV_ON_BASEBOARD, PROFILE_NONE},
        {i2c2_init,     DEV_ON_BASEBOARD, PROFILE_NONE},
        {mmc0_init,     DEV_ON_BASEBOARD, PROFILE_NONE},
        {pps_init,      DEV_ON_BASEBOARD, PROFILE_NONE},
        {boneleds_init, DEV_ON_BASEBOARD, PROFILE_ALL},
        {NULL, 0, 0},
};


You should see this during bootup:

ubuntu@omap:~$ dmesg |grep pps
[ 0.080893] pps_core: LinuxPPS API ver. 1 registered
[ 0.080906] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giom...@linux.it>
[ 2.030757] pps_core: source pps-gpio.-1 got cdev (253:0)
[ 2.030773] pps pps0: new PPS source pps-gpio.-1
[ 2.035711] pps pps0: Registered IRQ 223 as PPS source

You could see that the /sys/class/pps/pps0/assert file is updated every second after kernel captures an assert event:

ubuntu@omap:~$ cat /sys/class/pps/pps0/assert
1367766762.003443018#1707722
ubuntu@omap:~$ cat /sys/class/pps/pps0/assert
1367766763.003447249#1707723

NTP has to be custom built to support PPS. You need to install packages needed for native development and linux headers for the target kernel. I don't remember where we found that timepps.h file though.

# get latest ntp source from [http://www.ntp.org/downloads.html/]. 4.2.6p5 is the production release as of this writing.
wget http://www.eecis.udel.edu/~ntp/ntp_spool/ntp4/ntp-4.2/ntp-4.2.6p5.tar.gz
tar xvzf ntp-4.2.6p5.tar.gz
# copy timepps.h into the include directories
cp timepps.h ~/ntp-4.2.6p5/include/timpps.h
cp timepps.h /usr/include/timepps.h
# start configure and make
./configure
make
sudo make install
Getting the right configuration for your GPS in ntp.conf was not intuitive to say the least. If all works out, you could use ntpq -p to see that little 'o' in front of PPS(0) entry indicating it has locked onto the PPS through the specific GPIO pin to get 2us jitter (this table was captured ~5 hours after one bootup more than a year ago):

     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*SHM(0)          .GPS.            0 l    4   16  377    0.000  -19.922   9.783
oPPS(0)          .GPIO.           0 l    2   16  377    0.000   -0.281   0.002
-vhost.cohesivel 128.249.1.10     3 u   50   64  377   56.110   13.134   2.715
-clock01.laca02. 216.119.63.113   2 u   16   64  377   25.002   17.157   1.003
+cheezum.mattnor 129.7.1.66       2 u   20   64  377   57.517   11.404   1.817
+gatekeeper.tss. 173.13.85.5      2 u   31   64  377   39.604   15.033   0.929

With NTPD, It is better to have beaglebone running on constant clock frequency. You could do a "cpufreq-set -g performance" on startup to keep it at 720MHz.

Hope this helps. You might wonder if this is all worthwhile if we don't have a realtime kernel. That is another can of worms.

cheers,
George



On Wed, May 1, 2013 at 6:02 AM, <rop...@gmail.com> wrote:
Hello,

I'd like to build a NTP Server using PPS signal from a GPS to guarantee the precision. I was wondering if it is possible to use the PPS signal with BeagleBone and NTP daemon. Has anybody ever tried it?

Thanks!

--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to the Google Groups "BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

George Lu

unread,
May 7, 2013, 10:09:49 PM5/7/13
to beagl...@googlegroups.com
You are very welcome.

I think it will work fine with Debian on beaglebone with the right pinmux for the uart port you use.

You could consider the GPS breakout from Adafruit which is already on 3.3V logic and the NMEA output does not need inversion. You won't even need the MAX232. Its power consumption is lower than 18LVC, and the PPS is 10ns (vs 1us) jitter.



On Tue, May 7, 2013 at 6:08 PM, <rop...@gmail.com> wrote:
George, thank you so much for your answer, I really appreciate it.

I have built NTP servers using PPS signal (Trimble, Garmin, etc) using FreeBSD on regular PCs getting the PPS through serial port (pin 1 - DCD). Once FreeBSD supports PPS natively, recompiling kernel is easy.

I intend to run Debian on my BeagleBoard and reading NMEA sentences through TX/RX serial port and getting PPS through GPIO. Do you think I will have good results?

David M.

unread,
May 8, 2013, 2:43:33 PM5/8/13
to beagl...@googlegroups.com, rop...@gmail.com
Here are my thoughts:
 
I'm using Angstrom, but I don't think that's a consideration--Linux PPS will work on most distros that I'm aware of.
 
The way this works is, the NTP daemon would have two clock drivers, one for an NMEA GPS and an ATOM driver which provides the PPS function.
 
The ATOM driver is marked as a preferred source in ntp.conf.
It points to /dev/pps0.
 
The Linux kernel will let you set one of your GPIO's to be the PPS device, so that the pulses from your GPS will or should go to the GPIO's.  You are going to need another MAX232.  My GPS module does not do any hardware handshaking so I can use a single MAX232--remember that it has two inputs and two outputs.  For my device,  I have TxD, one output,  RxD and DCD, (the PPS signal), two inputs, so I am set.  The level shifter I use downstream from there, the 74LVC245, has more inputs than I need.  I only need to transmit to the GPS during configuration so I will toggle the level converter when that needs to happen.
Here is the part I haven't figured out yet:  I have the GPIO, it is, if I recall, /dev/gpio <something>?  Linux, and the NTP daemon, expect to see /dev/pps0.  I'm not sure what I need to do to associate the GPIO with the PPS driver.  That would be something I have to figure out as I go. I don't know how to do this yet.
 
But I'm very confident that this will work, even though I have a lot of work left to do with the extra parts of my project (a status display and configuration web server.) 
 
Reply all
Reply to author
Forward
0 new messages