# Raspberry Pi 5 — GPS/PPS PTP Grandmaster This directory contains the files used to turn the Raspberry Pi 5 into the PTP grandmaster for the lab. The intended time chain is: ```text GT-U7 GNSS ├─ NMEA over UART ──> gpsd/chrony └─ PPS on GPIO18 ──> chrony │ ▼ CLOCK_REALTIME (UTC) │ phc2sys │ ▼ eth0 NIC PHC │ ptp4l │ ▼ PTP domain 0 ``` The Pi therefore has two jobs: 1. discipline the Linux system clock from GNSS/PPS using chrony; and 2. copy that time into the Ethernet PHC and advertise it as the PTP grandmaster. ## Files in this directory | File | Install/use as | Purpose | |---|---|---| | `config.txt` | execute the commands in the file once | Adds the Pi 5 UART and PPS overlays to `/boot/firmware/config.txt` | | `ptp-gm.conf` | `/etc/linuxptp/ptp4l-gm.conf` | `ptp4l` grandmaster configuration | | `ptp4l-gm.service` | `/etc/systemd/system/ptp4l-gm.service` | Starts the PTP grandmaster | | `phc2sys-gm.service` | `/etc/systemd/system/phc2sys-gm.service` | Synchronizes the `eth0` PHC from `CLOCK_REALTIME` | | `ptp_nic_coalesce.service` | `/etc/systemd/system/ptp_nic_coalesce.service` | Optional NIC interrupt-coalescing tuning | ## 1. Install the required packages ```bash sudo apt update sudo apt install gpsd gpsd-clients pps-tools chrony linuxptp ethtool ``` ## 2. Configure the Pi UART and PPS input The `config.txt` file in this directory contains shell commands that append the required settings to the real Raspberry Pi boot configuration. Back up the boot configuration first: ```bash sudo cp /boot/firmware/config.txt /boot/firmware/config.txt.pre-ptp ``` Then review and execute the commands from `config.txt`. The resulting lines in `/boot/firmware/config.txt` should include: ```text # GPS UART on GPIO14/GPIO15 for Pi 5 dtoverlay=uart0-pi5 init_uart_baud=9600 # GPS PPS on physical pin 12 / GPIO18 dtoverlay=pps-rp1,pin=18,pull-down,schmitt-trigger ``` `pps-rp1` is a separate Pi 5 overlay. Make sure `pps-rp1.dtbo` has already been installed in the appropriate overlays directory before rebooting. Reboot the Pi: ```bash sudo reboot ``` After reboot, verify that the UART and PPS device exist: ```bash ls -l /dev/ttyAMA0 /dev/pps0 sudo ppstest /dev/pps0 ``` `ppstest` should report a new PPS assertion once per second. ## 3. Configure gpsd Configure `/etc/default/gpsd` so gpsd opens both the GT-U7 UART and PPS device: ```bash START_DAEMON="true" USBAUTO="true" DEVICES="/dev/ttyAMA0 /dev/pps0" GPSD_OPTIONS="-n" ``` Restart and verify gpsd: ```bash sudo systemctl restart gpsd systemctl status gpsd cgps -s ``` ## 4. Configure chrony Chrony disciplines `CLOCK_REALTIME` from the GNSS receiver. NMEA identifies the UTC second and PPS supplies the precise second boundary. Add the following refclocks to the chrony configuration used by the Pi: ```text refclock SHM 0 refid NMEA offset 0.0 precision 1e-1 poll 3 noselect refclock PPS /dev/pps0 refid PPS lock NMEA poll 3 ``` If this Pi should continue serving NTP to the lab, keep the required `allow` networks, for example: ```text allow 192.168.0.0/16 allow 10.0.0.0/8 allow 172.16.0.0/12 ``` Also keep: ```text rtcsync makestep 1 3 leapseclist /usr/share/zoneinfo/leap-seconds.list ``` Do **not** add `local stratum 1` for the GNSS/PPS setup. A selected local refclock already makes chronyd serve the correct NTP stratum; `local` is a separate fallback/local-reference mode. Restart chrony and verify that PPS becomes the selected source: ```bash sudo systemctl restart chrony chronyc sources -v chronyc sourcestats chronyc tracking ``` A healthy setup should show PPS selected (`#* PPS` on common chrony versions). The NMEA `offset 0.0` in the example is only a starting point. If the serial NMEA sentence latency is large, measure it and adjust the NMEA offset later. ## 5. Verify hardware timestamping on `eth0` Before enabling PTP, verify the Pi 5 NIC exposes a PHC and hardware TX/RX timestamping: ```bash ethtool -T eth0 ``` You want hardware TX/RX/raw timestamp support and a non-negative `PTP Hardware Clock` number. You can also identify the PHC with: ```bash readlink -f /sys/class/net/eth0/device/ptp/ptp* ``` ## 6. Install the PTP configuration and services From this directory, install the files as follows: ```bash sudo install -D -m 0644 ptp-gm.conf /etc/linuxptp/ptp4l-gm.conf sudo install -D -m 0644 ptp4l-gm.service /etc/systemd/system/ptp4l-gm.service sudo install -D -m 0644 phc2sys-gm.service /etc/systemd/system/phc2sys-gm.service ``` The bundled PTP configuration uses: ```text domainNumber 0 network_transport UDPv4 delay_mechanism E2E serverOnly 1 clockClass 6 clockAccuracy 0xFE timeSource 0x20 utc_offset 37 twoStepFlag 1 ``` `clockAccuracy 0xFE` is intentionally conservative until actual accuracy has been measured. The `utc_offset` value is the PTP/TAI-to-UTC offset advertised to clients; review it if a future leap second changes the TAI-UTC difference. Reload systemd and enable the services: ```bash sudo systemctl daemon-reload sudo systemctl enable --now ptp4l-gm.service sudo systemctl enable --now phc2sys-gm.service ``` The direction is important: ```text chrony: GNSS/PPS -> CLOCK_REALTIME phc2sys-gm: CLOCK_REALTIME -> eth0 PHC ptp4l-gm: eth0 PHC -> PTP network ``` ## 7. Optional NIC coalescing tuning `ptp_nic_coalesce.service` applies: ```bash ethtool -C eth0 tx-usecs 4 rx-usecs 4 ``` Treat this as an optional latency/jitter tuning step, not a requirement for PTP to work. First check what the driver supports: ```bash ethtool -c eth0 ``` If the settings are accepted and you want to keep them: ```bash sudo install -D -m 0644 ptp_nic_coalesce.service /etc/systemd/system/ptp_nic_coalesce.service sudo systemctl daemon-reload sudo systemctl enable --now ptp_nic_coalesce.service ``` ## 8. Verification Service state: ```bash systemctl status chrony systemctl status ptp4l-gm systemctl status phc2sys-gm ``` Live logs: ```bash journalctl -fu ptp4l-gm journalctl -fu phc2sys-gm ``` Query the local `ptp4l` management socket: ```bash sudo pmc -u -b 0 'GET PORT_DATA_SET' sudo pmc -u -b 0 'GET GRANDMASTER_SETTINGS_NP' sudo pmc -u -b 0 'GET TIME_STATUS_NP' ``` Expected results include: ```text portState MASTER/SERVER timeSource 0x20 clockClass 6 clockAccuracy 0xFE stepsRemoved 0 ``` The `grandmasterIdentity` reported here is the identity that should remain visible through WOLF-HUNTER and NYATER. ## 9. Troubleshooting checklist ```bash # PPS exists and pulses sudo ppstest /dev/pps0 # GPS data is arriving cgps -s # chrony actually selected PPS chronyc sources -v chronyc tracking # eth0 supports hardware PTP ethtool -T eth0 # PTP services are healthy journalctl -u ptp4l-gm -n 100 --no-pager journalctl -u phc2sys-gm -n 100 --no-pager ``` Do not run another service that also tries to discipline the `eth0` PHC. Chrony may continue to discipline `CLOCK_REALTIME`; that is intentional on the grandmaster.