About this server
Hardware, Software, and a Diagram.
Hardware
- Host
- Raspberry Pi Compute Module 5 (4 GB/16 GB EMMC/WiFi) on an Official CM5 IO Board, running DietPi.
- GPS / RTC HAT
- Uputronics Raspberry Pi GPS/RTC expansion board. The board features a u-blox MAX-M8Q multi-GNSS receiver attached to an external antenna and a RV-3028 RTC. NMEA arrives over the UART (
/dev/ttyAMA0); the HAT's PPS signal on GPIO 18 is directly connected to J2 Pin 6 (the Ethernet PHY's PPS input pin) allowing for the NIC's PTP Hardware Clock to be disciplined directly, instead of the kernel reading the pulse off a GPIO pin. - Antenna
- Bingfu GPS Antenna with SMA Male Connector
- Network
- Wired onboard Gigabit Ethernet. The CM5's PHY (BCM54210PE) exposes a PTP Hardware Clock and a hardware PPS input pin. That is what makes a hardware-timestamped PTP grandmaster possible here.
- Storage
- 16gb eMMC with log2ram (128 MB), shielding the SD card from chrony's measurement logs.
Software
- SatPulse
- GPS-disciplined daemon (
satpulsed) that reads NMEA and the PHY-pin PPS, disciplines the NIC's PTP Hardware Clock, feeds chrony through a SOCK refclock, and drivesptp4l. - PTP Time daemon
ptp4l(linuxptp): PTP grandmaster oneth0, the PHC-disciplined clock is fed by SatPulse over a Unix domain socket and serving IEEE-1588 compliant time to the LAN on UDP ports 319/320 with hardware timestamping.- NTP Time daemon
- chrony: time-discipline mechanism on the host, fed by SatPulse and serving NTP to the LAN.
- Reference clocks
refclock SOCK /var/run/chrony.satpulse.sock poll 2 filter 4 refid GNSS prefer(SatPulse-disciplined GNSS time), plus a public NTP pool for cold-start / outage fallback and sanity-check.- Kernel
dtparam=uart0=onenables the GPS UART anddtoverlay=i2c-rtc,rv3028enables the RTC. A hardware watchdog (bcm2835_wdt) restarts the box if discipline ever deteriorates.
Precision Time Protocol
This box's primary function is to act as a PTP (IEEE-1588) grandmaster and server highly accurate time. satpulsed keeps the NIC's PTP Hardware Clock locked to GPS, and ptp4l distributes that hardware-timestamped time to the LAN over UDP 319/320.
# /etc/linuxptp/ptp4l.conf (grandmaster on eth0)
[global]
time_stamping hardware
serverOnly 1 # linuxptp 3.x: masterOnly
domainNumber 0
uds_address /var/run/ptp4l # SatPulse pushes the disciplined clock here
# /etc/satpulse.toml
[phc]
interface = "eth0"
[ntp]
sock.path = "/var/run/chrony.satpulse.sock"
[ptp]
ptp4l.udsAddress = "/var/run/ptp4l"Reference clock chain
GPS satellites broadcast time tied to a UTC offset table. The MAX-M8Q recovers that time and emits a hardware pulse on the start of every UTC second (the PPS signal). That pulse travels from GPIO 18 to J2 Pin 6 (the Ethernet PHY's PPS input) where satpulsed reads it through the NIC's PHC, using the NMEA stream only to label which second the pulse belongs to. From there the disciplined clock fans out to chrony (NTP) and ptp4l (PTP).
GPS constellation
│ (radio: time-of-week + sat ephemerides)
▼
[ MAX-M8Q receiver ]
NMEA → /dev/ttyAMA0 ─┐ (which second?)
PPS → GPIO18 → J2 Pin6 (PHY) ─┴─► satpulsed → disciplines eth0 PHC
│ (when exactly?)
┌───────────────────────────────┤
▼ ▼
chrony SOCK refclock (GNSS) ptp4l (uds)
│ │
▼ NTP/123 over LAN ▼ PTP 319/320 over LAN
[ LAN clients ] [ PTP clients ]Inspiration & credit
The PPS-via-PHY discipline this server depends on runs on SatPulse (the satpulsed daemon above), built by JClark. And the whole project was inspired by Jeff Geerling and his videos on precision time. Thank you both.