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 |
Install FreeBSD on Pi 4
- 1.1 Install a silent u-boot
- 1.2 Configure the boot loader
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
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.
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
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
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
- 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.
- Waveshare: product page, wiki
- GNSS
- NTP daemons
Chrony
NTPsec
ntp