层级1 PTP主时钟:CM4 + SR1723U10(第一部分)
摘要
本文详细介绍了一个DIY构建的层级1 PTP主时钟,使用Raspberry Pi CM4和GPS模块,用于工业基础设施中的纳秒级精确时间同步,并将其与昂贵的商业解决方案进行比较。
<p><a href="https://lobste.rs/s/mekgva/stratum_1_ptp_grandmaster_cm4_sr1723u10">评论</a></p>
查看缓存全文
缓存时间: 2026/08/17 16:09
# 第一层PTP主时钟:CM4 + SR1723U10(上篇)
来源:https://opscode.io/posts/ptp-grandmaster-cm4-sr1723u10/
我从事需要纳秒级精确时间同步的工业基础设施工作。商用GPS驯服的PTP主时钟解决这一问题,低端型号售价数千美元,加上选配和支持费用则更高。实验室中已存放CM4和CM4 IO板。使用配备OCP M.2 GNSS模块的TimeHAT本是更简洁的方案(约400美元),但若目标是学习PTP实际工作原理而非部署生产设施,此成本过高。本次构建新部件花费约103美元。
本文记录了我构建的成果、遇到的问题、修复措施以及最终测量结果。
## 什么是PTP及其重要性
时间精度是一个连续谱系:
| 单位 | 定义 | 应用示例 |
|------|------|----------|
| 1秒(s) | 时钟的基本跳动 | 人类活动安排、定时任务 |
| 1毫秒(ms) | 1秒分割为1,000份 | 网页浏览、视频流、日志时间戳 |
| 1微秒(μs) | 1秒分割为1,000,000份 | 高频交易、音视频同步、分布式数据库 |
| 1纳秒(ns) | 1秒分割为1,000,000,000份 | 航空航天仪器、工业自动化、科学数据采集、本项目构建 |
NTP对Web服务器、数据库、认证系统以及任何只需记录事件发生时间但无需跨机器协调硬件事件的场景已足够。在局域网内配合良好参考源,NTP可达到低微秒级精度。广域网上通常处于低毫秒级。其上限取决于客户端与服务器间的网络路径抖动,每个延迟变量都会为偏移估算引入噪声。
PTP(精确时间协议,IEEE 1588)处理纳秒级精度。通过在以太网PHY层实现硬件时间戳,PTP可在局域网内将时钟同步至数十纳秒内。主时钟作为根时间源,采用GPS驯服时间并通过PTP协议分发至客户端。
1纳秒是光行进约30厘米(约1英尺)所需时间。完成本构建后,家庭实验室节点的时钟与GPS真值的偏差,仅相当于光穿过房间所需的时间。
## 硬件清单
| 组件 | 备注 | 成本 |
|------|------|------|
| Raspberry Pi CM4(8GB/32GB eMMC) | 已拥有 | 无 |
| CM4 IO板 | 已拥有 | 无 |
| SR1723U10 GPS模块 | 基于u-blox M10 | 约15美元 |
| JEFA Tech U.FL转SMA转接线 | 用于天线连接 | 约8美元 |
| Bingfu GPS天线 | 有源天线,SMA接口 | 约12美元 |
| MOOKEERF SMA线缆 | 多种长度 | 约10美元 |
| Waveshare CM4 IO板机箱 | 1U铝合金 | 约25美元 |
| ELEGOO杜邦跳线套件 | 用于布线 | 约8美元 |
| M2.5铜柱套件 | 安装硬件 | 约8美元 |
| 12V 2A电源适配器 | 为IO板供电 | 约12美元 |
| CR2032纽扣电池 | 用于板载RTC | 约5美元 |
| **总计(新部件)** | | **约103美元** |
CM4和IO板为现有库存。
**本次构建 vs TimeHAT方案:**
| 项目 | 本次构建 | TimeHAT方案 |
|------|----------|-------------|
| 计算单元 | CM4 + IO板(已有) | Raspberry Pi 5(约80美元) |
| GPS集成 | SR1723U10 + 布线(约23美元) | TimeHAT + OCP M.2 GNSS模块(约395美元) |
| 天线 | Bingfu + 转接线(约20美元) | 同款天线(约20美元) |
| 振荡器 | 标准晶振 | 温补晶振(TCXO) |
| **新支出** | **约103美元** | **约475美元+** |
振荡器差异至关重要。TimeHAT包含温补晶振(TCXO),可补偿温度引起的频率漂移。在GPS保持模式下,TCXO能显著提升时间保持精度,因为其频率在板卡温度变化时保持稳定。CM4采用无温度补偿的标准晶振。本构建在10小时保持测试中产生15毫秒漂移,对此用例可接受。在保持精度关键的生产环境中,TCXO值得额外投入。
TimeHAT还采用Intel i226网卡而非依赖CM4板载BCM54210PE,使用标准SMA接口且无需跳线。若从零开始硬件准备,该方案更简便。若已拥有CM4并想理解PHY层工作原理,本构建以低成本实现目标。
**关键硬件事实:**CM4采用BCM54210PE以太网PHY,具备完整IEEE 1588v2硬件时间戳支持。这使CM4上亚微秒级PTP成为可能。BCM54210PE在PHY内部的物理线路层直接为数据包添加时间戳,远早于数据包进入内核网络栈。这消除了内核调度和中断处理带来的抖动。
**客户端设备:**
- Turing Pi 2集群板(RTL8370MB-CG+交换芯片)
- RK1计算模块(Rockchip RK3588,Ubuntu 22.04)
- CM4(Ubuntu 24.04),即k8s1节点
Turing Pi 2拥有两个外部RJ45端口,均桥接至与四个节点插槽相同的交换矩阵。主时钟插入ge1(第二个RJ45端口)。RK1和CM4客户端节点位于内部节点插槽。所有设备均连接RTL8370MB-CG+交换矩阵,意味着主时钟与客户端间的PTP包仅经过单次交换跳转,无需路由。
## 为何选择Ubuntu 24.04
CM4最初运行Ubuntu 22.04(内核5.15.0-1093-raspi)。BCM54210PE的PTP支持于2022年加入Raspberry Pi内核树,随后合入主线Linux,但Ubuntu 22.04的raspi内核未包含此支持。结果是既无PHC设备也无硬件时间戳:
```
$ ethtool -T eth0
Time stamping parameters for eth0:
Capabilities:
software-transmit
software-receive
software-system-clock
PTP Hardware Clock: none
$ ls /sys/class/ptp/
(empty)
```
由于缺少`/dev/ptp0`,SatPulse无硬件时钟可驯服,GPS无法到达网络时间。
另存在次要问题:Ubuntu 22.04在`cmdline.txt`中设置`console=ttyAMA0,115200`,将内核控制台连接至GPS模块使用的同一UART。这导致dmesg持续出现输入溢出,GPS端口输出乱码。
升级至Ubuntu 24.04(内核6.8.0-raspi)解决了这两个问题:
```
$ ethtool -T eth0
Time stamping parameters for eth0:
Capabilities:
hardware-transmit
hardware-receive
hardware-raw-clock
PTP Hardware Clock: 0
$ ls /sys/class/ptp/
ptp0
```
## 布线
SR1723U10通过五根杜邦线连接CM4 IO板。四根用于电源和串行UART,第五根将PPS信号连接至J2排针。
| SR1723U10引脚 | 线色 | CM4 IO板连接位置 |
|---------------|------|------------------|
| VCC | 红色 | 40针排针第1脚(3.3V) |
| GND | 棕色 | 40针排针第6脚 |
| TX | 橙色 | 40针排针第10脚(RXD0) |
| RX | 黄色 | 40针排针第8脚(TXD0) |
| PPS | 绿色 | J2排针第9脚(SYNC_OUT) |
J2排针位于CM4 IO板以太网接口附近的小型10针排针。第9脚标记为SYNC_OUT,连接至BCM54210PE PHY的外部时间戳输入端。这就是GPS秒脉冲信号进入硬件时钟的路径。
## 操作系统配置
在`/boot/firmware/config.txt`添加:
```
dtoverlay=disable-bt
enable_uart=1
dtoverlay=i2c-rtc,pcf85063a,i2c_csi_dsi
```
前两行禁用蓝牙并将`/dev/ttyAMA0`连接至GPIO排针,以便GPS模块与CM4通信。第三行为CM4 IO板启用正确的I2C总线上的板载PCF85063A实时时钟。
从`/boot/firmware/cmdline.txt`移除串行控制台:
```
# 从cmdline.txt中移除以下内容:
console=ttyAMA0,115200
```
禁用蓝牙服务。`dtoverlay=disable-bt` overlay将蓝牙与UART硬件断开,但`hciuart`服务仍会尝试初始化并可能干扰:
```
sudo systemctl disable hciuart
```
重启后验证GPS模块是否以38400波特率输出NMEA数据:
```
(stty 38400 -echo -icrnl; cat) </dev/ttyAMA0 | head -10
```
应看到以`$GNRMC`、`$GNGGA`等开头的行。SR1723U10默认波特率为38400,而非许多指南假设的9600。
## 软件栈
技术栈为SatPulse (https://satpulse.net/) + ptp4l + chrony。SatPulse是由jclark (https://github.com/jclark)编写的守护程序,将GPS模块、PHC、ptp4l和chrony集成。它通过UBX协议处理GPS配置,从PHC读取PPS时间戳,驯服PHC频率,并通过SOCK参考时钟向chrony提供样本。
从GitHub发布页面安装SatPulse(arm64 .deb包):
```
wget https://github.com/jclark/satpulse/releases/download/v0.3.0/satpulse_0.3.0_arm64.deb
sudo dpkg -i satpulse_0.3.0_arm64.deb
```
在`/etc/satpulse.toml`配置SatPulse:
```
[phc]
interface = "eth0"
[serial]
speed = 38400
[gps]
config = true
[ntp]
sock.path = "/var/run/chrony.satpulse.sock"
[ptp]
ptp4l.udsAddress = "/var/run/ptp4l"
```
安装linuxptp并在`/etc/linuxptp/ptp4l.conf`配置ptp4l作为主时钟:
```
[global]
masterOnly 1
tx_timestamp_timeout 100
ptp_minor_version 0
[eth0]
```
复制SatPulse的ptp4l服务文件:
```
sudo cp /usr/share/doc/satpulse/ptp4l.service /etc/systemd/system/ptp4l.service
sudo systemctl daemon-reload
sudo systemctl enable --now ptp4l
```
在`/etc/chrony/conf.d/satpulse.conf`配置chrony:
```
refclock SOCK /var/run/chrony.satpulse.sock poll 2 filter 4 refid GNSS
```
在`/etc/chrony/chrony.conf`添加允许指令,使客户端可使用主时钟作为NTP服务器:
```
allow 192.168.0.0/24
log tracking measurements statistics
```
重启chrony:
```
sudo systemctl restart chrony
```
启用并启动SatPulse:
```
sudo systemctl enable --now satpulse@ttyAMA0
```
## 故障与注意事项
这是最有趣的部分。
### BCM54210PE SYNC_OUT引脚缺陷
每次系统启动时,BCM54210PE驱动会将SYNC_OUT引脚初始化为输出模式(`1 0`)而非输入模式(`0 1`)。SatPulse尝试重新配置但静默失败。结果是`无PTP硬件时钟外部时间戳接收`,主时钟完全失效。
诊断方法:
```
cat /sys/class/ptp/ptp0/pins/SYNC_OUT
# "1 0"表示引脚卡在输出模式
sudo satpulsetool sdp -i --pin 0 eth0
# "no timestamps received"表示PHC未接收PPS
```
修复方法:在SatPulse启动前强制引脚进入正确状态。创建`/etc/systemd/system/[email protected]/override.conf`:
```
[Unit]
After=chrony.service ptp4l.service
Requires=chrony.service
[Service]
ExecStartPre=/bin/sh -c 'sleep 5 && echo 1 0 > /sys/class/ptp/ptp0/pins/SYNC_OUT && sleep 1 && echo 0 1 > /sys/class/ptp/ptp0/pins/SYNC_OUT'
```
从输出切换到输入强制驱动器正确重置引脚状态。`sleep 5`确保chrony和ptp4l完成启动后SatPulse再连接其套接字。
### 实时时钟未启用
CM4 IO板包含带电池座的PCF85063A实时时钟。若未在`config.txt`中添加`dtoverlay=i2c-rtc,pcf85063a,i2c_csi_dsi`,内核无法识别RTC存在。每次重启时钟重置为重启前的已知时间(某次甚至落后数周),chrony随之大幅跳变时间。SatPulse因接收到的PPS时间戳远超系统时间而失败。
添加overlay后,将RTC设置为系统时间:
```
sudo hwclock -w
```
重启后验证:
```
date
sudo hwclock --show
# 两者应显示大致相同的当前时间
```
### 服务启动顺序至关重要
若无显式顺序,SatPulse可能在chrony或ptp4l创建Unix套接字前启动。上述override文件中的`After`和`Requires`指令解决了此问题。
## 客户端配置
在每个客户端安装linuxptp。Ubuntu 24.04包含该包但未提供systemd服务文件。创建`/etc/systemd/system/ptp4l.service`:
```
[Unit]
Description=Precision Time Protocol (PTP) service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/sbin/ptp4l -f /etc/linuxptp/ptp4l.conf
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
```
**CM4客户端(linuxptp 4, Ubuntu 24.04)**配置位于`/etc/linuxptp/ptp4l.conf`:
```
[global]
clientOnly 1
tx_timestamp_timeout 200
ptp_minor_version 0
[eth0]
```
**RK1客户端(linuxptp 3, Ubuntu 22.04)**配置位于`/etc/linuxptp/ptp4l.conf`:
```
[global]
slaveOnly 1
tx_timestamp_timeout 100
[eth0]
```
在两个客户端`/etc/chrony/conf.d/ptp.conf`配置chrony:
```
refclock PHC /dev/ptp0 poll 0 dpoll -2 tai refid PTP
```
`tai`关键字告知chrony PHC采用国际原子时时标,自动应用37秒UTC偏移量。
将主时钟添加为NTP源用于比较:
```
server 192.168.0.6 iburst minpoll 0 maxpoll 4
```
更新makestep使chrony在大偏移时立即跳变而非缓慢调整:
```
makestep 1 -1
```
## 测试结果
### 主时钟精度
正常工作时,SatPulse摘要如下:
```
satpulsed: summary: absOffMax=18 absOffMean=6.4 offRMS=7.8 freqMean=3533 nMissing=0 nOutliers=0
```
主时钟PHC与GPS真值偏差在18纳秒内,平均偏移6纳秒。
### 三层时间对比
主时钟同时提供PTP和NTP服务,客户端可同时观察三个层级:
| 来源 | 偏移量 | 不确定性 |
|------|--------|----------|
| PTP,硬件时间戳 | 3-4纳秒 | ±66-291纳秒 |
| 局域网NTP,来自本主时钟 | +31至+108微秒 | ±79-172微秒 |
| 广域网NTP,公共池 | +1至+3毫秒 | ±40-82毫秒 |
主时钟为同一物理机器,差异完全源于时间传递与测量方式。±值为chrony报告的不确定性范围:真实偏移量可能落入的区间。PTP使用PHY层物理线路硬件时间戳,局域网NTP使用内核软件时间戳(引入内核调度和中断处理抖动),广域网NTP额外增加网络路径抖动。
每层级精度约比上层差1000倍。
### 客户端对比:CM4 vs RK1
CM4客户端(k8s1)稳定达到±66纳秒不确定性,RK1达到±291纳秒。两者结果均良好,但存在4倍差距。
CM4客户端采用与主时钟相同的BCM54210PE PHY,在PHY层(物理线路层)打时间戳。RK1使用Rockchip GMAC及不同的PHC实现在MAC层打时间戳,距离物理线路更远。数据包从到达硅片到捕获时间戳间的每个附加阶段都增加抖动。RK1的±291纳秒下限反映了这一点。
```
#* PTP 0 0 377 1 -3ns[ -4ns] +/- 291ns <- RK1
#* PTP 0 0 252 2 +3ns[ +3ns] +/- 66ns <- k8s1 (CM4)
```
### 拓扑结构影响显著
主时钟通过TP-Link AXE5400消费级路由器 vs 直接连接Turing Pi交换机。
**通过消费级路由器:**
```
ptp4l: master offset -16580 s2 path delay 469541
ptp4l: master offset -178615 s2 path delay 485331
ptp4l: master offset 246261 s2 path delay 485331
```
路径延迟约480微秒,偏移波动±700微秒。
**直连Turing Pi交换机:**
```
ptp4l: master offset -13 s2 path delay 2615
ptp4l: master offset 127 s2 path delay 2607
ptp4l: master offset -14 s2 path delay 2615
```
路径延迟约2.6微秒,偏移在±130纳秒内。
仅移除消费级路由器,路径延迟改善180倍。消费级路由器通过软件队列缓冲数据包,产生可变且不可预测的延迟。此变异性直接计入PTP路径延迟计算,降低偏移估算精度。Turing Pi交换机以硬件速率传递流量,延迟稳定。
### 保持测试
我断开GPS天线10小时过夜。失去GPS输入后,SatPulse进入保持模式,主时钟仅依靠CM4本地晶振参考运行。clockClass从6(GPS锁定)变为52(保持模式)。
相似文章
PTP墙钟不实用且过于精确
使用树莓派和LED矩阵显示器构建PTP墙钟的指南,演示通过精确时间协议实现精确时间同步。
WiFi 时间
一篇关于一个已废弃项目的详细记录,该项目旨在构建一个“假的”GPS模块,通过WiFi使用NTP和ESP8266获取时间,目标达到亚毫秒精度,但最终因硬件限制未能实现。
我想要一个永远不需要调校的时钟。事情升级了。
一位科技爱好者记录了自己用树莓派、3D打印和开源软件打造自定义自动校时LED时钟的过程,此前他对现有产品感到沮丧。
BBC Master Pi 1MHz Domesday
Dominic Plunkett 更新了 BBC Micro 的 PiMHz 软件,使其能够模拟 BBC AIV 系统的大部分硬件,包括 LV 播放器,从而使 Domesday 光盘可以在轨迹球/鼠标和 PiTubeDirect 的配合下运行。视频介绍了 PiMHz 的实现原理、设置方法,并演示了社区版和国家版光盘。
我构建的软件:25MHz 486-SX上的GPS
一位开发者回顾了在1990年代初期,在一台25MHz 486-SX电脑上使用Hipparchus库进行高效整数运算,构建实时GPS驱动的动态地图显示,其性能在长达十年内超越了消费级GPS设备。