|
| 1 | +#!/usr/bin/env bash |
| 2 | +# ptp_crosscheck.sh — on the radxa-x4, (1) show the Intel I226 Ethernet doing |
| 3 | +# real IEEE-1588 hardware PTP, and (2) cross-compare the 8821CE Wi-Fi TSF PHC |
| 4 | +# against that real PTP clock on the SAME machine — quantifying the Wi-Fi TSF's |
| 5 | +# frequency error and short-term stability versus genuine PTP hardware, with no |
| 6 | +# second machine and no network dependency. |
| 7 | +# |
| 8 | +# sudo tests/pcie_phc/ptp_crosscheck.sh |
| 9 | +set -uo pipefail |
| 10 | +cd "$(dirname "$0")" |
| 11 | +ETH=enp2s0 |
| 12 | +WIF=wlp1s0 |
| 13 | +MOD=rtl8821ce_phc |
| 14 | + |
| 15 | +cleanup() { |
| 16 | + echo "[xchk] cleanup" |
| 17 | + sudo pkill -x ptp4l phc2sys 2>/dev/null |
| 18 | + sudo rmmod "$MOD" 2>/dev/null |
| 19 | + sudo ip link set "$WIF" down 2>/dev/null |
| 20 | + sudo iw dev "$WIF" set type managed 2>/dev/null |
| 21 | + sudo ip link set "$WIF" up 2>/dev/null |
| 22 | + command -v nmcli >/dev/null && sudo nmcli dev set "$WIF" managed yes 2>/dev/null |
| 23 | +} |
| 24 | +trap cleanup EXIT |
| 25 | + |
| 26 | +# --- find the igc (Ethernet) PHC --- |
| 27 | +IGC_PTP="" |
| 28 | +for d in /sys/class/ptp/ptp*; do |
| 29 | + n=$(cat "$d/clock_name" 2>/dev/null) |
| 30 | + case "$n" in |
| 31 | + rtl8821ce_tsf) : ;; # skip ours if already loaded |
| 32 | + *) [ -e "/dev/$(basename "$d")" ] && IGC_PTP="/dev/$(basename "$d")" ;; |
| 33 | + esac |
| 34 | +done |
| 35 | +echo "[xchk] Ethernet (I226) PHC = ${IGC_PTP:-<none>}" |
| 36 | + |
| 37 | +# --- 1. prove the I226 does hardware-timestamped PTP --- |
| 38 | +echo "[xchk] === ptp4l on $ETH (I226): does it use HARDWARE timestamping? ===" |
| 39 | +sudo timeout 8 ptp4l -i "$ETH" -m 2>&1 | grep -iE "clock|hardware|selected|MASTER|assuming|state" | head -6 || true |
| 40 | + |
| 41 | +# --- put the Wi-Fi MAC in monitor mode so the TSF ticks, then load our PHC --- |
| 42 | +echo "[xchk] arming Wi-Fi TSF PHC" |
| 43 | +sudo pkill -x wpa_supplicant 2>/dev/null |
| 44 | +command -v nmcli >/dev/null && sudo nmcli dev set "$WIF" managed no 2>/dev/null |
| 45 | +sleep 1 |
| 46 | +sudo ip link set "$WIF" down; sudo iw dev "$WIF" set type monitor 2>/dev/null; sudo ip link set "$WIF" up |
| 47 | +sudo iw dev "$WIF" set channel 6 2>/dev/null |
| 48 | +sleep 1 |
| 49 | +make -s >/dev/null 2>&1 |
| 50 | +sudo rmmod "$MOD" 2>/dev/null |
| 51 | +sudo insmod "./$MOD.ko" || { echo "[xchk] PHC insmod failed"; exit 1; } |
| 52 | +sleep 1 |
| 53 | +WIF_PTP="" |
| 54 | +for d in /sys/class/ptp/ptp*; do |
| 55 | + [ "$(cat "$d/clock_name" 2>/dev/null)" = "rtl8821ce_tsf" ] && WIF_PTP="/dev/$(basename "$d")" |
| 56 | +done |
| 57 | +echo "[xchk] Wi-Fi TSF PHC = ${WIF_PTP:-<none>}" |
| 58 | +[ -z "$WIF_PTP" ] && { echo "[xchk] no Wi-Fi PHC"; exit 1; } |
| 59 | +[ -z "$IGC_PTP" ] && { echo "[xchk] no Ethernet PHC to compare against"; exit 1; } |
| 60 | + |
| 61 | +# --- 2. cross-compare: discipline the Wi-Fi PHC to the I226 hardware clock. |
| 62 | +# The Wi-Fi PHC is the slave (system + I226 untouched). Steady-state: |
| 63 | +# 'freq' ~= the Wi-Fi crystal's frequency error vs the I226 (ppb) |
| 64 | +# 'offset' jitter ~= the Wi-Fi TSF short-term stability vs real PTP hardware --- |
| 65 | +echo "[xchk] === phc2sys: Wi-Fi TSF ($WIF_PTP) vs real PTP hardware ($IGC_PTP), ~25 s ===" |
| 66 | +sudo timeout 27 phc2sys -s "$IGC_PTP" -c "$WIF_PTP" -O 0 -m 2>&1 | grep -iE "offset" | tail -20 || true |
| 67 | +echo "[xchk] done" |
0 commit comments