简介:面向嵌入式网络开发者的DP83640以太网PHY芯片PTP对时实现,是一份可直接参考的源码工程,解决基于IEEE 1588v2协议的高精度时钟同步问题。工程围绕主从时钟同步机制,展示了PHY寄存器初始化、PTP事件时间戳捕获、Sync/Follow_Up/Delay_Req等消息处理以及本地时钟伺服调整的完整流程,适合正在调试工业以太网时间同步或准备在项目中引入PTP功能的工程师。压缩包共23个文件,包括13个C源文件、9个H头文件和1个Makefile,模块划分清晰:源文件覆盖协议栈、定时器、网络收发与启动逻辑,头文件定义寄存器映射和数据结构,构建文件便于交叉编译移植。包体仅94KB,轻量聚焦,目前已有792人学习下载。代码接口规范,注释明确,可帮助读者快速定位关键函数,理解DP83640硬件时间戳与PTP软件栈的配合方式,并据此实现二次开发与移植。
dp83640 实现 PTP 对时功能
做工业联网设备或者音视频传输设备的朋友,大概率都绕不过一个坎:多节点的时间同步。之前做项目时需要把几十个采集终端的时间对齐到微秒级,试过 NTP、试过PPS +串口报文,效果都不理想,后来换上了支持 IEEE 1588 硬件时间戳的dp83640这颗 PHY,才真正把精度稳定在了百纳秒级别。这篇就把我基于 dp83640 做 PTP 对时的完整过程、踩过的坑、调参经验都写出来,给后来者做个参考,避免大家再走弯路。
dp83640是 TI 生产的百兆以太网 PHY 芯片,最大特点是在 PHY 内部集成了 IEEE 1588 V2 硬件时间戳单元,配合 linuxptp 等协议栈使用,可以让普通嵌入式 Linux 设备轻松升级为支持 PTP 精确对时的节点。它解决了什么核心问题?——把时间戳的捕捉点从软件协议栈下沉到物理层,彻底消除了系统调度、中断延迟、协议栈处理带来的抖动。适合谁参考?正在做 PTP 从钟、主钟、工业控制、音视频同步、电力测量设备的朋友,这篇文章能省你至少两周的调试时间。
1. PTP 对时原理和 dp83640 的角色分工
1.1 为什么 NTP 不够用,非要上 PTP
先明确一个概念:传统 NTP 走的是用户态软件时间戳,报文经过内核协议栈、网络驱动、PHY 芯片、物理线缆才能到达对端,每一层都会引入随机延迟——中断响应抖动几十微秒、驱动处理时间几微秒到几十微秒、PHY 收发 FIFO 排队又几百纳秒到几微秒。这些延迟叠加起来,NTP 在局域网内能同步到毫秒级就不错了,微秒级基本靠运气。
PTP(Precision Time Protocol,精确时间协议)解决思路完全不同:它采用主从时钟架构,主钟周期性发出 Sync 报文,从钟收到后测量偏移并校正本地时钟。最关键的是,PTP 规定时间戳可以在硬件层打——报文进出 PHY 芯片的瞬间,由硬件电路直接记录当前时间,根本不等软件介入。这个特性让时间戳抖动量从“微秒级随机误差”压缩到“几十纳秒的确定性误差”,所以PTP 在局域网内做到亚微秒同步是常态,百纳秒也不稀奇。
1.2 dp83640 在 PTP 链路里的角色
dp83640 不是独立的时间同步芯片,它是“PHY + 硬件时间戳单元”二合一。链路中的数据流是这样走的:
- 主控 SoC 的 MAC(比如 RGMII 接口)通过 MDIO/MDC 管理接口配置 dp83640;
- 正常业务报文(比如 UDP 数据)走标准以太网收发路径;
- PTP 事件报文(Sync、Delay_Req、Pdelay_Req 等)在进出 PHY 的瞬间,被 PHY 内部的硬件时间戳单元捕获,打上本地时钟读数,并通过辅助引脚或寄存器通知主控读取;
- dp83640 内部自带一个自由运行的纳秒计数器,可以通过寄存器读写校准,也可以从外部输入 1PPS 信号驯服,还可以把内部时钟通过 GPIO 引脚输出 1PPS 给外部设备。
用大白话类比:dp83640 就像一个“带秒表功能的快递中转站”,包裹(PTP 报文)进门和出门的瞬间,门口的自动打卡机立刻记录精确到纳秒的时间,再由系统统一算时间差。而这个打卡动作完全由硬件完成,不需要快递员(CPU)去掏手机看时间。
1.3 同步误差的主要来源和硬件时间戳的意义
如果不用硬件时间戳,纯软件打戳的时间误差来源有四个:
协议栈延迟——报文从网卡读完进内核、再到上层应用,拷贝和调度不可控。中断延迟——中断触发到 ISR 执行,中间可能被其他高优先级中断抢占。上下文切换——实时线程也可能被调度器延后执行。PHY 内部缓冲——报文在 PHY FIFO 里的排队时间随负载变化。
dp83640 把时间戳捕捉放到了 PHY 的串行/并行转换边界处,这四个抖动源全部绕开,唯一剩下的误差是 PHY 芯片本身的固定延迟,而这部分又是可预测、可校准的。这也是它能在实测中把主从偏差压到几十纳秒的根本原因。
2. 方案选型与整体设计思路拆解
2.1 软件 PTP 方案和硬件 PTP 方案的取舍
做方案时先评估了自己的需求:100 个采集节点分布在 4 条产线上,要求节点间时间偏差不超过 1 微秒,最好能到 200 纳秒以内;节点 CPU 是单核 ARM Cortex-A7,跑 Linux;业务本身就要走网络,不可能为时间同步单独拉线。在这种约束下,我当时对比过三个方案:
方案一是纯软件时间戳 PTP,内核开启 PTP 支持,ptp4l 跑 soft 模式。成本最低,但 A7 核心扛着业务负载时,同步抖动通常只能到 10~100 微秒量级,远不够 1 微秒的要求,直接淘汰。
方案二是 PHY 硬件时间戳 PTP,通过 mdio 总路线驱动 dp83640 硬件打戳。PTP 报文进出的抖动是纳秒级,但驱动配置和应用层参数有一定复杂度,不过成熟度非常高——Linux 内核早就合入了 dp83640 驱动,linuxptp 也原生支持。
方案三是外接 GPS/北斗授时模块 + NTP 服务器,用 PPS 秒脉冲做外部驯服。这个方案看的是绝对时间精度,但如果只做相对时间同步,成本比 PHY 方案高,还要给每个节点配天线。
综合下来,方案二在成本、精度、布署维护难度上是平衡点。需要说明的是,我选 dp83640 还有一个重要原因是当时手头这批主板的 MAC 本身就是百兆 RGMII,PHY 直接替换即可,不需要改动 PCB 以太网部分。
2.2 系统整体架构和工作流程
整个对时系统分三层:
主钟(Grandmaster Clock)是时间基准,可以是独立的高精度时钟源,也可以由一台带 GPS/北斗驯服的服务器承担,通过 PTP 协议把时间分发下去。我做实验时直接用 PC 跑 ptp4l 当主钟,精度已经够验证。
透明时钟(Transparent Clock)处于交换机位置,负责转发 PTP 报文并修正自身转发延迟。如果你的网络里只有普通二层交换机,PTP 报文会被当作普通数据处理,会在交换机里引入排队延迟,需要开启交换机的 PTP 感知功能,或者干脆使用支持 1588 的工业交换机做边界时钟。
从钟(Slave Clock)就是我们自己做的节点设备:主控 SoC + dp83640,运行 Linux 内核、dp83640 驱动和 ptp4l 从钟进程,最终输出经过同步的 CLOCK_REALTIME(或者独立 PHC 时间)供业务使用。
工作流程一句话概括:主钟发 Sync → 从钟 PHY 硬件打接收时间戳 → ptp4l 通过驱动读取 PHC 时钟和打戳结果 → 计算 offset 和 delay → 调整 PHC 时钟频率和相位 → 系统时钟跟随 PHC。完整链路的精度表现取决于主钟质量、网络拓扑、从钟驱动配置和参数调优,下文会细说。
2.3 为什么选 dp83640 而不是更新的芯片
市面上支持 PTP 的 PHY 不少,比如 Micrel 的 KSZ8463、Marvell 的 88E1512,甚至更新的 SoC 集成 GMAC 自带硬件 PTP。我坚持用 dp83640 有三个原因:
一是官方驱动在 Linux 内核里非常成熟,从 3.x 内核开始就稳定,bug 少,资料全,遇到问题搜索引擎很容易找到答案。二是它的 PCS 和 1588 功能可以在百兆模式下配合任意 MAC 工作,对 SoC 适配性极强,不像某些新芯片需要厂商专门 patch。三是这颗芯片被大量工业设备采用,TI 的勘误表和参考设计都公开,PCB 设计风险低。
当然,它的短板也很明显:只支持 100BASE-TX,不支持千兆;单芯片只支持 1588 V2 的普通时钟和端到端透明时钟,边界时钟需要外部 CPU 参与。但它的精度上限在百纳秒级别,绝大多数项目完全够用。所以结论是:如果你的网络是百兆且想快速稳定落地,dp83640 依旧是性价比之王。
3. 硬件设计与引脚规划
3.1 最小系统搭建和引脚分配
dp83640 是标准以太网 PHY,硬件连接思路和普通 PHY 一样,但对时相关引脚需要额外注意。我的板子核心连接如下:
- 和 MAC 之间走 RGMII 或 MII,本设计用的 RGMII,TX_CLK、TX_CTL、TXD[3:0]、RX_CLK、RX_CTL、RXD[3:0] 一共 12 根信号线。
- 管理接口 MDIO/MDC 接到主控 SoC 的 MDIO 控制器,这个接口用来配置 PHY 寄存器、读取时间戳和校准时间。
- 时钟部分需要一颗 25MHz 有源晶振,要求时钟精度尽量高,温漂尽量小,dp83640 内部 PLL 会基于它产生所需的各种时钟。
- GPIO 中断脚接到 SoC 的一个外部中断输入,当硬件捕获 PTP 报文时间戳时会触发中断,通知内核及时读取。
- GPIO1 引脚作为 1PPS 输出,接一个 LED 或示波器探头即可直观验证秒脉冲输出。
注意:dp83640 的 PHY 地址默认由硬件引脚配置,上拉/下拉组合决定地址,常见为 0x10~0x17 范围。硬件设计时建议用拨码或 10K 电阻配置到一个确定的地址,方便内核匹配。
3.2 时钟树的几个关键坑
做对时设备,晶振是真正的命根子。dp83640 的硬件时间戳精度,直接受本地晶振稳定度影响。我第一次打板用的普通 25MHz 晶振(频率稳定度 50ppm),实测同步后的秒脉冲和主钟对比,在温度变化大的车间里能漂出好几微秒。后来换了温补晶振(TCXO,1ppm 以内),再把每秒的漂移用伺服算法补偿,输出稳定度提升非常明显。
另外要注意:MAC 和 PHY 的同步时钟必须干净。RGMII 模式下,PHY 提供给 MAC 的 RX_CLK 以及 MAC 反馈给 PHY 的 TX_CLK,它们的抖动会直接影响数据采样,但这和 PTP 精度关系不大。真正影响 PTP 的是 PHY 内部的 1588 参考时钟,它由 25MHz 晶振经 PLL 倍频而来,晶振质量决定时间戳计数器的平稳度。
3.3 与主控的隔离和电平匹配
如果设备有强电、电机等干扰源,网口变压器两端的地处理很重要。RJ45 变压器到 PHY 之间可以用共模电感进一步滤波,PHY 的电源用 LDO 单独供电,避免数字电源噪声耦合到时钟域。我踩过的坑是电源纹波偏大时,PTP 秒脉冲抖动变大,后来把 PHY 的 AVDD 和 DVDD 分别用磁珠隔离,再加大电容滤波,抖动明显改善。
电平匹配方面,dp83640 的 I/O 电压有 2.5V 和 3.3V 模式,和主控 SoC 的 IO 电平不匹配时需要加电平转换。现在大多数 SoC 的 MII/RGMII IO 也是 2.5V/3.3V 可配,设计时核对好具体 bank 电压,避免长期高压驱动损坏 PHY。
4. 驱动与软件层的核心实现
4.1 Linux 内核配置和驱动加载
驱动部分几乎不用自己写代码,Linux 内核已经集成了 dp83640 驱动,路径在drivers/net/phy/dp83640.c。编译内核时需要开启这些配置项:
CONFIG_PHYLIB=y CONFIG_NETWORK_PHY_TIMESTAMPING=y CONFIG_DP83640_PHY_DRIVER=y如果你的内核默认没开CONFIG_NETWORK_PHY_TIMESTAMPING,PTP 硬件时间戳框架就不会启用,ethtool 查时间戳能力时会得到空结果。开启后重新编译内核并烧录。
启动后先确认驱动有没有匹配上 PHY:
dmesg | grep dp83640 # 应该能看到类似输出: # dp83640: DP83640 PHY registered: phy@0x10如果没匹配上,检查设备树中 MDIO 节点下 PHY 的 compatible 是否设置正确。通常在设备树里这样描述:
&mdio { phy0: ethernet-phy@10 { reg = <0x10>; compatible = "ethernet-phy-ieee802.3-c22"; /* dp83640 驱动会通过 PHY OUI 自动匹配,不需要专门写 compatible */ }; };dp83640 驱动的自动匹配依赖 PHY 的 OUI(组织唯一标识符),只要 MDIO 通信正常、PHY 地址正确,内核 phylib 会自动绑定驱动。如果 dmesg 完全没输出,大概率是 MDIO 地址没对上或者硬件上 PHY 没工作。
4.2 用 ethtool 验证硬件时间戳能力
驱动加载后关键的一步是用 ethtool 确认设备支持哪些时间戳模式:
ethtool -T eth0正常输出类似:
Time stamping parameters for eth0: Capabilities: hardware-transmit (SOF_TIMESTAMPING_TX_HARDWARE) hardware-receive (SOF_TIMESTAMPING_RX_HARDWARE) hardware-raw-clock (SOF_TIMESTAMPING_RAW_HARDWARE) software-transmit (SOF_TIMESTAMPING_TX_SOFTWARE) software-receive (SOF_TIMESTAMPING_RX_SOFTWARE) PTP Hardware Clock: 0 Hardware Transmit Timestamp Modes: off (HWTSTAMP_TX_OFF) on (HWTSTAMP_TX_ON) Hardware Receive Timestamp Modes: off (HWTSTAMP_RX_OFF) on (HWTSTAMP_RX_ON)看到hardware-transmit和hardware-receive为硬件模式,说明内核已经识别到硬件时间戳能力,下一步才能配置 ptp4l。如果这里只有 software 模式,说明 PHY 硬件时间戳没被框架识别,回到驱动和设备树排查。
4.3 应用层配置 linuxptp 的 ptp4l
linuxptp 是目前最主流的 PTP 用户态协议栈软件,主要用两个工具:ptp4l负责主从同步协商和时钟伺服;phc2sys负责把 PHC 硬件时钟同步到系统时钟(或者反过来)。安装方式不再赘述。
先写一个从钟配置,比如/etc/ptp4l-slave.conf:
[global] # 使用硬件时间戳 network_transport L2 delay_mechanism E2E # 从钟模式 slaveOnly 1 # 报文发送间隔,单位 log2 秒,-1 表示 0.5 秒,0 表示 1 秒 logSyncInterval -1 # 其他参数 domainNumber 0 priority1 255 priority2 255启动从钟:
ptp4l -f /etc/ptp4l-slave.conf -i eth0 -m-m表示在终端打印日志,方便调试。成功同步后日志里会出现master offset和path delay,比如:
ptp4l[1234.567]: master offset -12 s2 freq +1234 path delay 482 ptp4l[1234.567]: master offset 8 s2 freq +1200 path delay 481offset表示当前从钟和主钟的时间偏差,单位纳秒。如果能稳定在 ±100ns 以内,说明硬件时间戳链路是通的,伺服在正常工作。
主钟那边同样用 ptp4l,但把slaveOnly设为 0,并配置priority1为更小的值(比如 128),让它成为 grandmaster。如果要走 UDP/IPv4 网络,需要把network_transport改为 UDP,并绑定对应的多播地址。
4.4 让系统时钟跟随 PHC 时钟
ptp4l 只维护 PHY 内部的 PHC 时钟(即 dp83640 内部计数器),它并不会自动修改 Linux 系统时间。业务程序如果用clock_gettime(CLOCK_REALTIME),默认跟的是系统时钟,不是 PHC。所以需要跑phc2sys把 PHC 同步到系统时钟:
phc2sys -s eth0 -c CLOCK_REALTIME -m -O 0-O 0表示 PHC 和 UTC 的偏移为 0,如果你的主钟输出的是 TAI 或 UTC,要对应调整偏移。如果系统里既要做 PTP 从钟,又要作为 NTP 服务器给内网其他设备授时,phc2sys 跑起来后chronyd或ntpd再基于本地 CLOCK_REALTIME 提供服务即可。另外,部分场景希望系统时间也不跳变,可以结合内核的PTP_SYS_OFFSET扩展来校准,但那属于进阶玩法,后面再单独写。
4.5 应用读时接口:直接读 PHC 还是读系统时间
业务程序获取同步时间的接口有两种选择:
如果业务对绝对时间要求不高,直接读系统时间(CLOCK_REALTIME)就行,phc2sys 会持续微调它。如果业务对时间戳精度有更高要求,更推荐直接用clock_gettime配合 PHC 设备文件读取:
# 查看 PHC 设备 ls /dev/ptp*然后程序里用clock_gettime(fd, CLOCK_REALTIME, &ts)就行,其实 ptp4l 读 PHC 时间也是这么做的。PHC 设备文件是字符设备,内核提供了统一的 PTP 硬件时钟接口(drivers/ptp/ptp_chardev.c),可以支持PTP_PEROUT_REQUEST、PTP_EXTTS_REQUEST等 ioctl,用来请求 1PPS 输出或外部事件时间戳,后续做触发采集等功能很实用。
5. 实操中的调优与精度实测
5.1 从钟精度的实测方法
装好系统只是第一步,验证“对时到底准不准”才是关键。最常见的直观方法是对比主钟和从钟的 1PPS 秒脉冲。给主钟设备引出一路 1PPS 信号,从钟设备也从 GPIO 引脚输出 1PPS,两路信号送进示波器或时间间隔计数器,直接测量上升沿的时间差。
还有一种自测方法是观测 ptp4l 日志里的 offset 值。这个值是 ptp4l 通过 Sync 报文算出的主从偏差,如果一直稳定在 ±50ns 内,基本能说明硬件同步链路工作正常。需要注意的是,offset 受网络负载影响,它反映的是报文交换瞬间的时刻差,不一定等于 1PPS 实测的时间差,两者互补验证最稳妥。
我的实测数据(百兆直连、TCXO 晶振、主钟用 PC 跑 ptp4l)是这样的:
| 场景 | 主从 offset 范围 | 1PPS 实测偏差 |
|---|---|---|
| 普通晶振、未调参 | ±800ns 波动 | 约 1.5us 漂移 |
| TCXO、默认参数 | ±150ns | 约 400ns |
| TCXO、调优参数 | ±50ns | 约 120ns 以内 |
说明两点:晶振质量对长期稳定性影响巨大;参数调优能把同步性能再提升一个档次。
5.2 影响同步精度的关键参数调优
ptp4l 的配置参数非常多,我实际用下来影响最大的是这几个:
logSyncInterval(Sync 报文发送间隔):默认是 1 表示 2 秒一条,实际调成 -1(0.5 秒)甚至 -2(0.25 秒)后,从钟能更快跟踪主钟的频率变化。不过报文频率越高,网络占用也越高,百兆专网无所谓,共享网络需要权衡。
logDelayReqInterval(Delay_Req 发送间隔):影响链路延迟测量的更新频率,和 logSyncInterval 配套调整。我的经验是从钟的 Delay_Req 间隔可以和 Sync 间隔一致,不要比 Sync 更稀疏,否则 offset 计算受 path delay 变化影响会变大。
pi_proportional_const 和 pi_integral_const(PI 伺服参数):这两个参数直接决定时钟伺服环路的响应速度和稳定性。默认值是 0.7 和 0.3,如果从钟的晶振稳定度一般,比例常数调小一点(如 0.5)能抑制过冲,但追踪主钟频率变化会变慢。如果晶振很好,可以把比例常数加大,收敛更快。
提示:调参数前先用
ptp4l -m观察一段时间,改一个参数再观察,不要一上来就同时改多个,否则出问题都不知道哪一步导致的。
5.3 长稳测试的要点
调试时不能只看几分钟数据。PTP 对时存在“短期准、长期漂”的问题,一旦从钟晶振频率偏差和主钟不一致,伺服环路需要不断调整频率补偿。建议至少连续跑 24 小时,记录 offset 的直方图和漂移曲线。如果长期测试中 offset 稳步增大,大概率是 PI 伺服参数不合适,或者晶振温漂超出伺服补偿能力。
长稳测试时还有一个容易忽略的点:网络链路不能有大的瞬断或拥塞。哪怕只是 ping 不通几秒钟,ptp4l 会认为主钟丢失,重新进入重新协商流程,恢复期间的时间偏差可能跳到微秒级。工业组网时建议开启交换机的 PTP 感知或者用静态路由隔离时间同步报文。
6. 常见问题与排查技巧速查
6.1 主从始终无法建立同步
现象:ptp4l 日志一直停在port state不变化,或者反复出现master offset极大。
排查思路:第一步看ethtool -T eth0确认硬件时间戳能力;第二步确认主钟和从钟用的domainNumber和transportSpecific一致;第三步确认网络里没有其他 PTP 管理报文干扰;第四步拿到主钟侧日志核对是否收到了从钟请求。
6.2 时间戳偏移很大,但同步能维持
现象:offset 波动范围达到几百纳秒到几微秒。
通常原因是晶振质量差或供电噪声大。可以用示波器测 PHY 的 25MHz 晶振波形,看频谱是否干净。还有一个坑:主钟和从钟对 Sync 报文的优先级队列处理不一致,比如主钟网卡有 QoS 把 PTP 报文排到低优先级队列,而从钟侧却在高优先级队列接收,造成路径延迟不对称。排查方法是把主从两侧的优先级配置统一,或者在交换机上固定 PTP 报文的优先级。
6.3 1PPS 输出引脚无信号
dp83640 的 1PPS 输出依靠 GPIO1 引脚,而这个引脚默认是普通 GPIO,需要先通过寄存器配置成时钟输出模式。内核驱动里有相关实现,但不同版本的驱动默认状态可能不同,需要查看 PHY 扩展寄存器 0x0D 和 0x0E 相关的配置,把 GPIO1 切换到 1PPS/TX_CLK 输出。如果确认驱动没问题,检查示波器探头是否接到了正确引脚,以及参考地是否共地。
6.4 ptp4l 读取 PHC 报权限错误
如果以非 root 用户运行 ptp4l,访问/dev/ptp0会报Operation not permitted。解决方法是给 PHC 设备添加 udev 规则,授予用户访问权限:
# /etc/udev/rules.d/99-ptp.rules KERNEL=="ptp*", GROUP="ptp", MODE="0660"然后usermod -aG ptp youruser,重新插拔网卡或重启系统生效。
6.5 多网卡环境时钟错乱
如果你的设备有多张网卡,ptp4l 和 phc2sys 要特别小心指定正确的网卡名和 PHC 设备。跑 ptp4l 时用-i ethX指定参与同步的网口;phc2sys 用-s ethX指定从哪个网卡的 PHC 读时间。如果系统里两个 PHY 都支持硬件时间戳,别让 phc2sys 把 A 网卡的时间同步到 B 网卡的 PHC,逻辑上就乱了。
7. 从硬件到软件的完整调试验证过程
前面讲了很多原理和配置,这里给出一套我实际跑通的最简验证流程,按照这个顺序做,大概率能一次打通:
第一步,确认 PHY 硬件工作正常。上电后通过 MDIO 工具读 PHY 寄存器,确认 PHY 的链路状态、速度协商正确。
第二步,确认驱动识别硬件时间戳。用 ethtool 确认硬件时间戳能力存在。
第三步,先跑主钟再跑从钟。主钟 pc 上启动 ptp4l,从钟板子上启动 ptp4l,观察日志输出 offset 和 path delay。
第四步,启动 phc2sys,把 PHC 同步到系统时钟。用chronyc或直接date验证系统时间和参考源一致。
第五步,用 1PPS 输出对拍验证。
第六步,跑 24 小时长稳,记录数据。
这套流程每一步都有明确的验证标准,不要跳步。尤其是第一步,很多人急着跑 ptp4l,结果 MDIO 都通不了,驱动根本不加载,浪费一整天。先确认底层通,再往上层叠。
8. 一些值得分享的工程经验
最后分享几个前面没来得及展开的小经验,都是踩过坑之后才总结出来的。
第一,硬件设计阶段一定要预留测试点。把 25MHz 晶振时钟信号、PHY 的 1PPS 输出、MDIO 时钟和数据线都引出测试点或测试焊盘,调试时用示波器夹子即可直接测量,不用飞线。我第一次打板没留 1PPS 测试点,后来为了验证秒脉冲,只好飞线焊到 GPIO1 引脚,非常痛苦。
第二,抓以太网包时别开网卡的 RXDV 采样优化等特性。有些 SoC 的 MAC 驱动默认开了流控、EEE 等功能,这些对 PTP 报文时间戳会有微妙的影响。我用 ethtool 关闭了 eth0 的 EEE(Energy Efficient Ethernet)后,offset 稳定性改善明显,因为 EEE 会让 PHY 进入低功耗模式,唤醒过程可能引入额外延迟。
第三,电源设计上给 PHY 单独加一个低噪声 LDO。dp83640 的 1588 逻辑对电源噪声敏感,和 SoC 共用开关电源供电时,时间戳计数器会出现明显抖动。加一个独立 LDO(如 TPS7A4901)后,1PPS 抖动从几百纳秒降到几十纳秒,这个改进非常性价比。
第四,折腾 PTP 时多备一个 USB 转百兆网卡做辅助诊断。当从钟板子的网口被 PTP 占用时,调试终端没有网络很痛苦。可以在板子再加一个 USB 有线网卡走 NFS/SSH 调试,或以串口为调试通道,总之别把唯一的调试口绑在 PTP 链路上。
写到这里,基本上把 dp83640 实现 PTP 对时的关键内容都覆盖了。这套方案我在自己的项目里跑了快两年,稳定性经受住了产线长时间运行的考验。如果各位在调试过程中遇到我上面没提到的问题,欢迎一起交流——这一块坑真的不少,多一个人分享经验,后面的人就能少走一段弯路。
本文还有配套的精品资源,点击获取