ARTICLE DETAIL

资讯详情

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

U-Boot下YT8521SH PHY调试实战:RGMII时序与LED配置全解析

U-Boot下YT8521SH PHY调试实战:RGMII时序与LED配置全解析 这块板子原本用的是进口的千兆PHY因为供货问题换成了裕太微的YT8521SH。当时想得很简单引脚兼容焊上去就能跑。结果真到调试那天U-Boot里先是mii info读不到设备好不容易读到了又link不上link上了又ping不通折腾到半夜发现LED灯的状态也是乱的。前前后后花了两天半最后问题全部集中在两个地方RGMII时序的delay配置以及PHY的LED复用映射。这篇就把整个调试过程复盘一遍给后面要在U-Boot阶段调YT8521SH的朋友留个参考。这篇文章适合这几类人看正在做国产PHY替换方案、在Xilinx或其他平台用RGMII接口连接YT8521SH、以及想在U-Boot阶段就把网络打通再用tftp加载镜像的嵌入式工程师。我会把寄存器操作命令、时序判断方法、LED配置思路和常见坑位全部展开尽量做到你拿着文章能直接对着自己的板子操作。1. 项目背景与整体设计思路1.1 为什么选YT8521SH先说选型背景。我们这块板卡是工业控制类产品主控用的是Xilinx Zynq-7010原来配的是某进口品牌的千兆PHY。去年对方交期越拉越长一颗料等三个月是常事产线那边压力很大于是开始评估国产替代方案。裕太微YT8521SH是当时综合对比下来比较合适的选项单端口10/100/1000M自适应支持RGMII和SGMII两种MAC接口内置LDO外围电路精简工业级温宽也有对应型号。最关键的一点它的引脚排列和原来那颗PHY高度兼容硬件改板工作量很小基本只要调整部分电阻电容的值就能贴上去。但这里有个非常重要的概念需要先明确引脚兼容不代表默认寄存器配置兼容。两个不同厂家的PHY上电后的寄存器默认值、RGMII内部delay的默认开关状态、LED引脚的默认映射规则可以说完全不同。如果默认配置和你板卡的走线方案不匹配就会遇到我后面描述的那些诡异现象。1.2 调试环境的构成这个项目里的调试环境比较典型我列一下主控Xilinx Zynq-7010PS端GEM作为以太网MAC通过RGMII接口连接PHYPHY裕太微YT8521SHMDIO地址0x03由硬件引脚拉拔决定BootloaderU-Boot 2018.03需要支持mii/mdio命令和网络启动功能调试目标U-Boot阶段能ping通开发机后续用tftp加载内核和设备树辅助工具串口终端、示波器、FPGA内部的ILA逻辑分析仪调试过程中用到最多的其实是U-Boot自带的mii命令它在没有完整驱动支持的情况下可以直接读写PHY寄存器非常适合做底层验证。后面所有时序和LED配置本质上都是在和寄存器打交道。2. RGMII时序的坑Delay到底该加在哪一侧2.1 先看懂RGMII的采样关系RGMII是个典型的DDR接口。在千兆模式下时钟频率125MHz数据在时钟的上升沿和下降沿各采样一次每次采样4bit拼起来就是8bit数据。正因为是双沿采样它对时钟和数据的相对位置极其敏感。关键点在于RGMII标准定义的是源同步传输就是说发送端把时钟和数据同时发出去接收端理论上应该在时钟边沿去采样数据。但问题来了时钟是沿数据是电平两者同时到达接收端的话你根本无法在电平稳定的中间位置去采样——正好卡在数据翻转的边界上。所以RGMII实际工程里必须做一件事把数据或时钟相对移动半个采样窗口也就是大约2ns8ns时钟周期的一半让数据在时钟边沿附近保持稳定这样接收端才有足够的建立时间和保持时间。这也是RGMII delay问题的根源到底谁来做这个2ns的延迟方案AMAC侧FPGA/GEM对输出的TX时钟或TX数据加delayPHY侧关闭内部delay方案BPHY侧打开内部TX delay/RX delayMAC侧不做处理方案C错误示范两侧都加delay或者两侧都不加方案C看起来极端但实际工程里经常出现。比如MAC侧的RGMII IP核默认帮你加了IO delayPHY又因为在datasheet里读到default TX delay enabled而没有去动它结果就是这个方向的delay等于加了两次。反过来MAC侧没加、PHY的delay又被strap脚配置成关闭那等于完全没有delay。两种极端情况都会导致接收端采样不稳定现象就是link能起来、数据收不到或者CRC疯狂报错。2.2 YT8521SH的Delay配置实战YT8521SH的RGMII delay配置在寄存器0x17里具体bit定义以你手上的datasheet为准我这里只说思路和操作命令。这个寄存器里分别有控制TX delay和RX delay的两个bit通过mii命令可以查看和修改。我在调试时第一步是先读当前的配置状态 mii info PHY 0x03: OUI0x4F5E, Model0x81, Rev0xA0 mii read eth 0x03 0x17这里要注意不同版本的U-Bootmii命令的参数格式会有差异。有的是mii read addr reg有的要带设备名比如mii read eth 0x03 0x17。如果命令格式不对用help mii看一下当前U-Boot的用法就行。我当时的处理方案是RX方向让PHY开内部delayTX方向由MAC侧负责delay把PHY的TX delay关闭。这样做的原因是Zynq PS端的GEM在RGMII输出上已经有时序保证不需要PHY再叠加一层。具体操作就是把0x17寄存器的值调整成TX delay关闭、RX delay打开的组合。写完寄存器后立刻回读确认 mii write eth 0x03 0x17 0x3CB0 mii read eth 0x03 0x17这个0x3CB0是我们板卡上验证过的值之一不代表所有方案都适用。真正判断标准有两个第一个是看PHY能不能正确建立link第二个是ping包不丢、tftp下载不断流。注意同一个PHY在温度变化后最优delay值可能会有偏移。我在项目里做了一个简单的老化测试把板卡放到高低温箱里各跑两小时ping确认这个配置在冷热态下都稳定才最终定下来。2.3 Xilinx FPGA侧还需要做什么如果你的MAC是在Zynq PS端比如GEM那U-Boot阶段不太需要关心FPGA侧的时序约束因为PS端硬件已经处理好了。但如果你是在PL端自己写GMII转RGMII逻辑或者用Xilinx的AXI Ethernet IP那有一件事逃不掉RGMII接收路径的input delay约束。RGMII接收侧在FPGA里通常用IDDR原语实现双沿采样。为了让工具正确分析时序你必须给RXD和RX_CTL信号添加set_input_delay约束。这个约束的数值不是拍脑袋定的要根据PHY datasheet里给出的时序参数来计算。以常见情况为例PHY输出的RXD相对于RX_CLK有大约1ns到2ns的skew时钟周期是8ns。你需要在XDC里设置类似这样的约束set_input_delay -clock [get_clocks {rx_clk}] -min 1.0 [get_ports {rxd[*] rx_ctl}] set_input_delay -clock [get_clocks {rx_clk}] -max 2.0 [get_ports {rxd[*] rx_ctl}]这组数值要改成你实际PHY的时序参数然后留出20%以上的裕量。做完约束后一定要跑完布局布线再看时序报告setup/hold都不能有violation。我们项目里出现过一次问题就是忘了加这个约束Vivado在时序收敛后给了个红色报告上板调试时网络死活不通加了约束重新生成bitstream之后一切正常。3. U-Boot里的PHY初始化与驱动匹配3.1 先确认MDIO通路是不是通的很多人在U-Boot里调PHY上来就直接检查驱动代码其实第一步应该先确认MDIO总线能不能正常读写PHY寄存器。MDIO通路不通后面所有事都免谈。U-Boot里最简单的验证命令就是mii info它会扫描MDIO总线上所有地址把能响应的PHY列出来 mii info PHY 0x03: OUI0x4F5E, Model0x81, Rev0xA0如果这里什么都列不出来先别急着怀疑PHY芯片坏了按下面这个顺序排查PHY的复位引脚电平是否正常。我们第一次上电就是栽在这——PHY的RST脚被MAC那边的GPIO拉死了mii info完全没响应。用万用表量一下RST脚电压低电平肯定不对。PHY供电是否到位。YT8521SH需要一路为主电源加一路IO电源量一下各个电源轨的电压值。MDIO/MDC引脚有没有接对。MDIO是双向开漏信号需要有上拉电阻MDC是时钟输入要确认MAC那边有没有正常输出时钟。PHY的MDIO地址和硬件引脚配置是否一致。YT8521SH的PHY地址由引脚拉拔决定我们这块是0x03如果你的板子定义不一样命令里的地址也要改。3.2 PHY ID识别与驱动匹配MDIO通路确认没问题后接下来读PHY ID。PHY ID通过寄存器0x02和0x03读取0x02是高16位0x03是低16位 mii read eth 0x03 0x02 mii read eth 0x03 0x03我当时在板子上读到的值对应裕太微的OUI和YT8521SH的型号标识。要注意不同批次芯片在低16位上可能有差异判断芯片型号主要看寄存器0x02和0x03的组合结果以datasheet为准。U-Boot的PHY驱动框架在drivers/net/phy/目录下它会根据PHY ID匹配对应的驱动。如果U-Boot版本里恰好没有YT8521SH的驱动会fallback到通用PHY驱动genphy。大部分时候genphy也能正常工作负责最基础的速度协商和link检测但像LED映射、内部delay开关这类功能它不会帮你配置。所以这里有一个选择临时用mii命令手动配置或者在板级初始化代码里挂一段PHY配置流程。这个在下一节展开。3.3 在U-Boot里固化PHY寄存器配置临时调试用mii命令很方便但每次重新上电都要手敲一遍太不现实。正式做法是把寄存器配置固化到板级以太网初始化函数里。U-Boot里板级以太网初始化一般会调用board_eth_init函数。你可以在建立PHY连接之后把关键寄存器的配置写进去int board_eth_init(bd_t *bis) { struct eth_device *dev; int ret; /* 原来的MAC初始化代码 */ /* 配置YT8521SH寄存器 */ miiphy_write(eth0, 0x03, 0x17, 0x3CB0); miiphy_write(eth0, 0x03, 0x1D, 0x2040); return 0; }这里有两个提醒。第一miiphy_write的调用时机要在PHY已经完成硬件复位之后否则寄存器一会被清掉你写了也白写。第二不要每次进入board_eth_init都无脑重写一遍寄存器最好通过一个静态变量或编译宏控制避免和后面的U-Boot PHY驱动初始化流程冲突。如果你习惯用设备树配置也有另一条路在设备树里的ethernet-phy节点添加reg属性和max-speed等参数然后在U-Boot的PHY驱动里注册自己的配置函数。不过这种方式要求你改动驱动代码比直接在板级函数里写几行要繁琐一些看项目需要选择。4. LED灯配置实战让状态一目了然4.1 先搞清楚每颗LED的定义YT8521SH一般提供多个LED引脚可以映射到速率、链接状态、收发活动、双工模式等各种事件。硬件上电时的默认映射由strap引脚决定但很多板卡设计师不会特意去关注这块出来是什么样就什么样。结果往往是网线插上去了灯也能亮但亮的方式和你的产品需求完全对不上。我们这块板子有4颗LED产品定义是LED0Link/Activity有连接且收发包时闪烁LED11000M速率指示协商到千兆时点亮LED2100M速率指示协商到百兆时点亮LED310M速率指示协商到十兆时点亮但实际加电后LED0常亮不闪、LED1和LED2都不亮、LED3反而跟着link状态亮整个就是乱的。这就是因为PHY内部LED event映射和我们的预期不一致。4.2 寄存器配置实操YT8521SH的LED配置在寄存器0x1C和0x1D那里具体定义要查datasheet。操作流程是先把当前值读出来然后按位修改最后回读确认。我当时先读取了LED相关寄存器的默认值 mii read eth 0x03 0x1C mii read eth 0x03 0x1D然后根据datasheet里的位定义把LED0的事件映射改成Link_Act把LED1到LED3分别改成1000M、100M、10M速率事件。修改完写了回去 mii write eth 0x03 0x1D 0x2040 mii read eth 0x03 0x1D这个0x2040是我们在自己板卡上验证过的值我建议你直接按datasheet里的表格自己推一遍确认每个LED对应的映射字段是你要的再写进去。配置完成后验证方法很简单插上千兆交换机LED0应该常亮并伴随闪烁LED1点亮LED2和LED3熄灭然后强制把对端交换机接口降成100M再看灯的状态切换。4.3 LED相关常见坑LED配置这块经常遇到的问题主要有几个LED全亮或者全灭。一般是你写入的寄存器和PHY实际采用的配置页不一致。有些PHY的寄存器是分页的要通过扩展寄存器访问机制先切换到正确页面再写入配置。YT8521SH如果遇到写入不生效先检查是不是要额外设置页面寄存器。拔掉网线LED还是亮的。这个是link event映射没做对LED被配置成了检测到信号就点亮而不是真正的link up。你可以读一下PHY的link状态寄存器比如寄存器1的bit2先确认PHY是不是真的也认为链路还是up的。如果PHY说link down但灯还亮那百分百是映射的问题。活动LED不闪或者闪的频率不对。看板卡设计有些LED引脚是低电平有效有些是高电平有效对应的配置在寄存器里通常是不同的bit。调换极性前先看原理图确认。我还习惯在调试阶段在U-Boot里写一个小流程配置完LED寄存器后直接插拔网线、切换对端速率同时通过串口打印PHY寄存器1的状态确认PHY的状态变化和LED现象能对上。这比单纯看灯靠谱得多。5. 常见网络问题速查与避坑记录调试过程中遇到了不少问题下面按现象—排查方向—解决方案的格式列出来做成一个速查表方便以后直接对照。问题现象排查方向解决记录mii info读不到PHY复位引脚、供电、MDIO上拉复位引脚被拉死GPIO改为输出高后解决PHY能识别link一直是downRGMII delay配置不对、对端设备协商异常调节PHY内部delay、换交叉线确认link up但ping不通RGMII delay重复或缺失、FPGA约束不对确认同一方向只有一端加delay检查时序报告网络可以协商但CRC错误很多RX方向delay不足数据采样不稳定打开PHY的RX delay回读寄存器确认生效速率协商到100M但PHY跑了千兆模式对端强制100MPHY仍在千兆mii write强制设置速度或用mii切换使能自协商tftp下载到一半卡住网线质量、PCB走线过长、连接器接触不良换短网线测试确认走线长度后定方案LED状态和需求不匹配LED event映射寄存器未配置修改LED寄存器并回读切换速率验证5.1 顺带聊一下两个PHY背靠背的问题搜索热度里有一个phy芯片背靠背这也在我们项目里实际讨论过。当时有一个测试需求需要把两块板卡之间的以太网链路做老化和吞吐测试担心连接器寿命不够就想着能不能绕开连接器直接板对板连接。先说结论PHY的MDI侧就是连接RJ45那侧是可以做背靠背的把两片PHY的MDI差分信号直接连起来PHY一般支持Auto MDI-X能自动识别交叉关系物理链路就这么建立起来了。这种模式在产线老化测试座上很常见我之前做过类似的工装板效果没问题。但如果你想把两片PHY的RGMII侧直接对接那就走不通了。原因很简单RGMII是MAC和PHY之间的接口发送方向、接收方向的角色定义是固定的。两个PHY的RGMII都是为MAC端设计的信号方向和时序逻辑不可能自己协商所以除非中间有一个MAC或者FPGA做桥接否则RGMII to RGMII直接连是不成立的。如果你在网上看到有人问这类问题大概率是概念上把MDI和RGMII搞混了。回到我们的测试需求最终采用的方案是两片PHY通过MDI差分线直接背靠背做链路验证FPGA这侧各自通过RGMII连接MAC。这种方式既绕开了连接器损耗又能真实跑业务流量后续做高温老化非常方便。5.2 排查顺序的心得体会踩完这些坑之后我自己总结了一套排查顺序现在每次调PHY都按这个来第一步用寄存器状态说话不要靠猜。先mii info确认PHY在总线上再读寄存器0x01看link状态、读寄存器0x00看速度协商结果把PHY自己认为的状态和实测现象对齐。第二步能内环就内环。YT8521SH支持PHY内部loopback可以打开loopback在MAC侧发包看数据能否回环到本端。这个测试能快速区分问题在MAC到PHY这一段还是PHY到对端这一段。第三步怀疑时序问题时不要只改寄存器要配合波形或者FPGA的ILA去抓。改一个delay值抓一次RX_CLK和RXD的相位关系记录下来比闷头试错效率高很多。第四步每次改动寄存器都保存记录。我习惯在U-Boot环境变量里存一份当前的配置清单或者直接把命令放到一个bootcmd脚本里这样换一块新板子或者重新上电后可以一键恢复验证过的配置。6. 调试顺序与个人体会最后说点实操中的感受。YT8521SH这颗PHY本身性能没问题和主流进口芯片相比在功能和稳定性上并不差真正花时间的往往是我们对一颗不熟悉PHY的默认行为不够了解以及被引脚兼容这个说法带了节奏。如果让我重新来一遍我会在硬件投板之前就把PHY的datasheet里RGMII delay默认值、LED默认映射、strap引脚配置这几个章节反复读透然后根据板卡实际走线去确定delay该加在哪一侧、LED映射需要改成什么而不是等到U-Boot里才开始验证。硬件上少一个跳线电阻后面软件就要多烧掉两天。另外一个实用技巧建议在U-Boot阶段把所有验证过的寄存器配置命令整理成一个可重放的脚本放到环境变量或者一个bootcmd分支里。每次拿到一块新板子插上网线第一件事就是重放这套配置能立刻判断当前问题是硬件差异还是软件还没配置好。这个习惯后面做量产测试的时候能省很多事。
返回列表