ARTICLE DETAIL

资讯详情

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

STM32F407+DP83848百兆以太网RMII设计:原理图、初始化与热插拔中断实战

STM32F407+DP83848百兆以太网RMII设计:原理图、初始化与热插拔中断实战 如果你也用STM32F407搭配DP83848做百兆以太网大概率会在RMII模式上卡住一段时间——明明只比MII少了四根信号线为什么时钟、模式选择、PHY地址、热插拔中断全都能埋雷这篇文章把我从原理图设计、CubeMX初始化到网线热插拔中断整个流程踩过的坑完整梳理了一遍画板子的和调驱动的都值得看一眼。尤其是RMII接收数据错误这个高频问题我会把排查链路一步步拆给你看不是只给结论而是告诉你为什么会错、该从哪里下手。1. 为什么这块板子最终选了RMII接口选型与时钟账1.1 MII与RMII的本质差别不只是少四根线MII是16根数据线加2根时钟线百兆下RX_CLK和TX_CLK各跑25MHz一次传输4bit数据。RMII把数据线砍到7根用50MHz参考时钟一次传2bit。表面上看是省了引脚、方便布线实际上是把双倍的数据速率压力转移到了时钟质量上。所以RMII有一个隐含前提50MHz参考时钟必须非常干净、必须同源。很多板子画的时候觉得“不就一个时钟嘛”结果调驱动时始终出现偶发丢包或者接收数据错误最后查来查去都是时钟惹的祸。STM32F407本身以太网MAC是完整的但没有内置PHY必须外接PHY芯片。DP83848是TI原NS的百兆PHY支持MII和RMII两种模式价格不高、资料全、CubeMX里也有现成驱动所以和STM32F407搭配非常常见。如果你的板子不追求引脚极限MII也不是不能用但RMII少的那几根线在四层板上省出的布线空间很可观绝大多数参考设计也都走的RMII我最后选择RMII就是因为它更符合量产板卡的常规做法。1.2 RMII的50MHz参考时钟该从哪里来两条路线对比RMII接口要求PHY和MAC共用一个50MHz参考时钟。在STM32F407上这个时钟有两种主流接法方案时钟来源优点缺点方案A外部50MHz有源晶振同时接到PHY的XT1和STM32的PA1时钟质量高、温漂小、调试简单多一颗有源晶振成本略高方案B25MHz无源晶振接DP83848的XI/XOPHY内部倍频到50MHz从CLK_OUT输出给STM32的PA1省掉有源晶振成本低对晶振本身的质量和PCB布局更敏感方案B是很多开发板的标准做法DP83848内部PLL可以把25MHz倍频到50MHz再输出STM32F407的RMII_REF_CLKPA1直接接收这个时钟即可。我实测下来方案B完全够用但有两点必须注意第一晶振不能随便买那种几毛钱的低端货温漂和起振可靠性在工业环境里会变成大问题。第二PHY和MAC必须共用一个时钟源绝对不能给PHY用一个晶振、给MAC又接一个独立时钟两边频率哪怕都是50MHz也会因为相位和微小频偏导致采样错位表现就是网线能link上但ping包时好时坏大包必挂。调试时用示波器测PA1如果能看到一个稳定、边沿干净的50MHz方波再往下查如果波形抖动明显或者幅值偏低先不要动软件把时钟搞定再说。2. DP83848原理图设计容易画错却很难查的细节2.1 RMII信号完整接线表与RX_ER的处理RMII模式下STM32F407的ETH外设引脚和DP83848的对应关系是关键。我的建议是画原理图时直接对照这张表逐根核对STM32F407引脚功能DP83848引脚方向PA1RMII_REF_CLKCLK_OUT / XT1PHY - MCUPA2MDIOMDIO双向PC1MDCMDCMCU - PHYPA7RMII_CRS_DVCRS_DVPHY - MCUPC4RMII_RXD0RXD0PHY - MCUPC5RMII_RXD1RXD1PHY - MCUPB11RMII_TX_ENTX_ENMCU - PHYPB12RMII_TXD0TXD0MCU - PHYPB13RMII_TXD1TXD1MCU - PHY有一个很容易被忽略的地方DP83848在RMII模式下RX_ER这个引脚要不要接答案是不要接直接悬空或者做下拉处理。原因在于RMII标准里把接收错误信息编码进了CRS_DV信号的扩展脉冲而不是像MII那样用独立的RX_ER线。如果你照搬MII的连接方式把RX_ER硬接到了STM32的ETH_MII_RX_ER反而会让MAC在PHY报出错误指示时丢帧表现为接收路径不稳定。2.2 PHY地址、模式选择、复位和中断引脚的硬件配置DP83848的PHY地址由PHYAD0引脚在复位时的电平决定常见设计是把PHYAD0上拉到3.3V得到地址1。这个地址要和后面CubeMX里配置的PHY Address保持一致很多人在驱动里读不到PHY ID查到最后发现就是地址没对上。模式选择这一块要特别提醒DP83848的MII/RMII工作模式是靠复位瞬间对特定strap引脚的电平采样锁存的不是靠MDIO寄存器在初始化时切换的。画原理图时一定要找到数据手册里的模式配置引脚按RMII模式对应的电平接死。如果硬件上把这些脚随手拉高或者悬空软件再怎么配置也切不到RMII模式上电后PHY跑在MII数据收发自然是乱的。复位电路建议用两种方式叠加一个RC延时复位保证上电自动复位另外把RESET_N引到MCU的一个GPIO上方便软件随时硬复位PHY。复位后的延时一定要给足不要复位完几十微秒就去访问MDIO我一般延时10ms以上。INT引脚是后面热插拔中断的关键。DP83848的INT是开漏输出、低电平有效原理图上必须加一个10k上拉到3.3V否则MCU的EXTI永远等不到中断信号。2.3 电源滤波、偏置电阻、变压器与RJ45的配合DP83848是数模混合芯片3.3V电源要尽量干净。我的做法是每个电源引脚就近放0.1uF陶瓷电容模拟电源VDDA单独加一颗磁珠或小电感做隔离再加大电容储能。电源纹波大时RMII时钟会跟着抖这种问题查起来非常隐蔽。RBIAS偏置电阻是另一个常见的坑。DP83848的RBIAS引脚需要接一颗精度1%的电阻到地典型值是4.7k到4.87k左右。这颗电阻决定PHY内部偏置电流直接影响差分信号的驱动能力。省掉、焊错、或者用普通5%电阻凑合都会导致网口对端无法稳定识别信号。以太网变压器建议选1:1隔离、支持10/100M的型号常见的有集成在网络变压器里的RJ45座子。变压器中心抽头的接法要按器件手册来很多百兆变压器是中心抽头接3.3V再并一个0.1uF去耦电容也有些设计改成经电容接地。TXD/TXD-和RXD/RXD-这两对差分线要做100欧差分阻抗走线尽量等长、尽量短靠近RJ45的地方可以加共模电感和TVS管做防护。25MHz无源晶振的负载电容不是随便配的很多新手直接套18pF结果晶振不起振或者频偏超标。负载电容要按晶振规格书标称值来常见的6~8pF都有PCB上也要把晶振靠近PHY的XI/XO引脚走线越短越好周围铺地隔离。2.4 PCB布局的几条军规关于PCB布局我踩过一次亏总结下来就三条RMII信号线整组尽量短最好控制在50mm以内过孔越少越好RMII_REF_CLK时钟线要远离DCDC电感、开关电源走线如果空间允许可以单独包地底层地平面不要被长走线劈开否则回流路径一断时钟和数据的时序就乱了。画板阶段多花十分钟布局能省掉调试阶段好几个晚上。3. CubeMX配置RMIIIOC文件里那些容易被跳过的点3.1 ETH外设与引脚映射的配置CubeMX里打开ETH外设选择RMII模式Generation后会自动把上面那张表的引脚分配好对应引脚的模式会被设置为复用功能。需要注意PA1作为RMII_REF_CLK输入模式要设成输入不是输出。很多人在这一步习惯性把ETH的引脚全部配成复用推挽输出PA1时钟输入反而不工作。时钟树部分说一下STM32F407的ETH模块挂在AHB1时钟域MAC本身使用AHB1时钟工作但RMII接口的50MHz参考时钟来自外部PHY。不要把PLL48CLK和RMII_REF_CLK搞混用USB那些外设才需要PLL48CLKRMII参考时钟必须从PA1进来。这一步没有配置后面PHY再正常MAC也收不到数据。3.2 DMA、中断与PHY地址设置ETH要正常工作DMA是必须的。CubeMX里把ETH_RX和ETH_TX对应的DMA通道分别使能参数保持默认即可。如果想用中断方式通知收包还需要打开ETH的全局中断。PHY地址默认填1对应前面原理图里PHYAD0接高。如果你的板子PHY地址是0这里必须改成0否则驱动初始化时读PHY ID会失败。MDC时钟分频也要注意MDC不能超过2.5MHzCubeMX会根据AHB1频率自动算分频系数一般不用手动改。生成代码后强烈建议先读一次PHY ID寄存器验证硬件。注册0x02和0x03读出来应该接近0x2000和0x5C90这是DP83848系列芯片的ID。读不到或者读出来全FF/00先查PHY地址和MDIO/MDC接线别急着往下调网络协议栈。3.3 PHY初始化的顺序问题软件初始化顺序我总结成了一个固定序列先通过GPIO拉低RESET_N复位PHY延时10ms以上释放复位然后初始化ETH外设再通过MDIO访问PHY确认ID和BMSR寄存器状态最后再启动DMA和网络协议栈。这个顺序里最容易出问题的是复位后立即访问PHY。PHY内部要从复位状态恢复寄存器访问太早很多命令会被吞掉。我在调试时碰到过一次PHY ID能读到但自协商始终不完成的怪问题最后定位到就是复位释放加延时不够PHY还没准备好就被写入了自协商配置。把延时拉长到10ms重新测试一次稳定通过。4. RMII接收数据错误的实战排查链路4.1 先给故障分类能link但ping不通和ping通但大包错不是一回事RMII接收数据错误这个关键词太常见了但具体现象千差万别。我把自己遇到过的几类整理成一张表方便大家对照现象大概率原因排查方向能link但完全ping不通PHY模式不对、时钟不同源、MDIO地址错先读PHY ID和BMSR小包通、大包必丢时钟质量问题、PCB阻抗不连续看REF_CLK波形、查差分走线热插拔几次后网络假死link事件处理不完整、DMA未复位检查热插拔中断流程只有发送或只有接收RMII某根信号线虚焊、RX_ER误接对照2.1接线表逐根测量发送正常接收CRC错CRS_DV时序和采样边沿问题查时钟、CRS_DV布线这个表不是为了省事而是提醒你错误现象本身能帮你快速缩小范围别一上来就怀疑驱动代码。4.2 从RMII时序和RX数据面确认故障层级如果确认MDIO能读到PHY ID、BMSR显示link up但PC端收不到板子的数据问题就集中在RMII数据面。用示波器看PA1的50MHz时钟再看CRS_DV在接收时有没有正常产生高电平脉冲。如果PHY收到数据但CRS_DV没有反应说明RXD信号线或者PHY配置有问题如果CRS_DV正常但MAC收不到问题就在STM32F407这一侧。一个很经典的RMII接收错误来源是发送数据时CRS_DV状态异常。RMII标准下CRS_DV在发送期间也会被PHY拉高表示载波侦听这是正常行为MAC会区分。但如果PHY和工作模式不匹配或者CRS_DV信号线被错误地上拉/下拉MAC就会把发送期间的载波信号误判成接收数据收到的全是被截断的坏包。4.3 用MDIO寄存器定位到配置层问题MDIO寄存器是排查RMII问题最好的入口。我每次调试网口都会先读这几个寄存器0x02/0x03PHY ID确认MDIO通路和PHY地址寄存器0x01BMSRbit2Link Status确认物理链路寄存器0x01 bit5Auto-Negotiation Complete确认自协商完成寄存器0x00BMCRbit12Auto-Negotiation Enable如果BMSR显示link up但自协商没完成多半是PHY配置被外部干扰如果link状态在插拔后不更新那问题很可能不在寄存器配置而在中断处理流程。还有一个容易踩的坑通过MDIO写BMCR的Reset位软复位PHY后RMII接口会有短暂的不稳定期此时如果MAC还在收发数据就会产生一堆CRC错误。软复位之后一定要等自协商完成再重新初始化MAC的DMA和描述符不能复位完立刻把链路置为up。4.4 时钟与PCB层面的根因验证如果寄存器全部正常数据面还是报错基本就锁定在时钟和PCB上了。用示波器逐个量PA1的RMII_REF_CLK、CRS_DV、RXD0/RXD1重点看时钟上有没有叠加周期性噪声。低速DCDC的开关噪声很容易耦合到时钟线上导致接收采样不稳定。PCB层面的问题我就遇到过一种特殊场景RMII信号线在走线时被顶层的一根电源线跨过导致参考平面不连续百兆速率下偶发错帧。后面调整走线把信号线全部走同一层并保证底层完整地平面问题消失。这种时间和成本都花在排查上的经历提醒我画板时不能只求“能连通”而忽略信号完整性。4.5 热插拔后的稳定性和网口假死RMII接收数据错误还有一个高频触发场景就是热插拔。网线拔出再插入如果驱动没有正确感知link状态变化lwIP侧的网络状态不会被更新结果表现为插拔几次后ping不通。很多项目直接把链路状态做成静态up热插拔后外部交换机都已经重新协商好了板子还守着旧的ARP表项和连接状态自然不会通。解决思路就是在硬件上给PHY的中断引脚接到MCU用中断方式感知link up/down而不是靠应用层周期性去读状态。这也正好对应了本篇标题里的热插拔中断部分。5. 热插拔中断DP83848的状态变化怎么变成MCU的中断5.1 为什么轮询Link状态不是好方案最简单粗暴的做法是MCU每100ms通过MDIO读一次BMSR看看link状态有没有变化。短期内能跑但有两个问题一是lwIP收到上层命令时可能还在轮询周期内链路恢复的响应时间不可控二是轮询本身占用MDIO总线和驱动初始化、PHY配置等操作撞在一起时要处理互斥。做产品的话还是建议把PHY的link change事件做成真正的硬件中断。5.2 DP83848的中断寄存器MICR和MISRDP83848提供了两组扩展寄存器来控制中断MICR寄存器地址0x11和MISR寄存器地址0x12。MICR负责中断输出使能MISR记录具体的中断事件来源。初始化的时候我通常在PHY配置完成后执行这几步写MICR打开中断使能和中断输出使能把INT引脚变成可用的中断线。写MISR把Link Status Change事件使能这样网线插拔时INT引脚会产生一个下降沿。清掉MISR中可能残留的历史中断状态避免上电瞬间的link抖动误触发一次中断。INT引脚本身是开漏、低有效原理图上已经加了10k上拉。MCU侧配置成下降沿触发的EXTI即可。5.3 STM32端EXTI和ISR的处理细节STM32端把DP83848的INT引脚接到一个支持EXTI的GPIO上。以下降沿触发进入中断回调后千万不要急着去更新lwIP状态。先把MISR读出来确认是Link Status Change事件然后读取BMSR的link状态位再做一个软件防抖隔10到20ms再读一次BMSR两次结果一致才认为网线状态确实变了。为什么要防抖因为网线插拔的瞬间PHY的内部状态变化会有短暂抖动有时候link寄存器在几个毫秒内会在0和1之间跳变。不做防抖就会出现插入网线后先触发一次link up、紧接着又触发一次link downlwIP的状态被来回切换最终表现为网络不稳定。防抖确认后再做对应的协议栈操作link down调用netif_set_link_down通知协议栈链路断开。link up等待自协商完成BMSR bit5再调用netif_set_link_up。如果需要重新获取IP可以在link up后触发DHCP续租或重新请求。这样做的核心价值在于lwIP会在链路恢复后重新发ARP报文、处理新的IP/网关状态热插拔之后不再出现假死。5.4 复用LED_LINK做热插拔检测的偷懒方案有些工程师不做DP83848的INT中断配置直接把LED_LINK引脚接到MCU GPIO做轮询。LED_LINK是PHY输出的link状态直通信号电平会随link up/down变化不经过中断寄存器。优点是硬件简单缺点是只能轮询、无法区分速率变化等事件而且LED_LINK的极性每个产品手册可能不同有的是link up时输出高有的是低接线前要查数据手册。如果项目对网络响应要求不高LED_LINK方案可以接受如果要做完整的热插拔感知、或者将来要扩展速率变化监测、远端故障等功能还是老老实实走INT中断比较划算一次性把中断流程搭好后面加功能只是改寄存器的事。6. 几个实测后觉得值得写进笔记的经验6.1 RMII真的不是“什么晶振都能跑”第一版样板为了省成本用了普通规格的25MHz无源晶振常温下看起来没问题一到低温环境就开始出现ping大包丢包的情况。示波器看REF_CLK频率漂移和抖动明显变大PHY在某些温度点下的时钟余量接近临界。换成一颗低相噪、温漂指标更好的晶振后问题消失。RMII的50MHz参考时钟质量直接决定了整个链路的稳定性上去省几毛钱后面可能要花几天来排查。6.2 仿真软件里没有STM32F407可以先做硬件验证经常有人在社区问Proteus之类仿真软件里没有STM32F407能不能先把代码逻辑跑通。我的个人体会是STM32F407加DP83848这种RMII时序强相关的东西仿真帮助非常有限。RMII时钟的相位关系、MDIO时序、PHY的自协商状态机的动态行为仿真环境很难模拟出真实芯片的电气特性和寄存器细节。用它验证业务逻辑还行但最终还是要上板子实测。画样板时留好测试点比仿真省钱省力得多。6.3 画板时预留的测试点关键时刻能救命调试网口我强烈建议在原理图上为这几处预留测试点PA1的RMII_REF_CLK、MDIO、MDC、PHY_RESET、以及DP83848的INT引脚。哪怕只是焊盘也能救急。我碰到过一次MDIO怎么都读不到PHY ID最后就是靠万用表测测试点发现MDC信号没有从MCU出来问题出在STM32的GPIO配置上而不是PHY芯片。6.4 拆机料和翻新料的坑DP83848这类芯片市场上有一段时间假货、翻新料很多。如果是在非正规渠道采购的上板后CRC错、热插拔死机这类问题会突然变多。排查时如果所有电路参数都正常软件流程也无可挑剔可以怀疑一下芯片本身。换一颗正规渠道的料试试往往问题就消失了。焊接质量也要检查QFP封装引脚间距小桥连、虚焊在网口这种高速信号下会被放大成各种随机故障。6.5 多次热插拔后MAC DMA的复位处理最后分享一个热插拔场景下的实际坑。我的板子做完热插拔中断后前几次插拔都正常连续插拔十几次后lwIP开始不响应。排查发现并非link状态错误而是MAC的DMA描述符在多次快速插入/拔出中被协议栈的收发操作搅乱了DMA停在异常状态但ETH中断标志没有被正确清掉。解决方式是在每次link up事件触发、协议栈恢复链路之前做一次ETH DMA的软复位重新初始化描述符然后再启动接收和发送。这一行代码加进去后连续插拔几百次都没有再出现假死。这块板子后来量产了插拔几千次没有复现问题。整个过程回头看最贵的就是原理图阶段那几根被随手拉高、随手悬空的引脚——它们决定了后面所有软件调试的起点。
返回列表