ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

ZYNQ上的PTP时间同步:SGMII链路配置与PetaLinux实践

ZYNQ上的PTP时间同步:SGMII链路配置与PetaLinux实践 做ZYNQ平台上的IEEE 1588/PTP时间同步链路一旦经过SGMII很多从RGMII设计里移植过来的经验就不太灵了。我最近在Zynq-7020上把这条链路完整跑通外部PHY走SGMII接入PetaLinux管理MAC和PHC时钟设备最终主从时钟同步偏差稳定在几百纳秒量级。网上关于ZYNQPTP的资料不少但大多是拿RGMII直连PHY做demo一旦中间插了SGMII环节时间戳到底在哪里打、IP核该配成MAC模式还是PCS/PMA模式、Linux侧怎么把ptp4l和硬件时钟配合好这些细节很少有人完整串起来讲。这篇文章就把我这套方案的完整思路、配置步骤和踩过的坑写出来给准备在ZYNQ上做SGMIIPTP的人做个参考。1. 为什么SGMII会成为ZYNQ上PTP方案的链路核心1.1 三种链路形态的取舍RGMII、GMII转SGMII、全PL MACZYNQ平台上跑千兆以太网物理接口的选择直接影响1588时间戳的实现难度。最常见的三种形态是PS自带GEM直接走RGMII到外部PHY、PS GEM的GMII进PL再转SGMII、以及完全在PL里做带MAC的以太网子系统。RGMII的优势是电路简单、ZYNQ原生支持但RGMII要求PHY离FPGA不远信号完整性问题多而且很多高端PHY的SGMII口只是可选的通用接口。如果板卡为了走线方便或PHY选型限制SGMII几乎是绕不开的。SGMII本身是MAC和PHY之间的串行接口1.25Gbps波特率、8B/10B编码等效千兆速率。相比RGMII它只需要一根TX差分对和一根RX差分对引脚少、抗干扰强芯片间连接非常干净。ZYNQ-7000的PS侧GEM虽然不支持直接出SGMII但PL里有现成的GTX高速收发器配合Xilinx的IP核可以把GMII或者AXI接口转成SGMII。这样一来PS GEM加PL转换再加外部PHY就是一条非常标准的工业授时板卡链路。从实际选型角度我更倾向于PS GEM PL侧SGMII PCS/PMA 外部PHY这条路线。原因很简单GEM自带硬件IEEE 1588时间戳单元Linux里对应的驱动就是xilinx_emacpsPetaLinux内核直接支持PHC设备会稳定出现在/dev/ptp0。如果一上来就用全PL的Ethernet Subsystem加MAC虽然也能做1588但驱动适配、中断处理、DMA描述符这些全都得自己来工作量不是一个量级。下面这张表是我在方案预研时做的对比链路形态时间戳来源Linux驱动成熟度定制灵活性适合场景PS GEM RGMII直连PHYGEM硬件时间戳很高低常规单板千兆不挑PHYPS GEM PL SGMII转接 外部PHYGEM硬件时间戳很高中板级走线受限、选用SGMII PHY全PL AXI Ethernet Subsystem SGMIIIP内MAC硬件时间戳中等高多网口、需卸载到PL的定制方案1.2 SGMII带给PTP的特殊约束自协商与固定延迟SGMII不是简单的换了物理层它自带一套自协商机制用来在MAC侧和PHY侧之间协商10/100/1000M速率。这个自协商对普通网络传输没什么感知但对PTP有影响——链路协商、速率切换这些事件会造成短暂的链路中断如果主时钟在同步过程中恰好赶上游标切换offset会瞬间跳变。所以我在设计里会把PHY配置成强制千兆模式除非产品确实需要支持10/100M否则不要让SGMII自协商在城市级电口上频繁工作。另一个约束是延迟的确定性。PTP计算延时时默认路径是对称的也就是主到从和从到主的链路延迟相等。SGMII链路里的GTX收发器、PCS编解码都会带来固定延迟外部PHY芯片的SGMII侧和铜缆侧也会有收发延迟。这些延迟虽然固定但如果不做补偿会在最终精度里变成系统性偏差。好在GEM的1588硬件时间戳支持软件配置固定延迟补偿把PHY datasheet里给出的TX/RX路径延迟写进寄存器或者ptp4l配置里就能把这一部分扣掉。1.3 方案目标设定先定精度再定架构做PTP方案最容易犯的错是先搭硬件再谈精度。我的建议是反过来先明确产品需要什么级别的同步精度。如果是电力变电站采样同步或者测量设备触发同步通常要求亚微秒甚至百纳秒级那硬件时间戳是刚需任何软件时间戳方案都别考虑。如果只是网管系统做事件记录对齐微秒级就够那RGMII加软件时间戳也能凑合。我这套方案的目标定为主从双机同步偏差小于1微秒常态几百纳秒。这个目标直接决定了后面所有技术选型必须用GEM硬件时间戳、必须用两步模式Sync加Follow_Up、必须把系统时钟也一起驯服掉。定了目标之后整条链路的架构就很清晰了不会做一半发现某个环节撑不住精度要求。2. PTP时间戳机制与延时的账得一笔一笔算清楚2.1 同步报文流程与主从偏差计算公式IEEE 1588/PTP的核心思路不复杂主时钟和从时钟各自维护一个本地时间通过交换带时间戳的事件报文来算出两个时钟的偏差然后从时钟把自己的本地时间校准到主时钟。最常见的两步模式流程是这样的主时钟发出Sync报文在MAC层硬件发送瞬间记下发送时间t1从时钟在MAC层硬件接收瞬间记下接收时间t2紧接着主时钟发出Follow_Up报文里面携带t1的精确值之后从时钟发出Delay_Req记录发送时间t3主时钟收到后记录接收时间t4并通过Delay_Resp报文回传给从时钟。有了这四个时间戳主从偏差和链路延迟就能解出来。假设链路下行和上行延迟相等为delay从时钟相对主时钟的偏差为offset从时钟时间减主时钟时间那就能写出两个关系式t2 t1 offset delayt4 t3 - offset delay。两式相减再除以二就是offset ((t2 - t1) - (t4 - t3)) / 2两式相加再除以二就是delay ((t2 - t1) (t4 - t3)) / 2。这也是为什么PTP对时间戳采集位置这么敏感的原因。任何一个环节如果用的是软件时间戳比如内核协议栈拿到报文后才记时中间排队、中断、驱动处理的延迟轻易就是几十微秒甚至更大而且抖动毫无规律offset的计算结果自然没法看。所以1588落地的第一原则永远是时间戳越靠近物理层越好最好在MAC与物理层交界的地方打点。2.2 时间戳采集位置决定精度上限我把PTP时间戳的位置分成三档软件时间戳、MAC层硬件时间戳、PHY层硬件时间戳。软件时间戳精度在几十微秒量级受系统负载影响巨大只适合纯展示类功能。MAC层硬件时间戳是在以太网MAC的发送和接收通道上自动打点抖动通常在几十纳秒以内ZYNQ GEM和Xilinx PL里的Axi Ethernet Subsystem都支持。PHY层时间戳是把打点位置进一步推到PHY芯片的PMA侧由外部PHY的1588模块完成精度更高同时对PHY选型有要求不是所有PHY都带这个功能。在ZYNQ加SGMII这套结构里时间戳打点位置取决于MAC是谁。用PS GEM做MAC时打点位置在GEM内部这个位置虽然离物理线缆还有一段SGMII转换和PHY转发路径但那些都是固定延迟可以精确补偿所以最终精度可以做到亚微秒。用PL的Ethernet Subsystem做MAC时打点位置在IP核内部本质也是MAC层时间戳。真正要注意的是别把时间戳点放在PL里的PCS/PMA IP上——那个IP根本不产生时间戳它只做编解码和串并转换。2.3 OC、BC、TC三种时钟角色怎么选PTP网络里每个节点都有角色常见的是OCOrdinary Clock普通时钟、BCBoundary Clock边界时钟、TCTransparent Clock透明时钟。OC是最常见的主或从节点只在一个端口上参与同步比如一台从设备挂在主时钟下它就是OC从模式主时钟自己也是一个OC主模式。BC有多个端口每个端口都像OC一样参与同步但BC会把从某个上游主时钟学习到的时钟信息重生成后再往下游端口分发适合用于多网段级联场景。TC则不同它不参与主从协商而是计算PTP报文穿过自身节点的驻留时间然后把修正字段累加进去下游节点拿到报文时就能把中间设备造成的延迟算进去。简单来说OC适合端节点BC适合跨网段网关TC适合交换机这种透明转发设备。ZYNQ板卡在工程里最常扮演的是OC从时钟角色通过SGMII链路从上游交换机或主时钟获取时间。搞清楚这三种角色配置linuxptp的时候就分得清自己是该跑OC模式、开启边界时钟还是用TC对时延做修正。3. SGMII IP核模式抉择MAC模式还是PCS/PMA模式3.1 两种模式的本职区别在Vivado里建立SGMII链路时会碰到一个关键的配置选择把IP核配置成MAC模式还是PCS/PMA模式。这与时间戳谁打直接相关。Xilinx提供两种不同粒度的IP一种叫1G/2.5G Ethernet PCS/PMA or SGMII它只包含物理编码子层PCS和物理介质附加子层PMA串行侧是SGMII但local侧暴露的是GMII接口它不包含MAC层也就不产生PTP时间戳。另一种是Axi Ethernet 1G/2.5G Subsystem或者Ethernet Subsystem这类带完整MAC的IP它把MAC和PCS/PMA封装在一起local侧走AXI接口串行侧直接出SGMII。所以当看到与PHY芯片一起使用时应配置成MAC模式这句话它的准确含义是如果选择的是带MAC的以太网Subsystem IP必须确保IP工作在MAC模式让IP内部的MAC和PCS/PMA配合完成SGMII链路而不是只启用PCS/PMA功能后对外暴露GMII接口结果发现自己还得在PL里再塞一个MAC。这个模式选错后面所有的AXI DMA映射、PHC设备注册、时间戳读取都要推翻重来。3.2 与外部PHY芯片搭配时的Vivado配置流程我用的方案是PS GEM做MACPL只做SGMII转换所以在Vivado里例化的是1G/2.5G Ethernet PCS/PMA or SGMIIIP配置成SGMII接口模式local侧接到PS GEM的GMII接口上。这样GEM的1588硬件时间戳单元就直接覆盖整条MAC路径PL侧IP只负责把GMII并行的以太网数据转成SGMII串行再送到外部PHY芯片。具体Vivado里的关键配置按我的经验是这几项协议选择SGMII而不是1000BASE-X。二者都是1.25Gbps串行但SGMII有自协商机制是MAC与PHY之间的内联接口1000BASE-X多为光模块或背板场景。Line Rate设成1G如果后面还要兼容100M或10M需要确认外部PHY是否支持SGMII的10/100M降速模式。GT参考时钟要连到板上提供给GTX的差分时钟通常125MHz。这个时钟质量直接决定SGMII眼图和稳定性别随便用个内部PLL生成。如果IP提供1588相关选项比如通过AXI4-Lite接口暴露时间戳寄存器就打开这会给PL侧调试留一条路。外部PHY芯片比如88E1512、DP83867这类带SGMII接口的千兆PHY的SGMII口接到FPGA的GTX差分对上PHY的配置引脚要根据板卡设计设好。调试初期建议先用PHY的strapping配置强制一个固定模式不要一上来就依赖寄存器读写实现自动协商减少变量。3.3 1588在IP内部如何落地如果是全PL的Ethernet Subsystem方案IP内部会在MAC的发送和接收数据路径上插入时间戳模块。Sync报文在发送时MAC会采样本地时间写入时间戳寄存器同时打一个标志用于和Follow_Up或者单步模式的Sync字段关联。接收时同理MAC识别出PTP事件报文类型自动记录接收时间。这部分的落地要点是中断和寄存器读取。IP核通过AXI4-Lite接口暴露时间戳寄存器当发送或接收事件发生时IP会拉高中断信号软件在中断服务里读取对应的TX/RX时间戳。这个过程中中断延迟不能太夸张否则虽然硬件打点时间准但软件取出的时间戳和报文顺序如果错位照样会出问题。我习惯在IP配置里把TX和RX事件分别映射到两个中断ID软件侧用独立线程处理避免两个事件共用一个中断源导致互锁。4. PetaLinux从构建到启动boot.bin、boot.scr、image.ub的完整动作4.1 用PetaLinux 2025.1生成三件套ZYNQ这套方案最终跑的是PetaLinux 2025.1。先说明一点PetaLinux的版本必须和Vivado配套2025.1的硬件工程导出XSA后只能用配套版本的PetaLinux导入版本错配会出现设备树生成异常这类怪问题。工程构建流程大概是这样的# 1. 在Vivado里完成硬件设计导出XSA # 导出时勾选包含bitstream # 2. 创建PetaLinux工程注意模板选zynq petalinux-create -t project -n eth1588 --template zynq # 3. 导入硬件描述 cd eth1588 petalinux-config --get-hw-description/path/to/zynq_sgmii_1588.xsa # 4. 配置rootfs加入linuxptp、ethtool等工具 petalinux-config -c rootfs # 5. 构建 petalinux-build # 6. 生成BOOT.BIN和镜像 petalinux-package --boot --format BIN --fsbl --fpga --u-boot第4步rootfs配置里我需要额外强调一点linuxptp这个包在PetaLinux的rootfs菜单里默认是不勾选的必须在apps或者network分类下找到linuxptp并勾上否则后面用ptp4l还得自己交叉编译。ethtool也要勾因为调试时间戳能力时靠它查看网卡能力。构建完成后工程里的BOOT.BIN和image.ub分别在images/linux目录下。BOOT.BIN是FSBL加bitstream加U-Boot的打包image.ub是内核、设备树和rootfs的打包。boot.scr不会自动生成需要自己写这一步很容易被忽略。4.2 SD卡分区和启动脚本写法SD卡启动是ZYNQ最省事的方案。常规做法是分两个分区第一个分区用FAT32放BOOT.BIN、boot.scr、image.ub第二个分区用ext4放rootfs。如果rootfs是initramfs格式并已经编进image.ub那其实一个FAT分区就够了但为了方便文件操作我还是习惯分两个区。分区命令不多说fdisk或者gparted都可以注意第一个分区建议不小于500MBFAT32格式化后把三个文件放进去就行。rootfs分区可以用petalinux在images/linux/rootfs.tar.gz里解压或者直接把SD卡的第二个分区设成rootfs位置并在启动参数里指定。boot.scr的写法是重点。U-Boot启动时会读SD卡FAT分区里的boot.scr然后执行里面的命令。我用的是这段echo load mmc 0:1 0x2000000 image.ub echo bootm 0x2000000把它保存成boot.cmd然后在主机上用u-boot-tools里的mkimage工具转换mkimage -A arm -T script -C none -n boot script -d boot.cmd boot.scr这个boot.scr文件要和BOOT.BIN放在同一个FAT分区根目录下。U-Boot起来后BOOT.BIN里的U-Boot会自动挂载第一分区执行boot.scr加载image.ub然后启动内核。整个过程只要串口能看到U-Boot提示符后面基本就顺了。4.3 把ptp4l和phc2sys跑起来PetaLinux起来以后第一步先确认网口识别和PHC设备。用ethtool -T eth0查看时间戳能力如果输出里包含了hardware-transmit和hardware-receive说明GEM的1588硬件时间戳已经被驱动识别这是整条链路成功的关键标志。然后用linuxptp跑主从同步。从设备上执行ptp4l -i eth0 -m -s -2 -H这里-Sm表示打印日志到标准输出-s表示slave模式-2表示IEEE 802.3以太网报文-H表示 hardware timestamp。ptp4l跑起来后日志里会周期性打印offset、delay、drift这些值。如果是在主时钟侧去掉-s参数gPTP或普通PTP模式都行。ptp4l同步的是网卡上的PHC硬件时钟也就是/dev/ptp0但系统时间不会自动跟着走。要让整个Linux系统时间也同步上去还需要跑phc2sysphc2sys -s eth0 -c CLOCK_REALTIME -m这条命令把PHC时钟作为源去校准系统实时时钟。如果产品里还挂了PPS信号输出可以用phc2sys的PPS选项或者单独用ts2phc做PPS对齐。实测下来ptp4l和phc2sys两个进程配合好系统时间和PHC时间都能稳定在同步状态。4.4 绕开FSBL烧写报错用SD卡启动跑通之后很多项目会想把镜像固化到QSPI Flash或者NAND里省掉SD卡。这一步里最常碰到的报错就是Valid FSBL file is required for flash operation。这个报错并不是说板卡坏了而是用Vitis或XSCT里的program_flash工具烧写时工具需要一个FSBL来初始化DDR、时钟和外设。如果没有指定FSBLprogram_flash根本没法执行Flash操作。解决办法也很直接在program_flash命令里显式传入FSBLprogram_flash -f BOOT.BIN -offset 0x0 -flash_type qspi-x4-single -fsbl /path/to/zynq_fsbl.elf -verify也可以更简单直接在U-Boot环境下从SD卡加载BOOT.BIN后用sf命令烧写QSPI这样完全绕开XSCT反而更省事。烧写时注意Flash型号要在U-Boot或FSBL的设备树里声明好ZYNQ对部分NAND Flash型号支持有限选型前先查一下支持的型号列表别等画完板子才发现Flash不启动。5. 精度实测与排错记录三个坑每一个都是经验5.1 同步精度验收方法整套系统搭建好之后验收精度不能只盯着ptp4l日志里的offset看。ptp4l打印的offset是软件算出来的数字虽然可信但更硬核的验收方式是对比主从两侧的PPS脉冲。正常情况下板卡会预留一个PPS输出引脚从设备同步稳定后PPS应该和主设备的PPS边沿对齐。用示波器同时测两个PPS看边沿时间差这个数值就是真正端到端的同步精度。我做实测的时候主从两台ZYNQ通过千兆交换机或者网线直连从设备跑ptp4l和phc2sys稳定运行20分钟以后观察PPS偏差。结果在我预期之内网线直连抖动最小基本稳定在300-500纳秒中间经过普通千兆交换机后抖动会放大到1-2微秒这主要是因为交换机本身的转发延迟和排队跟PTP协议的透明时钟驻留时间修正有关。如果对精度有更高要求中间交换机必须支持PTP TC或者BC功能普通交换机会把时间戳撕碎。5.2 坑一PHY的SGMII自协商导致链路反复复位第一次上板调试时遇到的是链路起来了但ping不通偶尔通几秒又断的现象。查串口日志发现PHY的链路状态在up和down之间反复跳eth0的link标志一直在闪。刚开始以为是GTX参考时钟的问题用示波器量了125MHz时钟信号很干净排除后来又怀疑是SGMII IP的复位时序给了足够的复位时长也没改善。最后把PHY的寄存器读出来才发现问题出在SGMII自协商上。外部PHY默认开启了SGMII的自协商而PL侧的PCS/PMA也在做自协商两边协商的速率状态机没有对齐导致链路建立后又被重新协商打断。解决方法是把PHY配置成SGMII强制千兆模式关闭自协商或者让两端都用SGMII的标准自协商流程但确保PHY的配置引脚正确。从那以后我就记住一条原则在FPGA加PHY的场景里能强制协商结果就尽量强制别把链路的rate协商交给PHY的默认配置。5.3 坑二PTP时钟源与本地晶振漂移第二个坑是ptp4l跑起来以后offset在-500纳秒到1微秒之间来回跳但PPS对不齐。仔细看ptp4l日志offset的平均值其实接近0但方差很大这通常不是协议问题而是本地时钟源稳定性不足。GEM的1588硬件时间戳时钟源来自PS侧的时钟默认精度取决于板载晶振如果晶振的温漂和频率误差偏大PHC的节拍就不准导致同步环路一直在大范围纠偏。解决思路是先看板卡上的晶振指标频率稳定度至少要达到TXCCO或者更高一点的水平实在不行就用外部高稳时钟源或者10MHz输入来驱动PHC。另一个改善手段是调整ptp4l的参数比如把pi的响应系数降下来防止本地时钟抖动造成过度调节。经过这个坑我认识到PTP方案选硬件时钟源比选PHY芯片还重要。5.4 坑三FLASH操作需要有效FSBL前面提到烧写镜像时的FSBL报错我在新板的调试中确实踩到了。当时想从QSPI启动以摆脱SD卡直接用Vitis的program_flash烧BOOT.BIN结果工具报Valid FSBL file is required for flash operation一开始以为是BOOT.BIN没生成好重新跑了petalinux-package之后还是同样的问题。后来看了程序_flash的帮助文档才明白这个工具在执行flash操作前要用FSBL先初始化外部存储器接口和时钟否则它连DDR都无法访问。我当时传的FSBL路径写错了指向了一个空文件。改正确后执行program_flash -f images/linux/BOOT.BIN -offset 0x0 -flash_type qspi-x4-single -fsbl images/linux/zynq_fsbl.elf -verify烧写顺利完成。这个坑也告诉我出现工具报错先分清楚是配置问题还是路径问题很多时候一排错链路上的每一步都检查一遍花不了太多时间。6. 最后再分享几个细节如果重新做一遍这个方案我会在第一天就把时间戳打点位置、链路延迟补偿、以及PetaLinux镜像构建这三件事单独拎出来先各做一个最小验证再合并到一张板上。三条线的问题如果混在一起排查很容易被表面现象带偏。另外调试PTP时串口日志和上位机显示工具不能随便凑合我最后还是写了一个简单的Qt串口监视程序用来实时显示从设备的ptp4l输出和PPS偏差没有这个工具光靠示波器盯两个通道的效率太低了。关于Qt串口库的交叉编译注意在PetaLinux SDK环境下把QtSerialPort模块的include路径和库路径配好其他的和普通Linux程序没区别。这套方案里用的PCS/PMA转SGMII加PS GEM的架构对大多数ZYNQ SGMII加PTP项目来说是最稳的起点。等这条路线跑熟了后面再上全PL的Ethernet Subsystem即使要自己适配驱动也已经有前面调试链路的基础心里的底气会足很多。
返回列表