FreeBSD 14 Pi 4 MAX‐M8Q - BYO-NTP/recipes GitHub Wiki

date server os gnss daemon 🎯 🗣️
2025-05 Pi 4 FreeBSD
14
Waveshare MAX-M8Q
GNSS HAT
chrony
NTPsec
ntp
2 µs discuss

Pi 4 with Waveshare MAX-M8Q hat assembled

1. Install OS

Install FreeBSD on Pi 4

Tell the FreeBSD boot loader to ignore console input with autoboot_delay=-1. If this isn't done before attaching the GNSS hat, the hat will spew data to the console and interrupt the boot process. I perform this step by attaching the SD card to a VM running FreeBSD.

sysrc -f /boot/loader.conf autoboot_delay=-1 \
    console=vidconsole boot_multicons=NO boot_serial=NO

2. Configure the GNSS

Configure the jumpers to A mode and plug a USB cable into the HAT and a Windows computer with u-blox u-center installed. Configure the GNSS per the recommendations on the gnss page.

Restore the jumpers to 'B' mode and connect the hat to your Pi.

3. Configure the UART

ttyu0 (aka cuau0) is our GPS hat, tell getty to ignore it:

sed -i '' -e '/^ttyu0/ s/onifconsole/off/' /etc/ttys
kill -HUP 1

The NTP daemons look to /dev/gps0 by default, so link gps0 to the serial port using devfs:

test -L /dev/gps0 && rm /dev/gps0
grep -q gps0 /etc/devfs.conf && sed -i '' -e 's/^link.*gps0$//g' /etc/devfs.conf
echo 'link    cuau0 gps0' >> /etc/devfs.conf
service devfs restart

4. Configure PPS

The distributed FreeBSD image doesn't include most Pi overlays. Install the package and copy the overlays to the SD card.

pkg install -y rpi-firmware
cp -p /usr/local/share/rpi-firmware/overlays/* /boot/efi/overlays/

Load the pps-gpio overlay by adding this block to /boot/efi/config.txt in the [all] section:

grep -q pps-gpio /boot/efi/config.txt || cat >> /boot/efi/config.txt <<EOF

# Waveshare MAX-M8Q GNSS hat
dtoverlay=pps-gpio,gpiopin=18
enable_uart=1

EOF

Load the FreeBSD gpsiopps kernel module.

sysrc -f /boot/loader.conf gpiopps_load="YES"
kldload gpiopps

Allow the ntpd user read access to gpiopps0:

grep -q gpiopps0 /etc/devfs.rules || cat >> /etc/devfs.rules <<EONTP
[devfsrules_ntp=10]
add path 'gpiopps0' mode 0660 group ntpd
EONTP
sysrc devfs_system_ruleset+="devfsrules_ntp"
service devfs restart

NTP daemons (and gpsd) expect to find PPS output at /dev/pps0 but the gpiopps module mounts it at /dev/giopps0. Alias it to /dev/pps0.

grep -q pps0 /etc/devfs.conf && sed -i '' -e 's/^link.*pps0$//g' /etc/devfs.conf
echo 'link    gpiopps0 pps0' >> /etc/devfs.conf
service devfs restart

Reboot and verify

Power off your Pi (poweroff) and install the GPS hat. Power it on and verify that it works:

dmesg | egrep '(uart|pps)'
gpiopps0: <GPIO PPS> on ofwbus0
gpiopps0: PPS input on gpio0 pin 18
uart0: <PrimeCell UART (PL011)> mem 0x7e201000-0x7e2011ff irq 16 on simplebus0

5. Install a NTP daemon

Each section heading is a link with many more details about installing, configuring, and verifying that particular NTP daemon.

export NTP_REFCLOCKS=$(cat <<EO_CHRONY
refclock SHM 0         refid NMEA precision 0.02 offset 0.052 noselect
refclock PPS /dev/pps0 refid PPS  precision 4e-6 lock NMEA poll 2 trust
EO_CHRONY
)
curl -sS https://byo-ntp.github.io/tools/chrony/install.sh | sh
export NTP_REFCLOCKS=$(cat <<EO_NTPSEC
refclock nmea refid NMEA minpoll 3 maxpoll 4 time2 0.048 baud 115200 mode 8 prefer
refclock pps  refid PPS  minpoll 1 maxpoll 2 time1 0.0
EO_NTPSEC
)
curl -sS https://byo-ntp.github.io/tools/ntpsec/install.sh | sh
export NTP_REFCLOCKS=$(cat <<EO_NTP
server 127.127.20.0 minpoll 3 maxpoll 4 mode 88 prefer
fudge  127.127.20.0 refid NMEA time2 0.047 minjitter 0.3

server 127.127.22.0 minpoll 3 maxpoll 4
fudge 127.127.22.0 refid PPS time1 0.0
EO_NTP
)
curl -sS https://byo-ntp.github.io/tools/ntp/install.sh | sh

Observe

  • watch the status in near real time (requires installing gnu-watch):
    • printf '\e[8;9;80t'; ssh -t pi5 gnu-watch -n2 chronyc sources
    • printf '\e[8;9;80t'; ssh -t pi5 gnu-watch -n2 ntpq -c peer
  • Measure the offset
  • Gather statistics with telegraf + influxdb + grafana or similar.

References

Performance

Chrony

NTPsec

ntp

⚠️ **GitHub.com Fallback** ⚠️