以太网接口这个东西,做嵌入式或者硬件开发的兄弟基本都躲不开。不管你是玩STM32、FPGA还是Linux驱动,只要板子要上网,就绕不过MAC、PHY、MII、RMII、GMII、RGMII这一串名词。很多新手第一次看芯片手册,翻到以太网章节直接懵了:MAC和PHY到底谁管谁?MII、RMII、RGMII又是什么鬼?其实理清这几个概念,整个以太网硬件链路就通了一大半。这篇文章我就以最直白的方式,把这几个核心概念的关系、接口定义、以及实际工程中的设计要点一次性讲透。
这篇文章适合三类人看:一是刚开始接触以太网硬件设计的嵌入式工程师,二是需要调试网络不通问题的软件/硬件开发,三是对计算机网络底层协议感兴趣的爱好者。文章不会堆砌术语,每个概念我都会拆开揉碎了讲,同时会结合我在实际项目中踩过的一些坑。
1. 为什么需要把以太网拆成MAC和PHY?
很多人一开始都有个疑问:网口不就一根线插上去就行吗,为什么要分MAC和PHY两个部分?这个问题的答案,要从以太网的分层设计说起。
以太网工作在OSI模型的物理层和数据链路层。靠近CPU和软件那一层,负责组帧、解帧、地址过滤这些逻辑操作的部分,叫MAC(Media Access Control,介质访问控制层)。靠近网线那一侧,负责把数字信号转换成能在网线上传输的模拟电平、实现编码解码、载波侦听、自协商这些物理操作的部分,叫PHY(Physical Layer,物理层)。MAC和PHY之间需要标准化的接口来传数据,这就是MII家族接口存在的意义。
从一次实际的数据发送流程来看,你会更清楚两者的分工。假设你的STM32要发一个UDP包,CPU先把数据交给MAC内核,MAC会做这些事情:加上以太网帧头(目的MAC地址、源MAC地址、类型/长度字段),计算并填充帧校验序列FCS,然后按照MII接口的时序,把数据一位一位(或者说一个Nibble一个Nibble)发送给PHY。PHY拿到这些并行数据后,要做的事情完全不同:它要按物理层协议做编码(百兆是4B/5B编码,千兆是8B/10B编码),然后把编码后的比特流转换成差分信号,经过网络变压器耦合到RJ45接口,最终通过网线传出去。接收方向正好反过来。
这个分工其实很像一个快递公司。MAC就是前台客服,负责接单、填写面单、核对地址(帧头、校验);PHY就是运输车队,负责把包裹实际送到公路上(物理介质)。前台不需要关心汽车怎么开,车队也不需要关心面单怎么写,两边只需要约定一个交接标准就行——这个交接标准就是MII。
1.1 从一次数据发送说起
为了更直观地讲解,我以最常见的STM32F407+LAN8720A组合为例。STM32F407内部集成了MAC,但PHY需要外接,比如Microchip的LAN8720A或者国产的YT8512C等。MAC和PHY之间通过RMII接口连接,RMII是MII的精简版,后面会细讲。
当应用层要把“hello”这几个字节发给远端设备时,数据流向是这样的:
- 应用层把数据传给TCP/IP协议栈,协议栈封装成IP包和UDP/TCP包。
- 协议栈通过DMA或寄存器方式,把整个IP包交给MAC内核。
- MAC内核会自动在IP包前面加上14字节的以太网头(目的MAC、源MAC、Type),在末尾加上4字节的CRC校验,形成一个完整以太网帧。
- MAC通过RMII接口,以2位数据宽度并行地上传帧内容给PHY。
- PHY收到比特流后,进行4B/5B编码、加扰、差分信号转换,最后通过MDI引脚送出到网络变压器。
接收方向正好反过来:PHY从网线收到模拟信号,先做解码、去扰,恢复出数字比特流,再通过RMII接口交给MAC,MAC做地址过滤和CRC校验,确认无误后把有效载荷提交给协议栈。
所以调试以太网时,第一步就要明白问题出在哪一段:如果MDIO能正常读写PHY寄存器、Link状态是up,但MAC收不到数据,问题多半在MAC配置或者接口时序上;如果Link都不up,物理层的问题更大。
1.2 MAC和PHY各自的职责边界
把MAC和PHY的职责彻底分开理解,对后续调试验证非常关键。我整理了一个对照表,方便大家平时查阅。
MAC层负责的内容:
- 以太网帧的封装和解封装:添加/移除帧头、FCS校验。
- 地址管理:源MAC地址填充、目的MAC地址过滤(单播、广播、组播)。
- 流控:半双工模式下的CSMA/CD(载波侦听多路访问/冲突检测),全双工下的802.3x流控帧。
- 错帧检测:CRC校验失败则丢弃该帧。
- 与上层协议栈的接口:DMA描述符、中断、缓冲区管理。
PHY层负责的内容:
- 数据编码:百兆的4B/5B、千兆的8B/10B编码,以及编解码的加扰/解扰。
- 信号调制:把数字信号转换成适合在双绞线上传输的MLT-3电平(百兆)或4D-PAM5(千兆)。
- 自协商:和对端设备协商速率和双工模式,确定双方能支持的最高工作模式。
- 载波侦听和冲突检测:这是CSMA/CD协议在物理层的具体实现。
- 线路时钟恢复:从接收信号中恢复出时钟。
- 提供MDIO/MDC管理接口,供CPU读写寄存器配置PHY模式、查询状态。
再补充一点,现在的MAC和PHY芯片有很多集成方案,比如单片机的MAC+集成了PHY的交换机芯片、SoC内部集成MAC+外挂PHY、或者一颗芯片同时集成MAC和PHY(比如WIZnet的W5500就是MAC+PHY+TCPUDP协议栈全集成)。虽然集成度不同,但只要涉及以太网数据收发,MAC和PHY各司其职的基本架构是不变的。理解这个架构,后面无论换什么平台,思路都能快速迁移。
2. MII接口:经典百兆时代的连接方式
了解了MAC和PHY的分工,接下来要看它们之间怎么对接。IEEE 802.3规范定义了一系列MAC与PHY之间的标准接口,最早、最经典的就是MII(Media Independent Interface,介质无关接口)。之所以叫“介质无关”,是因为MAC通过MII连接PHY后,PHY可以接双绞线、光纤等不同介质,MAC不需要关心具体物理介质是什么。
MII接口是为100Mbps以太网设计的,数据总线宽度4位,时钟频率25MHz。4bit × 25MHz = 100Mbps,刚好匹配百兆速率。如果工作在10Mbps模式,时钟降到2.5MHz。MII接口的信号总数大概有16根左右,按功能可以分成四组:发送数据组、接收数据组、管理接口组、状态指示组。
- 发送数据组:
- TXD[3:0]:4位并行发送数据。
- TX_EN:发送使能信号,高电平表示MAC正在发送数据。
- TX_CLK:发送参考时钟,由PHY提供,100M模式下25MHz,10M模式下2.5MHz。
- TX_ER:发送错误指示,一般不用,接地或接低电平即可。
- 接收数据组:
- RXD[3:0]:4位并行接收数据。
- RX_DV:接收数据有效信号,高电平表示PHY正在向MAC送数据。
- RX_CLK:接收参考时钟,由PHY从接收线路中恢复出来,和发送时钟可以不同步。
- RX_ER:接收错误指示,PHY在接收过程中发现编码错误或信号异常时拉高。
- 管理接口组:
- MDC:管理接口时钟,由MAC主动输出,最高频率一般不超过2.5MHz(有些PHY支持更高)。
- MDIO:管理接口数据线,双向,用于读写PHY寄存器。
- 状态指示组:
- CRS:载波侦听信号,PHY检测到介质上有活动时拉高。
- COL:冲突检测信号,半双工模式下检测到冲突时拉高。
2.1 MII信号线定义与原理
MII接口里,有两根信号我觉得值得专门强调,因为很多第一次调试的人会栽在它们手里:TX_CLK和RX_CLK。
TX_CLK不是MAC给出的,而是PHY提供的。这跟很多人直觉不同,因为通常认为发送时钟应该由发送方决定。实际上以太网的发送时钟来源于PHY内部的25MHz晶体或参考时钟,PHY把这个时钟送给MAC,MAC在TX_CLK的上升沿进行TXD数据的声明和更新。所以硬件设计上,TX_CLK必须由PHY引出再接回MAC,不能简单用有源晶振而不用PHY的时钟输出。在实际项目中,我见过有人图省事把PHY的CLK_OUT脚悬空,结果MAC完全收不到发送时钟,数据根本发不出去。
RX_CLK同样由PHY提供,但这个时钟是从接收线路上恢复出来的,由PHY内部的CDR(时钟数据恢复)电路锁定输入比特流后生成。当网线上没有信号时,RX_CLK仍然会维持运行,只是频率可能漂移在25MHz附近,可以用示波器观察确认是否有稳定的25MHz方波来初判PHY工作状态。
另一个要注意的是MDIO/MDC管理接口。MDIO本质上是个同步串口,类似I2C但更简单,MAC作为主机主动发起读写,MDIO引脚是双向的。PHY芯片有5位PHY地址(通常通过硬件引脚配置),MDIO帧里包含起始位、操作码、PHY地址、寄存器地址、数据等。调试以太网时,我强烈建议第一步先写一个简单的MDIO读写函数,能成功读写PHY的寄存器(比如寄存器0的PHY ID或寄存器1的状态位),基本就能判定链路方向问题。
2.2 GMII:迈向千兆的并行之路
百兆之后是千兆。MII的4位数据总线在125MHz时钟下最多只能跑到100Mbps,要上1000Mbps,最简单的思路就是把数据总线加宽或者把时钟提高。IEEE 802.3ab定义了GMII(Gigabit Media Independent Interface,千兆介质无关接口)来对接千兆以太网。
GMII的数据总线宽度从4位扩展到8位,时钟频率125MHz,8bit × 125MHz = 1000Mbps。发送方向新增加了一根GTX_CLK,和MII不同的是,GTX_CLK由MAC提供给PHY。这一点很关键,千兆模式发送时钟由MAC直接送出,PHY只在发送数据时根据GTX_CLK同步,而接收方向仍然是PHY恢复时钟给MAC,也就是RX_CLK。
GMII的收发信号和在MII基础上都从4位变成8位:TXD[7:0]、RXD[7:0],其他控制信号TX_EN、TX_ER、RX_DV、RX_ER、CRS、COL保持不变。接口引脚总数在24根左右。
从硬件设计角度,GMII最大的问题是引脚占用太多,24根信号线对PCB布局和BGA封装MCU/FPGA来说压力很大。而且并行8位数据在125MHz频率下的等长布线、串扰、时序裕量都比较头疼,所以GMII虽然速率够,但实际应用并不如预期的广泛,更多被RGMII这种精简方案取代。
值得一提的是,GMII接口还支持100Mbps和10Mbps的工作模式。在这两种模式下,数据总线降到4位,时钟降到25MHz或2.5MHz,控制信号也退化成类似MII的表现。这样的兼容设计,让一颗千兆PHY可以向下兼容所有标准以太网速率,但MAC侧的配置要跟着模式切换。
3. RMII和RGMII:引脚减半的实用派
GMII引脚太多,MII引脚也不少(16根),对于很多引脚紧张的MCU和入门级交换机芯片来说很不友好。于是出现了两个广受欢迎的简化接口:RMII(Reduced MII,精简MII)和RGMII(Reduced GMII,精简GMII)。
RMII是为百兆以太网设计的,把MII的16根引脚缩减到7-8根。RGMII是为千兆以太网设计的,把GMII的24根引脚缩减到12根。这两个接口的核心理念就是:要么通过减少数据线宽度换更高时钟频率,要么通过双沿采样来让同样数量的引脚跑双倍速率。
3.1 RMII如何用一半引脚搞定百兆
RMII的引脚分配如下:TXD[1:0](2位发送数据)、TX_EN(发送使能)、RXD[1:0](2位接收数据)、CRS_DV(载波侦听/数据有效合并信号)、REF_CLK(50MHz参考时钟)、MDC、MDIO。如果不需要管理接口,甚至可以只留前6根。
关键点在于REF_CLK。RMII在发送和接收方向共用同一个50MHz参考时钟,2位 × 50MHz = 100Mbps,完美匹配百兆。这个REF_CLK可以由外部晶振/有源晶振提供,也可以由PHY的CLK_OUT引脚提供。在STM32+LAN8720A的设计里,通常是PHY提供50MHz时钟输出到MCU的RMII参考时钟引脚,当然也可以反过来用MCU生成50MHz给PHY。有一点要非常小心:REF_CLK必须送到MAC和PHY两边的对应引脚,而且两个芯片的REF_CLK必须同源、同相。如果两边时钟不是同一个源,或者走线长度差异过大导致相位偏差大,通信就会不稳定。
CRS_DV是另一个需要特别关注的点。RMII里把MII的CRS(载波侦听)和RX_DV(接收数据有效)合并成了一个信号CRS_DV。这个信号在介质空闲时是低电平,当介质上有数据时同步拉高。对于10Mbps半双工模式,CRS_DV的行为会有点复杂:数据不是连续发送的,CRS_DV会在介质上出现载波时先拉高,然后在数据有效时再拉高一次。有些MCU的RMII接口完全用简化方式处理,只看高脉冲的宽度而忽略中间的翻转,所以要注意不同芯片手册对CRS_DV的时序定义可能略有不同,配置时一定要看对应的参考手册。
还有一个容易忽略的地方:RMII的半双工模式下,CRS_DV的时序会给流控带来麻烦,所以实际应用中RMII更多被配置为全双工模式。全双工下CRS_DV直接等价于RX_DV,逻辑简单很多。
3.2 RGMII的双沿采样与延时调节
RGMII把GMII的8位数据总线减半成4位,时钟仍然是125MHz,但采用DDR(Double Data Rate,双沿采样)技术,在时钟的上升沿和下降沿各采样一次,4位 × 125MHz × 2 = 1000Mbps。可以说RGMII是GMII的引脚减半版本。
RGMII信号列表:TXD[3:0]、TX_CTL(发送控制信号,合并了TX_EN和TX_ER)、TX_CLK(发送时钟)、RXD[3:0]、RX_CTL(接收控制信号,合并了RX_DV和RX_ER)、RX_CLK(接收时钟)、MDC、MDIO。总引脚数约12根。
TXD和TX_CTL的时序约定是:上升沿发送TXD[3:0]和TX_CTL,下降沿发送TXD[7:4]和TX_CTL的扩展位(比如错误指示位)。接收方向类似:上升沿接收RXD[3:0]和RX_CTL,下降沿接收RXD[7:4]和RX_CTL的扩展位。
RGMII在实际工程里最大的坑就是时钟和数据之间的相位关系。因为数据在双沿都被采样,接收端(MAC侧)必须在正确的时刻采样数据。理想情况下,数据由发送端在时钟沿跳变处更新,接收端应该在两个沿的中间采样才最稳。但RGMII的时钟和数据往往都是由PHY或MAC同时送出的(取决于方向和模式),数据线和时钟线如果等长设计,到达接收端的相位几乎一致,这样在采样沿上数据可能正好在翻转,导致采样失败。
所以为了规避这个问题,标准RGMII规范要求发送端在发送时钟的上升沿和下降沿附近切换数据,但同时给接收端提供一定的时钟偏斜(clock skew)。工程上的常见做法有三种:一是在PCB上故意让时钟走线比数据线长一段,引入相位延迟;二是利用PHY芯片内部的可调延时寄存器,比如在TX_CLK或RX_CLK路径上增加1.5ns~2ns的延时(很多PHY像RTL8211、YT8531都有类似寄存器);三是使用FPGA或MAC内置的IDELAY等原语做动态调整。我调试过的很多项目最终都是通过PHY寄存器调延时解决的,因为在PCB上做蛇形线反复打样的成本高,见效慢。
4. 实操选型与硬件设计要点
理解接口协议之后,实际选择以太网方案就轻松很多。不同项目需求不同,看下面这个对比表,心里大概就有底了。
| 接口 | 数据宽度 | 时钟频率 | 引脚数(约) | 最高速率 | 典型应用场景 |
|---|---|---|---|---|---|
| MII | 4位 | 25MHz | 16 | 100Mbps | 老式MCU、工业控制板 |
| RMII | 2位 | 50MHz | 7-8 | 100Mbps | STM32、小封装Linux板卡 |
| GMII | 8位 | 125MHz | 24 | 1000Mbps | FPGA全功能设计、交换机芯片 |
| RGMII | 4位 | 125MHz DDR | 12 | 1000Mbps | 主流SoC、千兆PHY、FPGA |
选型时除了带宽和引脚数,还要看工作电压、PHY芯片的封装、功耗、温度范围、是否支持自协商、MDC/MDIO的时序、以及是否有配套驱动。现在的潮流是国产PHY芯片逐渐普及,比如裕太微YT8512C(百兆)、YT8531(千兆)、景略JL1101等,性价比和供货稳定性都不错;微芯LAN8720A、瑞昱RTL8211F、美满88E1512这些也仍然是主流选择。
4.1 不同接口的选型考量
如果是STM32F4/F7/H7系列做百兆以太网,首选RMII接口配一颗百兆PHY,因为它引脚少,而且STM32的RMII时钟配置相对简单,可以直接用PHY的50MHz输出作为MAC的REF_CLK。如果要做千兆,最常用的就是RGMII接口,搭配一颗千兆PHY如RTL8211F或YT8531。大多数Linux开发板(如i.MX6ULL、RK3568)的以太网接口都提供了RGMII模式,驱动里的fifo-mode、tx-internal-delay这些参数就是围绕RGMII时钟延时的。
FPGA设计要灵活一些。如果你在FPGA里用三速以太网IP核(比如Xilinx TEMAC或Intel TSE),MAC到PHY之间既可以出GMII也可以出RGMII。我的个人建议是:如果引脚充裕且对时序要求极致,直接GMII最简单,因为只需要在同一边沿采样,不存在DDR的问题;如果引脚紧张或者需要外接多速率PHY,选RGMII但在PHY寄存器里打开内部延时输出。
另外一个容易忽略的选型点是PHY的时钟源结构。有的PHY用25MHz外部晶振(例如LAN8720A),内部通过PLL倍频生成50MHz REF_CLK输出;有的PHY直接用50MHz外部时钟输入(例如RTL8211F常用25MHz石英晶体生成125MHz)。这会影响你的系统时钟设计。如果PHY没有可用的时钟输出引脚给MAC,那MAC侧需要外挂自己的参考时钟源,两边必须确保同步源正确。
4.2 硬件设计中的常见坑
我在好几个项目里调试以太网时都遇到过硬件设计层面的低级问题,整理几个最常见的坑,大家可以直接当避坑清单用。
第一个坑是PHY复位时序。很多PHY芯片复位之后需要一小段时间(通常是几毫秒到几十毫秒)来完成内部校准和寄存器初始化,在这个时间窗口内MDIO是不响应任何访问的。如果你在系统刚上电、主控还没来得及等待复位完成就去读PHY寄存器,极大概率读到0xFFFF。解决方法是:硬件复位信号由主控GPIO控制,初始化流程里先拉低复位引脚再拉高,然后延时至少10ms再访问MDIO。有些PHY还需要外部有源晶振先起振稳定再释放复位,这个时序也要查数据手册。
第二个坑是REF_CLK的提供方式。前面提到RMII必须有一个50MHz的REF_CLK同时给MAC和PHY。如果这个时钟由PHY的CLK_OUT提供,而MAC又要求REF_CLK同源,那么设计时必须保证CLK_OUT连接到MAC对应的引脚上,且两段走线尽量等长。如果PHY没有输出时钟功能,就要用外部有源晶振分出一个时钟同时作为MAC和PHY的时钟源。有的PHY(例如YT8512C)也可以由MAC侧向PHY提供50MHz,这种模式下要把PHY的REF_CLK引脚方向配置对,否则PHY一直起不来。
第三个坑是RGMII的时钟延迟寄存器配置。这个问题在千兆调试中非常普遍。不同厂商的PHY,内部延时控制位的位置和默认值都不一样。比如有些PHY默认接收时钟带1ns左右延时,有些默认不代,你需要通过MDIO把RXC延时打开或关闭。如果完全不配延时,运气好可能连通,但运行一段时间在高温低温下就会随机丢包;运气不好一帧都收不到。我建议在调试阶段先把PHY寄存器的延时调到中间值,然后连续PING大包测试,再逐一微调。
第四个坑是网络变压器的接法。RJ45座子里如果自带隔离变压器,注意中心的抽头(center tap)是接电源还是接地,跟PHY的供电电压有关。典型的电压驱动型PHY需要把变压器中心抽头接到3.3V或者2.5V,而电流驱动型PHY则需要接电容到地。接错了直接导致链路信号幅度不对甚至完全不通。调试时用示波器量PHY的差分输出线上有没有正常的眼图,就能很快判断变压器连接是否正确。
第五个坑是MDIO的上拉电阻和电平转换。MDIO是一个开漏/开集输出的双向信号,必须接一个上拉电阻,一般1kΩ~10kΩ,具体值按PHY手册要求来。如果MDC/MDIO的电平和主控IO不一致,还要做电平转换。很多国产PHY芯片的门槛电压比较严格,3.3V供电时MDIO高电平要足够高才能识别,上拉电阻太小会增加功耗但驱动能力强,太大的话翻转时间过长,导致读写不稳定甚至超时。
5. 常见问题与排查技巧实录
调试以太网和调试串口完全不是一个难度等级,因为牵涉到的环节更多:电源域、复位、时钟、MDIO、接口时序、PHY配置、MAC配置、协议栈、路由。任何一个环节出问题,表现都是“网络不通”。所以排查时一定要有顺序,从上电的第一件事开始逐步验证。
5.1 以太网不工作的排查顺序
我个人的排查顺序几乎固定,按照这个顺序排查,大部分问题都能在30分钟内定位到模块。
- 确认电源和时钟。用万用表确认PHY的供电电压正常(3.3V或2.5V/1.8V,具体看芯片),再用示波器确认PHY的时钟或REF_CLK有正确的方波输出。这一步如果没过,后面全白搭。
- 检查PHY复位。确认RESET_N引脚拉高的时间晚于供电稳定时间,并且有足够的上电延迟。如果复位引脚被悬空,要确认PHY是否有内部上电复位电路,很多芯片没有,必须外部控制。
- 确认MDIO读写正常。写一个简单的MDIO读函数,读取PHY的寄存器0(PHY ID高16位)或寄存器1(状态和控制寄存器),看能否读到有效值。读不到就检查MDC/MDIO接没接对、上拉电阻有没有、PHY地址配置对不对。
- 确认Link状态。读取PHY寄存器1的bit2(Link Status),如果Link是up,说明物理层协商成功。Link为down的话,检查网线、对端设备、变压器、PHY的自协商使能位。
- 抓MAC-PHY接口波形。用逻辑分析仪抓MII/RMII/RGMII的信号。重点看:MAC是否在向PHY发送数据(TX_EN/TX_CTL是否有动作),PHY是否在向MAC发送数据(RX_DV/RX_CTL是否有动作)。如果MAC发数据但PHY没收到链路数据,问题在接口时序或PHY配置;如果PHY收到了网线数据但MAC没收到接口数据,问题在接口方向或MAC配置。
- 看MAC和协议栈状态。在Linux下用ifconfig、ethtool查看网卡UP带没带,Link检测正不正常;在STM32裸机或RTOS下查看MAC的DMA状态寄存器有没有RX buffer溢出、FIFO错误、CRC错误等计数。
这个顺序的逻辑是自下而上:先保证物理介质和PHY工作正常,再保证MAC到PHY的通道通畅,最后才去排查协议栈和应用程序。很多人上来就抓包、查路由,绕了一大圈发现是PHY的复位引脚没接好,太浪费时间了。
5.2 接口波形与信号完整性
在你怀疑MII/RMII/RGMII接口时序有问题的时侯,逻辑分析仪和示波器是你最好的朋友。但要注意,不同接口的信号观测方法完全不同。
对百兆MII/RMII接口,用普通逻辑分析仪就够了,采样率不用太高,25MHz/50MHz的信号100MHz采样率也能看个大概。主要观测:TX_CLK/REF_CLK是否稳定、TX_EN是否有高电平输出、TXD数据线上是否有周期性数据变化。如果MAC发PING请求,用逻辑分析仪抓TX_EN,应该能看到脉冲波形;如果PHY收到回应,抓RX_DV,应该能看到对应的脉冲。两边都有,说明MAC-PHY数据通道没有问题。
对RGMII这类DDR接口,普通逻辑分析仪就不太够用。RGMII的时钟是125MHz,数据在双沿翻转,要求逻辑分析仪至少500MHz以上采样率,最好1GHz采样。实际观测时注意:用示波器看RXC和RXD的相位关系,理想状态下数据切换点在时钟沿之后1ns左右,接收端采样点在数据稳定窗口的中间。如果你能测量到RXC和RXD的相对延迟,很多问题就一目了然。有条件的话,打开示波器的眼图模式,观察RXD信号的眼图是否张开得够大。眼图太小、眼睛糊成一团,大概率是PCB走线太长、阻抗不匹配、或者参考时钟抖动过大。
信号完整性方面的几个经验之谈:MII/RMII信号线一般要求走线阻抗控制在50Ω单端(或者差分对100Ω,看接口定义),信号线之间尽量拉开间距减少串扰。RGMII数据线必须在PCB等长,长度差控制在50mil以内比较保险。时钟线尽量包地处理,减少EMI。串阻方面,MAC和PHY之间靠近发送端串22Ω或33Ω电阻,可以有效抑制过冲和振铃。这些都是我在画PCB时积累的通用做法,不是死板规定,具体值要根据实测调整。
6. 调试中的几个实战心得
最后分享几个我调试以太网时积累的实战心得,可能比较零散,但都是真金白银换来的经验。
第一点是关于PHY的寄存器读写。写MDIO的时候,第一次读PHY寄存器最好打印原始值,不要做任何位运算。有些PHY在未上电或未复位成功时读回来是全FF,有些读回来是0。通过原始值就能判断基础状态。真正跑通MDIO后,再去理解每个寄存器位的含义。
第二点是关于PHY的自协商模式。大多数应用场景建议开启自协商,因为对端设备可能是百兆交换机也可能是千兆交换机,自协商能让两侧自动协商到双方都支持的最高速率。但有些工业现场需要固定百兆全双工,关闭自协商,强制配置速度。遇到强制模式还要注意:PHY芯片通常要求配置速度模式后再做软复位才能生效,忽略这个复位会导致配置不生效。
第三点是关于RGMII的TX延时。以前我调试一个FPGA千兆项目,FPGA内部MAC通过RGMII接RTL8211F PHY,现象是FPGA能收到网线来的数据(RX方向OK),但PHY发出去的数据MAC收不到(TX方向NG)。后来查数据手册发现,RTL8211F的TX时钟和数据路径可以通过寄存器分别加延时,而默认配置下TX延时是没有打开的。我在PHY寄存器里打开了TX_CLK的延时(增加约2ns),问题立刻消失。这个案例让我深刻体会到,不同厂商PHY的RGMII延时默认值差异很大,买来芯片先查寄存器默认值,不要盲目套用经验值。
第四点是关于PCB布线调试。如果板子上以太网不通,又找不到逻辑问题,建议先用飞线把MAC的TX/RX信号跨接到一个开发板上(比如另一个STM32开发板),做一个最小闭环测试。这样可以排除你自己PCB布线问题的干扰,直接验证MAC+PHY+驱动的配置是否正确。等这个最小系统跑起来了,再反查PCB设计,思路会清晰很多。
以太网调试是个系统工程,但核心概念并不复杂。把MAC和PHY的职责、接口的信号时序、关键时钟的来龙去脉搞清楚,再配合MDIO寄存器做链路验证,绝大多数问题都能在半小时内定位。这篇文章相当于把地基给你打好了,后续无论是深入底层协议,还是移植到不同芯片平台,都能少走很多弯路。