☰
RK3566以太网RGMII延迟线调优实战:从丢包到千兆稳定
2026/9/28 1:40:45 网站建设 项目流程

1. 项目缘起:一块RK3566板子引发的网络稳定性排查

RK3566这颗芯片在嵌入式圈子里火了好几年,四核A55的架构、Mali-G52的GPU,加上双千兆以太网的配置,让它成了不少AIoT设备和桌面安卓电脑方案的首选。我手头这个项目用的是RK3566搭配Android 12,板子跑起来之后其他功能都正常,唯独以太网这块儿时不时抽风——插上网线能识别,DHCP也能拿到地址,但跑iperf3压测的时候丢包率忽高忽低,有时候ping网关的延迟会突然从零点几毫秒跳到几十毫秒,严重的时候直接断流几秒钟再恢复。

这种问题最让人头疼,因为它不是完全不工作,而是“时好时坏”。你盯着它测十分钟可能一切正常,转身去泡杯茶回来就发现SSH已经断开了。一开始我怀疑是PHY芯片的问题,换了几个不同批次的PHY模块,现象依旧。后来用示波器抓RGMII总线的波形,才发现问题的根源出在时序上——RGMII接口的时钟和数据之间的延迟关系没有调好,导致接收端在采样时偶尔采到错误的数据。

RGMII这个接口说起来简单,它就是千兆以太网MAC和PHY之间的标准接口,用4位数据线在时钟的上下沿同时传输,实现千兆速率。但正因为它是双沿采样,对时序的要求就特别苛刻。RK3566的GMAC控制器内部有延迟线(Delay Line)的配置选项,可以调整时钟相对于数据的延迟量,这个参数如果配得不对,就会出现我遇到的那种“能通但不稳”的情况。这篇文章就把我在RK3566上折腾RGMII延迟线的完整过程整理出来,从原理到配置到实测,给遇到类似问题的朋友一个可参考的路径。

2. RGMII接口时序的核心原理拆解

2.1 为什么RGMII的时序这么难搞

要理解延迟线配置,得先搞清楚RGMII的时序到底是怎么回事。RGMII全称Reduced Gigabit Media Independent Interface,是千兆以太网MAC和PHY之间的接口标准。它把GMII的8位数据线缩减到4位,为了保持千兆的吞吐量,采用了DDR(双倍数据速率)的方式,在时钟的上升沿和下降沿都传输数据。具体来说,TXC(发送时钟)的上升沿传输TXD[3:0]的低四位,下降沿传输高四位,接收方向RXC和RXD也是同样的机制。

这种双沿采样的设计对时序窗口的要求非常严格。在千兆速率下,时钟周期只有8纳秒,上升沿和下降沿之间的间隔是4纳秒。接收端需要在每个沿的中间位置稳定地采到数据,这就要求数据和时钟之间的偏斜(skew)控制在一个很小的范围内。RGMII标准里定义了一个2纳秒左右的时序窗口,超过这个范围就可能采错。

实际工程中,MAC和PHY之间的PCB走线长度差异、芯片内部的缓冲延迟、PHY芯片的制造工艺偏差,都会影响最终的时序关系。所以RGMII接口通常需要额外的延迟补偿机制,要么在PHY侧加内部延迟,要么在MAC侧通过延迟线来调整。RK3566的GMAC控制器就提供了后者——一组可配置的延迟线参数,让开发者根据实际硬件情况来微调时序。

2.2 RK3566的延迟线机制是怎么工作的

RK3566的GMAC控制器内部有两组延迟线,分别对应发送方向和接收方向。每组延迟线可以独立配置,调整时钟信号相对于数据信号的延迟量。这个延迟量的单位是“抽头”(tap),每个tap对应一个固定的时间延迟,具体数值跟芯片的工艺和时钟频率有关。

在千兆模式下,RGMII的时钟是125MHz,周期8纳秒。延迟线的可调范围通常覆盖几个纳秒,足够补偿PCB走线和芯片内部延迟带来的偏差。配置的方式是通过DTS(设备树)里的属性来设置,RK3566的GMAC节点支持tx_delay和rx_delay两个参数,分别控制发送和接收方向的延迟抽头数。

这里有个关键点:发送方向和接收方向的延迟需求往往是不同的。发送方向是RK3566输出时钟和数据给PHY,PHY负责采样;接收方向是PHY输出时钟和数据给RK3566,RK3566负责采样。两个方向的信号路径不同,延迟特性也不同,所以需要分别调整。很多人在调试时只关注一个方向,结果就是发送正常但接收丢包,或者反过来。

2.3 延迟配置不当会引发哪些典型症状

延迟线配错了,表现出来的症状很有规律,我整理了一个对照表,方便大家快速定位问题方向:

症状表现可能原因排查方向
链路能UP但ping丢包严重接收方向采样点偏移调整rx_delay
发送大包时CRC错误多发送方向时序偏差调整tx_delay
低速正常千兆异常延迟补偿不足增大延迟抽头
偶尔断流几秒后恢复采样点处于临界状态精细调整延迟值
完全无法建立链路延迟偏差过大或PHY配置错误检查PHY模式和延迟范围

这个表是我在实际调试中总结出来的,不一定覆盖所有情况,但大部分RGMII时序问题都能对上号。比如我遇到的那个“能通但不稳”的情况,就是典型的接收方向采样点处于临界状态,数据有时候能采对有时候采错,表现出来就是随机丢包。

3. 从DTS到寄存器:延迟线配置的完整实操

3.1 设备树里的关键配置项

RK3566的GMAC节点在DTS里的配置是延迟线调整的入口。以Android 12的SDK为例,GMAC节点通常在arch/arm64/boot/dts/rockchip/rk3566.dtsi或者具体的板级DTS文件里。核心配置项包括tx_delay和rx_delay,单位是抽头数,取值范围一般是0到0x7f(127),具体上限取决于芯片的延迟线设计。

一个典型的配置片段长这样:

&gmac1 { phy-mode = "rgmii"; clock_in_out = "output"; tx_delay = <0x2a>; rx_delay = <0x1e>; status = "okay"; };

这里的phy-mode要跟实际硬件匹配,RGMII模式下PHY和MAC之间没有额外的延迟,所以需要MAC侧来补偿。clock_in_out设置成output表示RK3566输出时钟给PHY,这是最常见的配置。tx_delay和rx_delay就是我们要调的延迟抽头数。

注意:不同版本的SDK里属性名可能略有差异,有的用tx_delay和rx_delay,有的用tx-delay和rx-delay,还有的通过assigned-clock-rates来间接影响。改之前先确认SDK的文档和现有配置。

3.2 延迟抽头数的计算逻辑

延迟抽头数不是随便填的,它跟时钟频率和芯片的延迟线步进有关。RK3566的延迟线步进在千兆模式下大约是20皮秒到30皮秒每个抽头,具体数值需要查芯片手册。假设步进是25皮秒,那么:

  • 需要补偿1纳秒的延迟,就需要大约40个抽头
  • 需要补偿2纳秒的延迟,就需要大约80个抽头

但实际调试中不会这么精确计算,因为PCB走线延迟、PHY内部延迟这些参数很难精确获取。更实用的方法是先设一个中间值,比如tx_delay和rx_delay都设成0x20(32),然后通过实测来微调。

我一般会准备一个测试脚本,在系统启动后动态修改延迟值并重新加载驱动,然后跑iperf3看丢包率。这样可以在不重启系统的情况下快速遍历多个延迟值,找到最优解。具体做法是:

# 通过debugfs动态调整延迟(如果驱动支持) echo 0x20 > /sys/kernel/debug/gmac/delay_tx echo 0x20 > /sys/kernel/debug/gmac/delay_rx # 重新加载驱动 ifconfig eth0 down ifconfig eth0 up # 跑测试 iperf3 -c 192.168.1.100 -t 30 -P 4

不是所有驱动都支持debugfs动态调整,如果不支持,就只能改DTS重新编译内核。这种情况下建议一次改多个值,编译一版内核测一轮,效率会高一些。

3.3 实测环境搭建与测试方法

测试环境很简单:一台RK3566板子作为被测设备,一台PC作为对端,中间用一根质量可靠的千兆网线直连。PC端跑iperf3服务端,板子端跑客户端。测试指标主要看三个:吞吐量、丢包率、延迟抖动。

# PC端启动服务端 iperf3 -s # 板子端跑客户端,持续60秒,4个并发流 iperf3 -c 192.168.1.100 -t 60 -P 4 -i 5 # 同时跑ping测试看延迟抖动 ping -c 1000 -i 0.01 192.168.1.100

我习惯在调延迟的时候同时跑iperf3和ping,因为iperf3反映的是大流量下的稳定性,ping反映的是小包延迟和抖动。两个指标都好了,才算真正调好。有时候iperf3跑出来吞吐量很高,但ping的延迟抖动很大,这种配置在跑实时性要求高的应用时还是会出问题。

测试的时候还要注意温度的影响。RK3566在满载跑网络的时候芯片温度会上升,温度变化会影响延迟线的实际延迟量。我遇到过常温下调好的参数,跑半小时之后丢包率又上来了,就是因为温度漂移。所以测试至少要跑30分钟以上,最好用风扇模拟实际工作环境。

4. 延迟线调优的实战记录与避坑经验

4.1 第一轮调试:从完全不通到能通

刚拿到板子的时候,DTS里用的是SDK默认的延迟值,tx_delay和rx_delay都是0。插上网线后链路能UP,但ping不通任何地址。用示波器抓RXC和RXD的波形,发现数据和时钟几乎完全对齐,接收端在时钟沿采数据的时候,数据正好在跳变,采到的全是错的数据。

第一轮调整把rx_delay设成0x20,tx_delay保持0。重新编译内核烧录后,ping通了,但丢包率在5%到10%之间波动。这说明接收方向的延迟方向对了,但值还不够精确。继续增大rx_delay到0x30,丢包率降到1%左右,但还是不够稳定。

这里有个经验:延迟值不是越大越好。当延迟超过某个点后,采样点会从数据窗口的一侧移到另一侧,丢包率会先降后升。所以调的时候要找到那个“谷底”,而不是一味增大。

4.2 第二轮调试:精细扫描找到最优值

为了找到最优的延迟值,我写了一个简单的扫描脚本,把rx_delay从0x10到0x50每隔4个抽头测一轮,每轮跑30秒iperf3,记录丢包率和吞吐量。结果发现丢包率在0x28到0x34之间最低,低于0x24或高于0x38都会明显恶化。

最终选了0x2e作为rx_delay的值,这个值在多次测试中表现最稳定。tx_delay那边因为发送方向的时序余量比较大,设成0x20就足够了。调完之后跑了一个小时的iperf3,丢包率稳定在0.01%以下,ping的延迟抖动也在正常范围内。

测试轮次rx_delay值丢包率吞吐量备注
10x108.2%620Mbps采样点偏移大
20x1c3.5%780Mbps有所改善
30x280.3%920Mbps接近最优
40x2e0.01%940Mbps最优值
50x340.5%910Mbps开始恶化
60x404.1%750Mbps明显恶化

这个表是我实际测试的记录,可以看到丢包率随延迟值的变化是一个U型曲线。最优值在曲线底部,两边都会恶化。实际调试的时候不用测这么密,大概每隔8个抽头测一轮,找到大致范围后再在附近精细扫描就行。

4.3 踩过的坑:那些文档里不会写的问题

第一个坑是PHY芯片的延迟模式。有些PHY芯片内部自带延迟,可以通过寄存器配置成“RGMII with internal delay”模式。如果PHY已经开了内部延迟,MAC侧再加大延迟,两者叠加就会过头。我一开始不知道PHY有这个选项,在MAC侧拼命加延迟,结果怎么调都不对。后来查PHY的手册才发现要先把PHY的内部延迟关掉,让MAC侧来统一补偿。

第二个坑是不同批次的PHY芯片延迟特性有差异。小批量试产的时候调好的参数,换了一批PHY之后又不行了。这种情况要么每批都重新调,要么选一个兼容性最好的中间值,牺牲一点性能换稳定性。我最后的做法是在DTS里把延迟值做成可配置的,不同批次的板子用不同的DTS配置,生产的时候根据PHY批次来烧录对应的固件。

第三个坑是电源噪声对延迟线的影响。RK3566的GMAC供电如果纹波比较大,延迟线的实际延迟量会跟着波动,表现出来就是网络性能时好时坏。我在电源引脚上加了一个22微法的电容之后,稳定性明显改善。这个不是RGMII本身的问题,但会影响延迟线的调试效果,所以一并提一下。

提示:调试RGMII延迟之前,先用示波器确认PHY的供电纹波在合理范围内。电源不干净的话,怎么调延迟都是白费功夫。

4.4 常见问题速查与排查思路

调试过程中遇到的问题五花八门,我整理了一个速查表,按现象分类,方便快速定位:

现象排查步骤可能原因
链路无法UP1.检查PHY供电和复位 2.确认phy-mode配置 3.检查时钟输出PHY未正常工作或模式配置错误
能UP但ping不通1.抓RXC/RXD波形 2.检查rx_delay 3.确认PHY延迟模式接收方向采样点严重偏移
小包正常大包丢包1.检查tx_delay 2.抓TXC/TXD波形 3.检查PCB走线等长发送方向时序余量不足
跑一段时间后断流1.监测芯片温度 2.检查电源纹波 3.复测延迟值温漂或电源噪声导致采样点偏移
换PHY后性能下降1.对比PHY手册延迟参数 2.重新扫描延迟值PHY批次差异

这个表里的排查步骤是我实际用过的,按顺序走一遍基本能覆盖大部分情况。最关键的还是抓波形,示波器能看到眼图的话,采样点的位置一目了然,比盲调延迟值高效得多。

5. 延迟线优化的进阶思路与扩展场景

5.1 动态补偿的可能性

固定延迟值在常温下工作没问题,但如果产品要在宽温范围内使用,比如工业级应用要求零下40度到零上85度,温度漂移就会成为问题。RK3566的延迟线本身没有温度补偿机制,但可以通过软件方式做动态调整。

思路是在系统里跑一个后台任务,定期检测网络质量(比如统计CRC错误计数),如果发现错误率上升,就微调延迟值。这个方案实现起来不复杂,但需要驱动层暴露延迟值的读写接口。我在一个工业网关项目里试过这个方案,效果还不错,能把宽温范围内的丢包率控制在可接受水平。

具体实现是在驱动里加一个sysfs节点,应用层通过读写这个节点来调整延迟。检测逻辑用ethtool的统计信息,看rx_crc_errors和rx_frame_errors的变化趋势。如果连续几个采样周期错误率都在上升,就按预设的步长调整延迟值,然后观察效果。这个方案的关键是调整步长要小,避免震荡。

5.2 多网口场景下的独立配置

RK3566有两个GMAC控制器,可以支持双千兆网口。两个网口的延迟配置是独立的,因为它们的PCB走线和PHY芯片可能不同。在DTS里分别配置gmac0和gmac1节点的延迟值就行。

但有个细节要注意:两个网口同时跑满的时候,芯片内部的电源噪声和温度都会上升,可能影响延迟线的实际表现。我在一个双网口设备上遇到过单网口跑没问题、双网口同时跑就丢包的情况。后来把两个网口的延迟值都稍微调偏了一点,让采样点离临界位置更远,牺牲一点时序余量换稳定性,问题就解决了。

5.3 与其他RK3566网络相关配置的配合

RGMII延迟线只是RK3566网络配置的一部分,实际项目中还要跟其他配置配合。比如clock_in_out的设置会影响时钟方向,如果设错了,延迟线怎么调都没用。还有PHY的驱动配置,有些PHY需要额外的寄存器初始化序列,这些在DTS的PHY节点里配置。

另外,如果项目里用了RK3566的AIoT DTS配置,网络部分的节点可能跟标准配置有差异,改延迟值之前要先确认节点的完整结构。我见过有人直接复制标准DTS的GMAC节点到AIoT配置里,结果因为时钟配置不同导致网络完全不工作。这种问题不是延迟线能解决的,得从整体配置入手排查。

5.4 实测数据与性能对比

最后放一组我调优前后的对比数据,给大家一个直观的参考:

指标调优前调优后
iperf3吞吐量(TCP)620Mbps940Mbps
iperf3丢包率8.2%0.01%
ping平均延迟0.8ms0.3ms
ping延迟抖动(标准差)12ms0.5ms
连续跑1小时断流次数5次0次

调优后的数据已经能满足大部分应用场景的需求。千兆网络跑出940Mbps的吞吐量,说明延迟线配置已经比较理想了,剩下的6%损耗主要是协议开销和测试环境的限制。

整个调试过程花了大概三天时间,其中大部分时间用在反复编译内核和测试上。如果驱动支持动态调整延迟值,时间可以缩短到半天以内。所以如果你正在做RK3566的网络调试,建议先确认驱动是否支持debugfs动态调整,能省很多事。

我在实际项目里还遇到过一个情况:板子跑Android系统,网络调试的时候发现Android的电源管理会在息屏后降低GMAC的时钟频率,导致延迟线的实际延迟量发生变化,息屏后网络就断了。这个问题的解法是在DTS里把GMAC的时钟配置成always-on,或者在电源管理策略里排除GMAC节点。这类问题跟延迟线本身无关,但会影响最终的调试结果,所以一并记下来。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询