Enabling PPS on Xavier AGX

I’m trying to enable a PPS input from a GPIO pin on the Jetson Xavier carrier board but cant seem to get it to work.

I have rebuilt the kernel with the following config(s)

# PPS support
CONFIG_PPS=y
# CONFIG_PPS_DEBUG is not set
# PPS clients support
# CONFIG_PPS_CLIENT_KTIMER=y
# CONFIG_PPS_CLIENT_LDISC=y
# CONFIG_PPS_CLIENT_GPIO=y
# PPS generators support
# CONFIG_NVPPS is not set

This gave me a device /dev/pps0 which was the KTIMER but I want to be using a GPIO input and there was no /dev/pps1. So I tried with CONFIG_PPS_CLIENT_KTIMER disabled as well but that didn’t really change the situation.

I have also edited the device tree and added a pps device with one of the 40 header pins selected.

pps {
gpios = <&gpio TEGRA_GPIO(Z, 6) 0>;
compatible = "pps-gpio";
assert-falling-edge;
status = "okay";
};

After this I built the image and flashed the Xavier and couldn’t find a pps device for the GPIO.

Is there something that I could be missing / doing wrong?

I have read through the forums and the most similar topic I can find is doing exactly what I’m asking except on the Jetson Nano ( Enabling PPS on Jetson Nano with Jetpack 4.3 ). In fact in that thread there’s a link to a decent blog post ( https://msadowski.github.io/pps-support-jetson-nano/ ) that seems to explain everything fairly thoroughly - however I can’t seem to get it to work on the Xavier AGX.

Any help would be appreciated.
Thanks

what would be the output of
ppstest /dev/pps0
given the pps timepulse is conencted to corresponding GPIO pin?
What is the output of
sudo cat /dev/ttyTHS0
given GPIO UART TX&RX are connected to corresponding pins RX & TX of GPS unit?

NB! The former is for readnig timepulse, while the latter is for reading NMEA sentences, etc.

Which of the two are you trying to implement? Former? Latter? Both? Neither of the two?

what would be the output of
`ppstest /dev/pps0`
given the pps timepulse is conencted to corresponding GPIO pin?

With CONFIG_PPS_CLIENT_KTIMER=y enabled the output of ppstest /dev/pps0 is the ktimer clock. With
CONFIG_PPS_CLIENT_KTIMER not enabled there is no output for /dev/pps0 because it doesn’t exist.

What is the output of
`sudo cat /dev/ttyTHS0`
given GPIO UART TX&RX are connected to corresponding pins RX & TX of GPS unit?

To my understanding I shouldn’t need the GPS plugged into serial, I was hoping to just have a single wire interface between the GPS and AGX where the GPS is outputting the PPS signal and the AGX is reading the incoming PPS signal on pin 24 - the pin I added in the device tree with gpios = <&gpio TEGRA_GPIO(Z, 6) 0>;.

Which of the two are you trying to implement? Former? Latter? Both? Neither of the two?

I am trying to implement the former. I want to read the timepulse.

modprobe pps-ktimer
ppstest /dev/pps1
so this one won’t show the timepulse if you run it? with connected gps device? without connected gps device? what will be the output?
On NX I was able to use jetson.io & dtb update in order to add the timepulse;
Pin number is to be checked with reference documentation. The example below matches pin7 of NX GPIO.
In my implementation I used following steps for NX:

  1. creatednew file pps.dts at /boot folder
/dts-v1/;
/plugin/;
/ {
    overlay-name = "Jetson PPS";
    compatible = "nvidia,p3509-0000+p3668-0001";
    fragment {
        target-path = "/";
        __overlay__ {
                        pps: pps_gpio {
                                compatible = "pps-gpio";
                                gpios = <&tegra_main_gpio 148 1>;
                                assert-falling-edge;
                                status = "okay";
                        };
        };
    };
};
  1. processed it with
    sudo dtc -I dts -O dtb -@ -o pps.dtbo pps.dts
  2. sudo /opt/nvidia/jetson-io/config-by-hardware.py -l
  3. sudo /opt/nvidia/jetson-io/config-by-hardware.py -n "Jetson PPS"
    then reboot; the referenced tegra_main_gpio 148 corresponds to the pin7 of nx jetson; for AGX you will have to check with the documentation

Thank you for the input Andrey,

so this one won’t show the timepulse if you run it? with connected gps device? without connected gps device? what will be the output?

I’ll get back to you on the output when I have the GPS available. For now all I can say is that modprobe pps-ktimer returns:

modprobe pps-ktimer
modprobe: FATAL: Module pps-ktimer not found in directory /lib/modules/4.9.140-tegra

But I have currently disabled the ktimer, and even when I do enable it and re-flash the TX2 I don’t load it as a module.

I have been reading through the thread “Time sensitive networking [TSN] on NX” and noticed that you may have been missing the /dts-v1/; at the top of the pps.dts file you have included. However, this still doesn’t fix my problem. I run into the same issue you seem to have had with the gpio warnings.

$ sudo dtc -I dts -O dtb -@ -o pps.dtbo pps.dts
     pps.dtbo: Warning (gpios_property): Property 'gpios', cell 1 is not a phandle reference in 
     /fragment/__overlay__/pps_gpio
     pps.dtbo: Warning (gpios_property): Could not get phandle node for /fragment/__overlay__/pps_gpio:gpios(cell 1)

It looks like these warnings aren’t an issue judging by that thread but It seems like I still can’t get that dts file to compile. When I run sudo /opt/nvidia/jetson-io/config-by-hardware.py -l the Jetson PPS configuration does not appear.

$ sudo /opt/nvidia/jetson-io/config-by-hardware.py -l
    Configurations for the following hardware modules are available:
    1. Adafruit SPH0645LM4H
    2. FE-PI Audio Z V2

I assume that the name needs to be changed for the board judging by the ‘valid names’ shown for the agx here: https://docs.nvidia.com/jetson/l4t/index.html#page/Tegra%20Linux%20Driver%20Package%20Development%20Guide/adaptation_and_bringup_xavier.html .

So the current dts file I am using looks like this (using pin 24 on the 40 pin GPIO header):

/dts-v1/;
/plugin/;

/ {
    overlay-name = "Jetson PPS";
    compatible = "p2972-0000-devkit,devboard";

    fragment {
        target-path = "/";
        __overlay__ {
                        pps: pps_gpio {
                                compatible = "pps-gpio";
                                gpios = <&tegra_main_gpio 206 1>;
                                assert-falling-edge;
                                status = "okay";
                        };
        };
    };
};

So It is working now!

I followed gtj’s steps from Time sensitive networking [TSN] on NX with a few modifications (really just the names to work with the AGX instead of the NX).

I saved this file to /boot/pps.dts where the pin has been set to 24 on the 40 pin header.

/dts-v1/;
/plugin/;

/ {
    overlay-name = "Jetson PPS";
    compatible = "p2822-0000+p2888-0001,p2972-0000-devkit,devboard";
    fragment {
        target-path = "/";
        __overlay__ {
                        pps: pps_gpio {
                                compatible = "pps-gpio";
                                gpios = <&tegra_main_gpio 206 1>;
                                assert-falling-edge;
                                status = "okay";
                        };
        };
    };
};

Then compiled the dts files and ignored the warnings that I don’t understand…

 sudo dtc -I dts -O dtb -@ -o pps.dtbo pps.dts

Then created the custom dtb

sudo fdtoverlay -i tegra194-p2888-0001-p2822-0000.dtb -o tegra194-p2888-0001-p2822-0000-user-custom.dtb tegra194-p2888-0001-p2822-0000-hdr40.dtbo pps.dtbo

Finally edited /boot/extlinux/extlinux.conf by adding the extra entry:

    LINUX ...
    INITRD ...
    FDT /boot/tegra194-p3668-all-p3509-0000-user-custom.dtb
    APPEND ...

and rebooted.

Thanks @gtj and @Andrey1984

Sorry if this is a bit of a duplicate question (although I guess it’s specific to the AGX as opposed to the NX).

What I don’t understand is why does the device tree need to be edited after the kernel has been flashed?

Editing ~/nvidia/nvidia_sdk/JetPack_4.3_Linux_P3448/Linux_for_Tegra/sources/hardware/nvidia/soc/t210/kernel-dts/tegra210-soc/tegra210-soc-base.dtsi to include

pps: pps_gpio {
    compatible = "pps-gpio";
    gpios = <&tegra_main_gpio 206 1>;
    assert-falling-edge;
    status = "okay";
    };

should be the same as including it after the flash by editing the device tree overlay right?

Thank you for sharing your success;
In the example above the default stock kernel has been used.

1 Like

Yeah, it’s just a matter using the device tree overlay to experiment because it’s easier to change on the fly, and putting the final result into the source tree’s dtsi file for permanent inclusion. There’s no function difference.

1 Like