STM32H563 + ADIN1200 的 RMII 时序裕量排查与修复实战 1. 板子上的以太网“偶尔通、偶尔断”先别急着怀疑PHY坏了做嵌入式网络设备的人大概率都遇到过这种场景板子画完、贴片回来上电初始化STM32H563的ETH外设MDIO能读到ADIN1200的寄存器Link也能起来但一跑业务就露馅——PING大包偶发超时TCP重传率高得离谱甚至某个温度下完全不通。代码翻来覆去查不出逻辑问题换一颗PHY还是老样子最后只能把锅甩给“信号质量不行”。我之前在一个工业网关项目里就栽过这个跟头。主控是STM32H563PHY选的是ADI的ADIN1200接口自然是RMII。当时第一版PCB为了赶交期RMII信号组的等长约束做得比较随意REF_CLK和数据线各走各的长度差了个好几厘米。结果就是前面说的那一幕常温短距离测试勉强能过放到产线做持续吞吐测试就原形毕露。这个问题的本质不是“不通”而是RMII接口的时序裕量不足。它不会直接让系统死掉但会在硬件环境略微恶化时温度升高、线缆变长、板卡批次差异让数据采样刚好落在建立时间或保持时间边缘造成偶发错误。这种问题最坑人因为它不是必现且很难用软件手段抓到直接证据。所以这篇就围绕STM32H563和ADIN1200这对组合把RMII时序裕量这件事从原理、排查到修复完整梳理一遍。文章不会只给结论会把我实际踩坑的过程、测量的方法和最后落地的改动都摊开讲。如果你正在做H5系列ADIN1200的方案或者遇到RMII接口诡异问题的这篇应该能帮你省几周时间。2. 先算清楚RMII的时序账才知道裕量到底被谁吃掉了2.1 RMII比MII省了引脚但代价是时序预算更紧RMIIReduced Media Independent Interface是MII的精简版数据线从4位砍到2位所以需要50MHz的REF_CLK才能撑起100Mbps吞吐。接口信号从MII的16根左右降到7根TXD[1:0]、TX_EN、RXD[1:0]、CRS_DV、REF_CLK再加上管理接口MDC/MDIO。引脚少了是好事但代价是所有数据都以REF_CLK为唯一参考时钟而且只有20ns的周期。所有信号要在REF_CLK的上升沿附近完成采样留给建立时间和保持时间的预算非常紧张。相比之下旧MII接口的25MHz时钟下有40ns周期时序容错明显更好。因此在RMII设计中REF_CLK的走线长度、时钟极性和数据线的等长匹配从原理上就决定了系统能不能稳定跑。这不是玄学是可以用公式算出来的硬约束。2.2 建立时间、保持时间与REF_CLK的三角关系时钟沿采样数据要满足两个条件数据在时钟沿之前稳定建立时间t_su在时钟沿之后继续保持一小段时间保持时间t_hold。RMII里的REF_CLK通常是由PHY提供的ADIN1200可以作为时钟源输出50MHzMAC根据这个时钟来驱动TXD/TX_EN同时PHY也用它来采样RXD/CRS_DV。以PHY输出REF_CLK给STM32H563为例整个链路的时序关系大概是PHY内部通过REF_CLK沿把TXD/TX_EN锁存到输出引脚TXD信号经过PHY内部延迟和PCB走线后到达STM32的ETH_TX引脚STM32内部对TXD的采样也是以REF_CLK来自PHY为基准的。看上去很简单但这里的延迟路径有PHY内部的输出延迟Tco、PCB走线延迟、STM32引脚输入延迟、以及REF_CLK本身从PHY输出到STM32引脚的走线延迟。如果REF_CLK和TXD的走线长度相差太大等于给建立/保持时间塞进了一个额外的偏差项。实际体会是在30MHz以下低速接口上几厘米的走线差基本不用管但RMII的50MHz参考时钟下数据有效窗口本身就是个位数纳秒这个偏差就变得很致命了。2.3 时序裕量到底怎么算时序裕量的物理意义是在当前设计下留给建立时间和保持时间的剩余空间。以PHY输出REF_CLK为例MAC端接收方向的数据时序校验可以简化成下面这个思路建立时间裕量 REF_CLK到达时刻 - 数据变化沿到达时刻 - 接收端要求的建立时间保持时间裕量 数据下次变化沿到达时刻 - REF_CLK到达时刻 - 接收端要求的保持时间在FR4板材上普通微带线的信号传播速度大约是每厘米67~70ps走线每差1cm延迟就差大约70ps。单独看1cm似乎可忽略但如果PCB上REF_CLK比数据线短了5cm就产生了约350ps的偏差再叠加PHY内部输出延迟通常1~5ns和STM32引脚的输入延迟就真的可能把只有几ns的建立时间吃光。ADIN1200的数据手册里会给出MAC侧接口的建立时间、保持时间要求H563的ETH外设也会给出RMII接口的时序参数。两者同时满足才是裕量为正。我实际测试时发现真正能把问题定位下来靠的就是把测量到的实际延迟代入公式算一遍而不是靠感觉去“调一下试试”。3. 实测记录一个偶发丢包问题的完整排查链路3.1 现象确认是“必现”还是“偶发”决定了排查方向当时我在板子上跑的是一个简单的TCP回环测试STM32H563接收网口数据原样回传电脑端用吞吐工具持续发。正常情况下100Mbps小包能跑到90Mbps以上且零丢包但这块板子跑几分钟后就会出现重传重传率在0.1%~1%之间波动看起来不高但是对工业控制场景是不可接受的。先做了一套常规检查MDIO读写都正常PHY的链路状态寄存器显示Link up协商结果是100Mbps全双工MAC侧的中断也没有报错。然后怀疑是软件问题把DMA描述符优先级、缓存一致性都查了一遍没有发现异常。换了一块板子跑丢包率更低但也没完全消失——这个“时好时坏”的特征让我开始怀疑硬件时序。3.2 示波器抓时序窗口真相在REF_CLK的上升沿附近我用的是一台带宽500MHz的示波器如果手头只有100MHz的抓50MHz时钟没问题但看上升沿细节会吃力测出来误差反而误导判断。探头用短地簧直接点在RMII信号上。测量点选在STM32引脚端也就是接收端同时抓REF_CLK、TXD0、TXD1、TX_EN四根线。之所以选发送方向是因为我们板子的REF_CLK是ADIN1200输出的PHY作为时钟源时序从PHY端到MAC端测出来最直接。波形结果显示数据线的翻转沿离REF_CLK上升沿非常近数据稳定窗口大概只有2~3ns。而ADIN1200要求接收端数据相对于时钟达到一定的建立时间如果数据刚稳定1ns时钟沿就来了采样结果自然不稳定。再测另一块丢包率更低的板子发现它的数据稳定窗口明显更宽4~5ns这就基本坐实了丢包率差异和时序裕量差异是相关的。这里要注意示波器波形看到的现象是“数据沿贴着时钟沿”但究竟是哪一段路径吃掉了时序预算需要结合布局布线来倒推。我随后跑到PCB设计文件里量了长度发现TXD[1:0]走线平均比REF_CLK长了约3cm有些过孔还额外加了延迟。3cm按70ps/cm计算大约是210ps这个量级看起来不大但加上芯片内部延迟和信号上升沿的大概1~2ns就把整个窗口压到了边缘。3.3 锁定根因REF_CLK的数据返回路径被忽略了根因比预想的还要多一层这个板子的REF_CLK走线是从ADIN1200的CLKOUT引脚直接拉到STM32H563中间没有串阻也没有在靠近PHY端加滤波电容。表面上看没问题但RMII的REF_CLK既作为时钟又隐含了“数据回送参考”的作用——当PHY作为时钟源时它自己的TXD输出路径是和REF_CLK输出路径在内部关联的外部走线如果再不对称等于给这个关联又加了一个变量。我另外还注意到H563的ETH外设RMII支持时钟极性的配置可以在寄存器里翻转采样沿。这意味着如果REF_CLK和数据线的延迟差让默认的上升沿采样落在数据变化的边沿附近那么把采样沿翻转到下降沿反而可能拿到更宽的稳定窗口。这也是后面修复时最先尝试的软件手段。4. 三种常见根因从硬件设计到软件配置逐个排雷4.1 根因一时钟源方向和电路设计不匹配RMII的REF_CLK有两种工作模式PHY提供时钟PHY as clock source或者MAC提供时钟MAC as clock source。H563和ADIN1200两端都得配置一致否则即使链路能通时序基础就是错的。H563的ETH外设可以配置RMII时钟是从外部引脚输入还是由内部生成后输出。ADIN1200的REF_CLK引脚也可以配置为输入或输出。很多人在做原型时硬件上REF_CLK是PHY输出的但代码里初始化时MAC侧没有正确配置对应的时钟方向导致MAC内部对REF_CLK边沿的处理和实际电路不一致时序裕量自然很差。我的建议是拿到一块新板子第一步先核对硬件原理图上REF_CLK的实际连接方向再去查驱动初始化代码里ETH的时钟配置确保两者一致。不要只看默认例程不同开发板的REF_CLK方向经常是反的。4.2 根因二PCB走线延迟失衡REF_CLK与数据线长度差过大这是最常见的物理层根因。RMII的信号组里REF_CLK是时钟TXD[1:0]、TX_EN、RXD[1:0]、CRS_DV都是数据设计中应该把REF_CLK和所有数据线做等长约束。很多PCB工程师习惯按普通信号去走RMII觉得“不过就是几十兆的信号”这就埋了雷。我之前这块板子就是吃了这个亏。建议在Layout阶段把REF_CLK设为约束管理器中的时钟Target数据线以它为基准做等长组内偏差控制在±2mm以内REF_CLK和整组数据线的长度差尽量控制在±5mm内。如果结构限制确实做不到优先保证REF_CLK不短于数据线因为“时钟比数据晚到”一般是可以通过软件采样沿调整来弥补的。4.3 根因三GPIO速度等级和上下拉配置拖了后腿这个坑特别容易误判因为它藏在MCU的引脚配置里。STM32H563的ETH_TX、ETH_TX_EN等引脚需要配置为复用功能同时还要选择合适的GPIO输出速度等级。输出速度等级太低上升沿变缓数据的稳定窗口会被压缩输出速度等级太高又会引入过冲和振铃对信号完整性同样不利。实测中100M RMII的TXD信号建议把GPIO速度配到High不同系列叫法不同H563上对应的是High speed档不要用Very High也不要用Medium。具体可以量一下波形上升时间做取舍。至于MDC/MDIO的上拉问题——这是网上被问得很多的一个点。MDC是管理时钟由MAC驱动PHY方向固定一般不需要外部上拉MDIO是双向数据线需要接上拉电阻常见4.7kΩ到10kΩ保证空闲状态为高。如果你用了ADI评估板的参考设计也可以直接照搬其取值。需要特别提醒的是千万别给RMII的数据线或REF_CLK随意加上拉/下拉电阻这会直接影响信号边沿质量和时序百害无一利。5. 修复与验证先软件后硬件一步步把裕量找回来5.1 第一步调整RMII时钟极性用软件试探裕量方向即使布局布线已经定型软件仍然有优化的余地。STM32H563的ETH外设RMII支持时钟极性选择可以在不推翻硬件的前提下改变采样时刻从而避开数据不稳定区域。我用一轮对比试验来确认效果配置1上升沿采样默认配置。实测丢包率0.5%左右配置2下降沿采样。实测丢包率降到0.01%左右几乎观察不到重传配置3恢复默认配置同时把PHY侧CLKOUT的驱动强度调小一档丢包率介于两者之间。出现这个结果说明该板卡的REF_CLK与数据线延迟差方向恰好让下降沿采样拿到了更宽的稳定窗口。这不代表所有板子都应该用下降沿但至少验证了软件调整的可行性。具体寄存器操作上H563的ETH外设里有一个控制RMII采样沿的位不同HAL版本名称可能不同你在初始化ETH时留意一下结构体里“Polarity”或“ClockDivision”相关字段即可。5.2 第二步调整GPIO速度等级和PHY驱动强度软件极性问题解决后我继续把发送引脚的GPIO速度从“Very High”降到“High”同时在ADIN1200寄存器里调整了RMII输出驱动强度。这一步的目的不是救时序而是降低EMI和过冲让信号更干净。过冲大的信号虽然不会立刻导致误采样但在高温或长走线下反射叠加会把裕量进一步吃掉。调整后重新抓波形TXD信号的上升沿从大约1.2ns变为1.8ns过冲从约15%降到5%以内数据稳定窗口又增加了大约0.5ns。量不大但对本来只有2~3ns的窗口而言相当于多了20%的余量。5.3 第三步硬件整改从走线层面根治软件调整是“找回”裕量但真正要在量产中稳定还得靠硬件把根因消除。我当时的改板动作主要有三个REF_CLK与数据线等长把REF_CLK走线单独绕线让REF_CLK与TXD[1:0]、TX_EN、RXD[1:0]、CRS_DV的长度差控制在5mm以内。绕线时用45度折角不走直角减少阻抗突变。REF_CLK远离其他高速信号确保REF_CLK两侧有足够的地铜皮包裹减小串扰。尤其不要让它和以太网变压器的差分走线平行长距离走线。靠近PHY的REF_CLK引脚增加串联端接在ADIN1200的REF_CLK输出靠近源端位置放一个22Ω电阻可以有效抑制过冲实测效果明显。改完板子再跑之前那个TCP回环测试持续12小时丢包率从0.5%降到0重传数为0。再测不同温度用温箱跑了-20℃到70℃在默认上升沿采样配置下也全部通过说明裕量已经真正恢复到了正常水平。5.4 补充软件上还可以做哪些防御性措施硬件修好之后我还在固件里加了两个防御性设计适合量产项目上电后统计PHY的链路错误寄存器如果连续几次出现接收错误就主动做一次软复位重新初始化避免偶发错误累积。周期性读ADIN1200的温度和寄存器状态提前发现信号质量劣化趋势。这套逻辑不复杂但对工业现场远程维护很有帮助。6. 把时序裕量做成可量化的指标比“感觉稳定”靠谱得多调试完这块板子之后我最大的感受是RMII能不能稳定不是玄学而是每一段路径延迟加起来能不能满足数据手册上的建立/保持时间要求。后续我在设计阶段就定了一套检查清单现在分享出来检查项合格标准REF_CLK与数据线长度差控制在5mm以内优先保证REF_CLK不短于数据线TXD/RXD信号上升时间1~2ns之间过冲小于10%数据稳定窗口数据沿到时钟沿大于等于数据手册要求的建立时间1ns余量RMII时钟源方向必须与硬件原理图一致MDC/MDIO上下拉MDC可不上拉MDIO按参考设计接4.7k~10kΩ上拉RMII数据线上下拉禁止添加任何上下拉电阻GPIO输出速度等级High不宜Very HighPHY的RMII驱动强度以波形实测为准优先降低过冲另外在测量方法上有几个经验示波器带宽至少要300MHz以上带宽不足看到的上升沿是失真的测出来的裕量会偏小或偏大都会误导判断。探头要用最短的地线夹不要用长地线否则探头本身就会在波形里引入几个ns的振铃。测波形要测在接收端引脚不是测在PHY输出端因为看的就是接收端实际的采样条件。如果板子已经量产不能大改优先尝试软件时钟极性调整往往能救回一大半再考虑用PHY寄存器调整驱动强度或均衡最后才是改PCB。最后说一句ADIN1200本身是一颗不错的工业以太网PHY低温、长距离这些场景表现都靠谱。大多数时候问题出在我们自己这一侧尤其是RMII的时序设计上。按照上面的思路做一遍量化验证再把裕量余量留足这套H563ADIN1200的方案还是很稳的。