ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Hi3559AV100+YT8521SH千兆自协商异常排查与RGMII时钟延时调优

Hi3559AV100+YT8521SH千兆自协商异常排查与RGMII时钟延时调优 拿到这块Hi3559AV100的新板卡时我一开始并没有把网络问题想得太严重。硬件同事说“千兆起不来但强制百兆能通”我一听还以为是网线或者对端交换机兼容性的老问题。结果这个“千兆起不来”前后折腾了两天最后定位到YT8521SH这颗国产PHY的自协商能力通告字段上连带着还把RGMII时钟delay的坑一起趟了。这篇文章把整个排查链路、寄存器读写过程、调优手法和最终固化方案原原本本记录下来针对的是Hi3559AV100平台 YT8521SH芯片的千兆自协商异常但思路对绝大多数PHY寄存器调优场景都通用。适合正在做硬件调试、底层驱动、SoC方案验证的工程师参考。1. 现象定位千兆口不是“完全不亮”而是“能亮但协商很慢、大包必丢”1.1 复现条件与第一轮物理层排查故障板卡的结构不复杂主控是海思Hi3559AV100GMAC通过RGMII接口外接裕太微YT8521SH单口千兆PHYPHY地址由板级strap电阻决定我手上这块读出来是3。上电后接PC、接不同品牌的交换机Link状态都极不稳定千兆几乎协商不出来偶尔亮灯也是百兆。把PHY强制到100M全双工之后链路能起来但iperf一跑就掉包ping 1472字节的大包频繁超时完全没法用。第一轮排查基本是纯硬件层面的换了3根网线用测线仪确认线序没问题示波器量25MHz晶振波形频偏在正常范围内按原理图逐路量PHY电源纹波压降和纹波幅度都没有异常复位引脚的上电时序也抓过没发现毛刺。把疑点放回PHY本身之后我又换了第二颗YT8521SH样片问题一模一样说明不是单颗物料体质问题。到这个节点物理层致因基本可以排除了晶振、电源、线缆、焊接、对端设备都做过多轮替换。但有个细节非常关键——强制100M能通但千兆不通而且强制模式下大包会丢这其实已经暗示问题不止“协商不上”这么简单。1.2 从海思SDK侧读取MAC状态确认问题不在MAC配置硬件排查没有结论我把目光转回SoC侧。Hi3559AV100的SDK里网络接口起来之后先看设备树里GMAC节点配置gmac0 { phy-mode rgmii; phy-addr 3; ... };phy-mode用的是rgmii而非rgmii-id这个细节后面会重点讲。再用ethtool eth0查看状态输出是Speed: Unknown! Duplex: Unknown! Link detected: no内核网络子系统显示的Link状态本质上是轮询PHY寄存器1Basic Mode Status Register的bit2拿到的。PHY返回link downMAC侧自然显示不通。我又用ifconfig看了MAC层的收发统计RX errors和CRC errors没有明显异常因为此时链路压根没起来数据面根本没流量。这一步的结论是GMAC的基本配置没有问题RGMII信号通路在物理上也应该是通的否则强制100M时不可能有数据包通过。问题范围被压缩到了PHY执行自协商的过程本身。1.3 该阶段的核心结论把故障范围压缩到PHY自协商过程到这里第一阶段排查链路已经收敛外部硬件环境没有明显异常MAC侧配置没有错误强制100M能通说明MAC到PHY的数据通路基本可用剩下的就是PHY为什么无法通过自协商建立千兆链路。自协商是一个纯软件可控的过程所有状态和能力都暴露在PHY寄存器空间里。这就意味着直接从寄存器层面去找证据比继续拿示波器量来量去更高效。接下来的整个排查都是围绕MDIO寄存器展开的。2. 自协商机制与YT8521SH寄存器地图排查中必须看懂的几个关键位2.1 自协商到底在协商什么FLP、能力字段与主从机制千兆自协商不是简单的“你给我起来”就行。PHY上电后会通过MDI差分线对发送Fast Link Pulse也就是FLP脉冲串里面携带16位的Base Page能力字。双方通过这个能力字交换自己支持的速率和双工模式协商出双方都支持的最高能力。这个过程可以类比成两个人用闪灯互相报菜名我这里有千兆全双工、百兆全双工、百兆半双工你那边有什么咱俩取个交集挑最好的组合。到了千兆这个速率档事情还更复杂一点1000BASE-T需要四对线同时收发PHY之间必须分出一方做Master、一方做Slave由Master提供时钟参考。这个主从关系不走Base Page而是通过Next Page交换1000BASE-T控制信息。Linux内核里通常通过寄存器91000BASE-T Control Register来通告千兆能力通过寄存器101000BASE-T Status Register查看主从协商状态。排查YT8521SH这种PHY的问题绕不开这几个标准寄存器。把它们的含义吃透比瞎改扩展寄存器有用得多。2.2 YT8521SH关键寄存器位速查IEEE 802.3定义了0到6这几个基本寄存器加上千兆扩展的9、10、11基本覆盖了自协商排查的主要战场。下表是我在排查过程中反复看的关键位建议收藏寄存器关键bit含义Reg0 (Control)bit12自协商使能为0时AN关闭只能强制模式Reg0 (Control)bit9重启自协商置1触发AN重新开始Reg1 (Status)bit2链路状态1Link UpReg1 (Status)bit5自协商完成标志1AN完成Reg4 (AN Adv)bit8通告100Base-TX全双工能力Reg4 (AN Adv)bit7通告100Base-TX半双工能力Reg4 (AN Adv)bit6通告10Base-T全双工能力Reg4 (AN Adv)bit5通告10Base-T半双工能力Reg9 (1000BT Ctrl)bit9通告1000Base-T全双工能力Reg9 (1000BT Ctrl)bit8通告1000Base-T半双工能力Reg10 (1000BT Stat)bit15主从协商错误Reg10 (1000BT Stat)bit14主从协商完成Reg10 (1000BT Stat)bit13本地接收器状态正常Reg10 (1000BT Stat)bit12远端接收器状态正常Reg10 (1000BT Stat)bit11对端通告1000Base-T全双工能力YT8521SH的扩展寄存器访问方式和不少国产PHY一样需要通过页选择机制切换。这类寄存器一般负责RGMII收发时钟延迟、LED控制、EEE节能以太网等配置不同批次的数据手册在具体地址上可能有差异排查时以你手上那颗芯片的datasheet为准。2.3 MDIO读写实操在板级Linux环境下如何直接访问PHY海思SDK编译出来的rootfs里通常不带mdio工具。我的做法是交叉编译一个mdio-tools塞进根文件系统命令行直接读写PHY寄存器效率比来回改驱动高太多。读操作的命令格式是mdio eth0 read 3 1含义是通过eth0所挂的MDIO总线访问PHY地址3读寄存器1。写操作同理mdio eth0 write 3 9 0x0200如果没有mdio工具手头又比较着急还可以用busybox的devmem直接操作GMAC里的MDIO控制器寄存器绕一圈去发起MDIO事务。不过这种方式受限于芯片手册的寄存器偏移操作繁琐且容易写错不如mdio工具直观。2.4 自协商状态的第一次快照证据浮出水面板子上电后先读一组状态寄存器做全量快照我通常把Reg0到Reg11能读的全读一遍。这一读问题就露馅了寄存器读回值关键位解读Reg00x1000AN已使能Reg10x7809bit50AN未完成bit20Link DownReg40x01E1百兆、十兆能力通告正常Reg90x0000千兆全双工、半双工能力都没通告Reg100x0000没有进入千兆主从协商流程问题一下就清楚了YT8521SH的寄存器9读出来是0等于告诉对端“我这颗PHY不支持千兆”。对端交换机和PC网卡接收到这个能力字段之后只能退回百兆甚至十兆去协商千兆自然起不来。3. 寄存器级调优实操能力通告、主从协商与RGMII时钟延时的调整记录3.1 能力通告修复把千兆能力明确写回Reg9和Reg4确认了根因是千兆能力通告缺失修复反而简单。通过mdio工具直接写寄存器# 先开启1000BASE-T全双工能力通告 mdio eth0 write 3 9 0x0200 # 重新确认百兆能力通告完整0x01E1 mdio eth0 write 3 4 0x01E1 # 开启自协商并使能重启自协商 mdio eth0 write 3 0 0x1200写Reg0的0x1200包含两个动作bit12置1保持自协商使能bit9置1触发restart AN。这是一个很典型的操作序列建议后续做PHY初始化时沿用。大约3秒后重新读状态寄存器寄存器读回值关键位解读Reg10x796Dbit51AN完成bit21Link UpReg90x0200千兆全双工能力已通告Reg100x7800主从协商完成双方接收状态正常对端通告千兆全双工再用ethtool eth0确认显示Speed: 1000Mb/sDuplex: Full。到这里千兆自协商已经恢复了。整个过程如果写成结论就一句话PHY在自协商时没有把千兆能力广播出去对端只能退避到百兆。但真正值得记住的是“强制百兆能通、千兆起不来”这类组合现象背后大概率藏着能力通告位的隐性丢失。3.2 自协商恢复后的第二个坑RGMII时钟延时导致的大包丢包千兆协商成功我本以为案子结了结果ping大包立刻露出马脚。链路显示Up速率1000M但只要ping超过1000字节的包丢包率就到20%以上ethtool -S eth0里rx_crc_errors持续增长。这个问题和自协商机制本身无关而是RGMII接口的时钟delay配置不对。RGMII规范要求时钟信号相对数据信号做约1.5ns到2ns的延迟以保证接收端的建立保持时间。现实中很多板卡没有在PCB上做等长绕线而是依赖MAC或PHY内部的可编程延迟补偿。Hi3559AV100这边用的是phy-mode rgmii这个配置下MAC不会主动加delay而YT8521SH如果也没有在扩展寄存器里开启收发时钟延迟双方数据采样点就对不上。强制百兆时问题不明显是因为100M速率下RGMII时钟频率低时序裕度相对充足一上到千兆时钟沿变快时序窗口被压缩数据错误就集中爆发了。3.3 RGMII时钟延时的四种组合测试YT8521SH的RGMII delay开关在扩展寄存器页里不同批次的芯片地址有差异我这边就不直接给死地址了。排查思路是查datasheet里RGMII Timing Adjust这一段把TX delay和RX delay的控制位找出来然后四个组合逐一验证组合TX DelayRX Delay实测结果1关关Link Up但大包必丢CRC errors持续增长2开关从PHY收上来的方向RX稳定发出去的方向TX仍有丢包3关开与组合2相反TX方向稳定RX方向丢包4开开双向打流均稳定CRC errors归零这个测试结果非常典型TX和RX两个方向必须分别补delay缺一边都不行。我最终在扩展页里把TX和RX delay都打开再配合phy-mode rgmii-id让MAC侧也明确工作在补延迟模式板子彻底安静下来。关于rgmii-id这个配置不同SoC的GMAC实现不同有的会根据这个字符串自行补时钟延迟有的只是标记一下。实际调试时建议先用PHY侧寄存器把delay固定打开再调整设备树、反复验证不要盲信某一侧。3.4 调优后的完整验证数据寄存器调优不是“看起来好了就行”必须用数据说话。我最终的验证方案是# 持续ping大包10000次 ping -s 1472 -c 10000 对端IP # TCP吞吐 iperf -c 对端IP -t 300 # 查看网卡错误计数 ethtool -S eth0 | grep -E crc|error修复后的结果ping 1472字节大包10000个0丢包平均延迟0.4ms以内iperf TCP打流5分钟带宽稳定在940Mbps左右达到千兆链路的正常吞吐rx_crc_errors由之前持续增长变为0反复up/down网口50次每次都能稳定协商到1000M Full。到这里从“千兆起不来”到“千兆稳定跑满”整个问题才算真正闭环。4. 从“能通”到“稳产”稳定性验证与驱动侧固化方案4.1 长时间稳定性与对端兼容性矩阵单板修好不算完还要考虑多台设备、多种对端环境下是否都能稳定复现修复效果。我拉了5台板卡分别对接Intel PC网卡、博通交换芯片的设备、瑞昱网卡等做了以下测试矩阵测试项测试条件结果反复插拔每台板卡连续插拔50次5台均稳定协商至1000M Full大包压力ping 1472字节10000包/次0丢包长稳打流iperf TCP8小时带宽始终稳定在930Mbps以上异常掉电恢复上电后立即ping均能完成自协商并联通另外特别留意一个“隐藏坑”YT8521SH是支持EEE节能以太网的。个别交换机开启EEE后长时间空闲再跑大流量时可能出现link flap表现为链路突然down了又马上up。这个在前期测试里最容易漏掉。规避的办法是直接在PHY扩展寄存器里把EEE关掉代价是待机功耗高一点点换来的是网络稳定。对我们的产品场景来说这个取舍是值得的。4.2 把寄存器修改固化到设备树与驱动初始化序列手动通过mdio工具改寄存器只能用于调试验证总不能每次开机都人工敲一遍命令。最终固化方案分两层。第一层是设备树明确RGMII工作模式gmac0 { phy-mode rgmii-id; phy-addr 3; max-speed 1000; };第二层是在内核PHY驱动里加config_init回调让PHY每次probe时都自动完成能力通告与时钟延时配置。以下是一个示意结构具体寄存器地址以你的芯片手册为准static int yt8521_config_init(struct phy_device *phydev) { /* 进入扩展寄存器页开启RGMII收发时钟延时 */ phy_write(phydev, 0x1f, 0x0002); phy_write(phydev, 0x10, 0x0083); /* 示意值TX/RX delay on */ /* 回到标准寄存器页配置千兆/百兆能力通告 */ phy_write(phydev, MII_CTRL1000, ADVERTISE_1000FULL); phy_write(phydev, MII_ADVERTISE, ADVERTISE_ALL); /* 重启自协商 */ phy_write(phydev, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); return 0; }固化之后我把之前手动写的mdio命令全部撤掉反复重启板卡验证每次都能自动完成千兆协商不再依赖人工介入。4.3 调试思路沉淀把“寄存器快照法”变成自己的习惯这次排查最大的收获倒不是某个寄存器值而是“寄存器快照对比”这套方法论。国产PHY芯片硬件上和主流PHY大体兼容但寄存器默认值、扩展页机制、上电初始化时序各自有各自的小脾气出问题时不具备“看一眼就知道哪里不对”的那种直觉。我的习惯做法是新板卡拿到手、PHY功能正常的时候先把Reg0到Reg11、以及扩展页的RGMII delay、EEE等关键配置全部读一遍存档成一个基线文件。后面不管是硬件改版、换物料批次、还是换驱动版本一旦网络行为出现异常先拿当前寄存器快照和基线diff差异就是嫌疑犯。这个方法帮我在其他项目里节省了大量瞎猜的时间。另外建议调试阶段始终保留mdio工具在根文件系统里不要因为“量产了”就移除。设备出货后如果遇到极少数网络问题售后返回来的板子能直接通过mdio读取PHY寄存器很多问题在电话里就能判断是硬件还是配置省得来回寄板子。最后再说一个小的实操细节每次修改完PHY寄存器之后不要急着测流量先花10秒钟读一遍Reg1的bit5和bit2确认AN真的完成、Link真的Up了再动手。很多时候你以为改了没生效其实是写完之后没等自协商完成就急着看结果自己吓自己。
返回列表