☰
RK3588更换千兆PHY调试实战:从RGMII到设备树的完整排坑指南
2026/10/5 6:16:22 网站建设 项目流程

前段时间调一块 RK3588 板子的网络,整整折腾了一个星期才收干净尾巴。板子原来用的是 RTL8211F 这颗瑞昱的千兆 PHY,在 RK3588 方案里非常常见,评估板、核心板、各种量产板都在用。这次因为供货和 BOM 成本的原因,我把默认的 RTL8211F PHY 换成了另一款兼容的千兆 PHY,型号我就不点名了,下面的记录里就叫它 PHY_X。换之前我想得很简单:同样是 RGMII 接口、同样挂 MDIO 总线、同样工作在千兆模式,设备树里把 PHY 型号相关的字段改一改,应该很快能跑通。结果从硬件检查、设备树配置到内核识别,再到最终的应用层 UDP 通信验证,每一层都给我“惊喜”。

这篇文章就是这次 RK3588 网络调试的现场笔记,我会把换 PHY 过程中踩到的坑、每一步排查的思路、以及最后沉淀下来的调试套路,全部整理清楚。内容覆盖面比较广,从 PHY 外围电路到设备树 phy-mode,再到内核 phylib 驱动和 UDP 抓包验证都会涉及,适合正在 RK3588 或其他平台做网络调试、准备替换 PHY 的嵌入式软硬件工程师参考。

1. 换PHY别急着动软件,硬件差异才是第一大坑

1.1 pin-to-pin兼容不等于外围电路一致

很多替换 PHY 的坑,在动手改设备树之前就已经埋下了。RTL8211F 之所以在 RK3588 方案里这么流行,除了稳定性好之外,还有配套的参考设计非常成熟,网上随手就能找到原理图。当你把这个位置换成一款新 PHY 时,最危险的直觉就是“既然 pin-to-pin 兼容,那我原理图不用动,直接换芯片就行”。实际上,就算引脚定义完全一致,PHY 芯片内部的默认状态、外置电阻的 strap 逻辑、上电复位的要求都可能不一样。

我这次就吃了一个小亏:RTL8211F 默认的 PHY 地址是 0x01,这是由它的 PHYAD0/PHYAD1 引脚外围电路决定的。换上去的 PHY_X 默认地址也是 0x01,表面看没问题,但它的 strap 电阻接法跟 RTL8211F 参考设计不完全一样——它对 PHYAD0 引脚的上拉/下拉电平判定阈值更敏感,沿用原板子的 4.7kΩ 电阻值时地址能识别出来,但在高低温边缘会出现 MDIO 地址读取不稳定的情况。这种问题最坑人,因为它不是完全不通,而是“时好时坏”。

所以换 PHY 的第一步,不是去翻设备树,而是先把新 PHY 的手册翻开,逐项核对这几类硬件配置:

  • MDIO 地址 strap:PHYAD0/PHYAD1/PHYAD2 等引脚的上下拉方式,决定了 PHY 在 MDIO 总线上的地址,设备树里的 reg 必须和它一致。
  • 复位引脚极性:绝大多数 PHY 是低电平复位,但也有少数芯片对复位脉冲宽度有额外要求。
  • 时钟输入方式:PHY 是使用外部 25MHz 晶振,还是由 MAC 侧直接输入参考时钟,或者由 PHY 自己输出时钟给 MAC。
  • 延时配置方式:RGMII 的 TX/RX delay 是靠外部电阻配置,还是靠 PHY 内部寄存器配置,默认值是什么。
  • 电源供电要求:核心电压、IO 电压是 2.5V 还是 3.3V,内部 LDO 是否使能。

建议把这两颗 PHY 的数据手册的“Strapping Options”“Recommended Circuit”“Delay Configuration”三部分放在一起对照。这一项功课做好,后面能少走一大半弯路。

1.2 时钟、复位、延时这些“看不见”的参数

RTL8211F 和新 PHY 之间,真正容易出问题的不是电源和地,而是三个“看不见”的参数:参考时钟、复位时序、RGMII 延时。

先说时钟。RGMII 接口在千兆模式下,TX 时钟一般是 125MHz,由 MAC 侧给到 PHY(也就是 GTX_CLK);RX 时钟由 PHY 恢复出来,给回 MAC。但很多 PHY 芯片内部还需要一个参考时钟源,常见的是外接 25MHz 晶振。RTL8211F 的参考设计里,晶振的负载电容取值、起振电路参数都是经过验证的;换一颗 PHY_X 后,如果它的晶振驱动能力、反馈电阻推荐值不一样,就会出现一个很隐蔽的现象:PHY 能上电、能扫描到 MDIO 寄存器,但是网络协商不稳定,插上网线时偶尔能 link 上千兆,一会儿又掉到百兆。用示波器看晶振引脚,波形幅度可能只有正常值的一半。

复位时序也是老坑。有些板子的 PHY 复位引脚直接连到 SoC 的 GPIO,软件在设备树里配了 reset-gpios,但是 reset-assert-us 和 reset-deassert-us 两个参数是从旧项目照抄过来的。RTL8211F 的上电复位时间可能在 10ms 以内就能完成初始化,而 PHY_X 手册要求复位释放后至少等待 50ms 才能开始 MDIO 通信。如果照旧参数只等了 10ms,内核 phylib 在 probe 阶段访问 MDIO 时,PHY 内部还没准备好,就会读到全 F 的 PHY ID,导致驱动加载失败,网口直接不认。这时候表现出来的是“同样的内核、同样的设备树,换了 PHY 后 eth0 就消失了”,非常容易让人怀疑是器件质量问题或者焊接问题。

延时这个更不用说。RGMII 接口为了实现简单布线,标准里规定了要用延迟来补偿数据和时钟的偏斜。RTL8211F 的参考设计里往往会在 PCB 上预留延时电阻的位置,或者在设备树里使用 rgmii-id 让 PHY 内部打开 delay。新 PHY 的 delay 默认策略很可能不一样,这直接导致后面设备树里 phy-mode 的配置不能照搬。我的建议是:在动手写设备树之前,先用示波器量一下 MAC 侧 RXC 和 RX_CTL 之间的相位关系,再回头决定用哪种 delay 组合,而不是一个个试。

2. 设备树改不对,网口就是“点不亮”

2.1 MDIO地址和phy-handle的匹配

RK3588 的设备树里,以太网控制器一般长这样(以 GMAC1 为例):

&gmac1 { status = "okay"; phy-mode = "rgmii-id"; phy-handle = <&phy0>; pinctrl-names = "default"; pinctrl-0 = <&gmac1_miim &gmac1_tx_bus2 &gmac1_rx_bus2 &gmac1_rgmii_clk &gmac1_rgmii_bus>; mdio { compatible = "snps,dwmac-mdio"; #address-cells = <1>; #size-cells = <0>; phy0: ethernet-phy@1 { reg = <1>; reset-gpios = <&gpio4 RK_PB7 GPIO_ACTIVE_LOW>; reset-assert-us = <10000>; reset-deassert-us = <50000>; }; }; };

这段配置里,mdio 子节点下的 ethernet-phy@1 中的 reg = <1>,就是 PHY 在 MDIO 总线上的地址。RTL8211F 默认是 1,所以原来的设备树里写的是 1。PHY_X 如果出厂默认 strap 是 0,或者板子为了避开地址冲突改成了 3,那这个 reg 必须跟着改,否则内核 phylib 去地址 1 读 PHY ID,读回来全是 0xFF,就会报 PHY 不存在。

还有一点很容易忽略:如果 MDIO 总线上挂了不止一颗 PHY,或者有一颗备用的 PHY、交换芯片等器件,它们可能占据了别的 MDIO 地址。新 PHY 的 strap 地址如果不小心和别的器件冲突,也会导致 probe 失败。判断方法很简单,Linux 启动日志里搜索 eth0 或者 mdio 相关字段,看有没有类似“Micrel KSZ9031”或“Realtek RTL8211F”的 PHY 识别记录。如果没有,或者识别到的是一个奇怪的 ID,优先检查 PHY 地址和 strapping。

另外,我调试时习惯在启动后看这几个路径:

ls /sys/bus/mdio_bus/devices/ cat /sys/class/net/eth0/phy_address ethtool eth0

如果 phy_address 读出来是 0x1f 或者大于 31,说明 MDIO 读写异常,多半是地址问题或 PHY 未复位。

2.2 phy-mode:四种RGMII模式怎么选

RGMII 有四种常见的 device tree 配置:rgmii、rgmii-id、rgmii-txid、rgmii-rxid。它们的区别在于 TX 和 RX 方向的内延时由谁提供。

  • rgmii:不加任何内部 delay,数据线和时钟之间的偏移调整完全靠 PCB 走线长度或外部电阻实现。
  • rgmii-id:同时打开 RX 和 TX 方向内部 delay。
  • rgmii-txid:只打开 TX 方向内部 delay。
  • rgmii-rxid:只打开 RX 方向内部 delay。

RTL8211F 在老项目中常用 rgmii-id。换到 PHY_X 后,如果它的默认 delay 策略不一样,这行配置就可能出问题。最典型的表现是:link 能协商上,速率显示 1000Mbps,但 ping 不通或吞吐很低。这是因为时钟采样沿和数据沿没有对齐,MAC 收到的数据是“歪”的。

我这次踩坑的经历很有代表性:刚换上 PHY_X 时,我先用 rgmii-id,结果 link 正常,ping 网关延迟忽高忽低,从 1ms 跳到几百毫秒,iperf3 测吞吐只有几十 Mbps。后来查手册发现 PHY_X 在 TX 方向默认已经打开了内部 delay,设备树里再用 rgmii-id 就会把 TX 方向的延时重复叠加,等于延迟过头了。把 phy-mode 改成 rgmii-rxid 后,吞吐立刻恢复到接近线速。

实用调试建议是:不要固守旧配置,先看 PHY 手册里的 delay 寄存器默认值。如果手册里没有明确写,就按“先 rgmii-id,不行换单方向,再不行换成无 delay”这个顺序去试。每改一次配置,都要重新验证两个指标:link 是否稳定协商到千兆、大包 ping 和吞吐是否正常。不要只看 ping 通就算过,一定要用 iperf3 或者大包压力测试确认时序裕量足够。

2.3 复位时序和时钟配置别照抄

设备树里的 reset-assert-us 和 reset-deassert-us 是很多人容易忽略的地方。默认值 10ms/50ms 不一定是错的,但换 PHY 后一定要重新对着手册确认。我这次把 deassert 时间从 20ms 调到了 50ms,PHY 识别率明显提升,说明旧参数在这个 PHY 上确实不够。

另外,RK3588 的 GMAC 外设时钟也需要检查。DTS 里 ethernet 节点的 assigned-clock-parents 和 assigned-clock-rates 会影响 MAC 侧生成 125MHz TX 时钟的能力。如果这部分配置有问题,就算 PHY link up,数据也发不出去。调试中如果发现 TX 方向完全没波形,可以先查一下 clk_summary 里 gmac 相关时钟是否正常:

cat /sys/kernel/debug/clk/clk_summary | grep gmac

比较直观的现象是,某些板子为了兼容多颗 PHY,会在 DTS 里配置不同的 pinctrl,导致 GMAC 时钟脚没有正确复用,这种情况靠改 PHY 配置永远修不好。

3. 内核识别、链路测试到UDP调试,一条链路拆到底

3.1 PHY驱动部分:先把“识别”弄稳

RK3588 平台的内核通常已经配置了非常丰富的 PHY 驱动。RTL8211F 有专门的 realtek 驱动支持,所以原来板子的网络非常省心。换到 PHY_X 后,内核 phylib 能不能正确匹配到驱动,取决于,内核里有没有对应 PHY 的驱动,以及 PHY_ID 匹配表有没有包含这颗芯片。

如果内核已经支持 PHY_X,dmesg 里会出现类似识别到的 PHY 驱动名称;如果内核里没有它的专属驱动,Linux phylib 会退回到 Generic PHY Driver。通用驱动不是不能用,但有些 PHY 的特殊寄存器配置(比如特定的 delay 配置、EEE 节能模式)不会在通用驱动里自动初始化,这可能会导致一些莫名其妙的问题。

排查 PHY 是否被内核正确识别,通常看这几个信息:

dmesg | grep -i -E "eth|mdio|phy" ethtool eth0 cat /sys/bus/mdio_bus/devices/*/phy_id

如果 ethtool eth0 能正常显示速度、双工、自动协商等参数,说明 phylib 已经成功驱动了 PHY;如果报错 “Cannot get device settings: No such device”,并伴随 mdio 读取失败,就要回到地址和复位检查。

关于 PHY 驱动,还有一个小建议:如果条件允许,尽量不要长期依赖 Generic PHY Driver。可以对比一下新 PHY 与 RTL8211F 的寄存器差异,看是否需要专门的内核配置项。比如在 menuconfig 里把 PHY 相关组件打开,或者在设备树的 PHY 节点里指定 compatible,确保内核能用最稳定的路径驱动它。这个动作在量产前做掉,能避免后续现场调网络时反复试错。

3.2 从链路层到应用层:经典两段式验证

很多朋友踩坑之后容易慌,一上来就用网络调试助手发 UDP 包,发现收不到就乱改。我的调试习惯是严格遵守两段式验证:先验证链路层,再验证应用层。链路层不通,应用层怎么调都是白搭。

链路层验证的固定动作:

ethtool eth0 # 确认 speed/duplex/link ok ip link show eth0 # 确认 UP ping -c 100 -s 1400 <对端IP> # 大包测试 iperf3 -c <对端IP> -t 30 # 验证吞吐

其中 ping 大包是为了制造边界压力,如果只有小包能通、大包全丢,通常就是时序问题或者 MTU 问题,这时回到 phy-mode 去调整 delay。iperf3 的吞吐测试能直接反映 TX/RX 方向的健康程度,如果单向吞吐很低,也可以帮助定位 delay 方向。

链路层验证通过之后,再做应用层 UDP 验证。我在 Windows 上习惯用网络调试助手,在 Linux 板子上则直接用 nc:

# 板子 A 上监听 nc -u -l 6666 # 板子 B 上发送 echo "hello" | nc -u <板子A的IP> 6666

如果两边在同一网段,A 能收到消息,说明整条物理链路和协议栈工作正常。如果收不到消息,先用 tcpdump 确认包是否到达网卡:

tcpdump -i eth0 udp port 6666

如果在 tcpdump 里能看到包,但 nc 收不到,那就是防火墙或者用户态程序的问题;如果 tcpdump 里完全看不到包,说明底层链路还有问题,回到链路段继续查。这个分界点能帮你快速缩小排查范围。

3.3 PHY寄存器速查与回环测试

当链路层表现异常时,最有效的工具不是换线、换交换机,而是直接操作 PHY 寄存器。下面几个寄存器是调试中最高频用到的:

寄存器地址名称作用
0x00BMCR控制复位、自协商开关、loopback、速度/双工强制
0x01BMSR读取 link 状态、协商能力、扩展寄存器是否存在
0x04ANAR本端自协商能力通告
0x05ANLPAR对端自协商能力,判断协商速度和双工
0x091000BASE-T Control千兆模式的 master/slave 配置等
0x0A1000BASE-T Status千兆协商结果、master/slave 状态

我在调试 PHY_X 时就用到了 0x00 寄存器的 loopback 功能。思路很简单:把 PHY 配置成内部回环模式,然后从 MAC 侧发数据。如果回环模式下 MAC 的发送统计和接收统计都在增长,说明 MAC 到 PHY 之间没有问题,故障定位到对端链路或者应用层。回环测试可以通过 mdio-tools 或 devmem 直接操作寄存器,也可以临时改驱动代码来触发,但不建议在正常产品里长期开启回环模式。

这一层一旦确定了,剩下的事情就简单很多:MAC 到 PHY 没问题,就看 PHY 到变压器、连接器、网线的链路;PHY 到 MAC 有问题,就检查 RGMII 时钟和数据线的时序。千万不要在没有数据支撑的情况下盲目换代码,那样只会把问题搞得更复杂。

4. 常见问题速查与现场排查套路

4.1 五个高频“换PHY后遗症”及对应排查

这次换 PHY 遇到的问题,我整理成了下面这张表,基本覆盖了同类场景下最常见的情况:

现象可能原因排查方向
eth0 不存在,dmesg里MDIO读不到PHYPHY地址 strap 不一致、复位时序不足、供电异常核对PHYAD strap、试增大reset-deassert-us、量电源和晶振
link 反复 up/down复位时间不够、PHY电源纹波大、MDIO读写不稳定延长deassert时间、检查3.3V/1.0V纹波、示波器抓link信号
只能协商到100Mbps千兆握手失败、RGMII时钟异常、线缆质量问题用千兆线直连确认、看PHY 0x09/0x0A寄存器、检查TXC走线
link up但ping不通phy-mode的delay配置不对、MAC时钟未生成尝试rgmii-id/txid/rxid组合、查clk_summary
能发不能收/能收不能发单向delay错误、RGMII RX方向数据采样失败重点调整rgmii-rxid/txid,分别测TX/RX吞吐

第一行是我这次遇到的首要问题,eth0 直接消失,查到最后就是 phy 地址 strap 和旧板子的参考设计有差异。第一第二行现象不同,但根源往往都在硬件的复位和时钟上,排查时可以先从这两项入手。

4.2 我给现场调试定的固定顺序

踩了一周的坑之后,我给自己定了一个固定的换 PHY 调试流程,之后再做类似改动,效率明显提高:

  1. 硬件核对:新 PHY 手册的 strap 配置、复位、时钟、延时默认值,逐项和原理图对照。
  2. 上电抓基础信号:示波器量参考时钟波形、PHY 复位释放时间、电源上电时序。
  3. 扫描 MDIO 地址:确认内核能否在期望地址读到合法 PHY ID。
  4. 确认 PHY 驱动匹配:dmesg 和 ethtool 确认 phylib 正常驱动新 PHY。
  5. 调 phy-mode delay:从 rgmii-id 开始,用大包 ping 和 iperf3 验证,定位最合适的组合。
  6. 链路层压力测试:确认长时间大流量下 no error、no drop。
  7. 应用层 UDP 验证:使用网络调试助手或 nc 做双向 UDP 收发,确认用户态功能正常。

这套顺序的关键是每一层都“钉死”了再往上走。我见过很多同行是在第 5 步还没做完的时候就开始怀疑应用层,甚至怀疑 RK3588 整个 GMAC 有问题,结果折腾半天,最后发现只是 phy-mode 少了个 rxid。调试网络这种模块,最忌讳跳层,一层层查最省时间。

这次换 PHY 给我的最大体会是:PHY 这种“外围小芯片”,换起来没那么简单,但也没有那么神秘。它的核心就在四个字——时序、地址。地址错了,MDIO 读不到设备;时序错了,link up 也一样丢包。只要把新 PHY 的数据手册当回事,把设备树里的 phy-mode、MDIO 地址、复位参数都当成“需要重新验证的变量”,而不是从旧项目里继承的正确答案,整个调试过程会清晰很多。最后再分享一个实际经验:每次修改完设备树 phy-mode 或 PHY 寄存器配置后,不要只 ping 几个包就判定 OK,至少跑一轮 30 秒以上的 iperf3 双向吞吐,再手动插拔几次网线确认 renegotiation 正常。网络问题最大的特点就是“间歇性、偶发性”,验证不充分,很容易在量产出货后暴雷。希望这篇记录能帮你少踩两个坑。

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

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

立即咨询