干了这么多年嵌入式,跟以太网打交道是躲不开的。做板子、调驱动,一涉及到网络通信,mac和phy之间那几根线怎么接、用什么接口、时序怎么对,总能把人折腾几轮。MII、RMII、GMII、RGMII这几个缩写看着相似,实际用起来差别很大,选错了轻则性能上不去,重则压根不通。这篇文章就专门把这几个接口掰开揉碎讲清楚,从信号定义、时序机制到实际调试中的坑都过一遍,给正在选型或者正在调板子的朋友一个参考。
1. 为什么MAC和PHY之间需要这几种接口:先理解连接的本质
要搞清楚MII、RMII、GMII、RGMII到底在解决什么问题,得先回到以太网硬件架构的基本盘上。一块以太网卡功能上分成两部分:MAC(媒体访问控制层)和PHY(物理层)。MAC负责组帧、寻址、CRC校验这些数据链路层的活,PHY负责把数字信号变成模拟信号扔到网线上,同时处理编码、时钟恢复、载波侦听这些物理层的脏活累活。
这两块芯片之间必须有一套标准的数字接口来交换数据和控制信息,于是就有了MII、RMII、GMII、RGMII这一族接口。名字里那个“II”是“Independent Interface”的缩写,意思是独立接口,也就是说不依赖特定PHY芯片型号,大家按统一规范来设计,MAC能和任意符合规范的PHY对接。
为什么强调“标准”两个字?因为MAC和PHY不一定是同一家芯片。MCU内部集成了MAC,PHY用外挂的(比如DP83848、YT8512、RTL8201),中间就可能出现不同厂商芯片互连的情况。没有标准接口的话,每次换PHY都得重新布线、重新写驱动时序,项目根本没法做。有了标准接口,只要PHY支持RMII,MCU的RMII引脚接过去,配置好时钟模式,基本就能跑起来。
理解这几个接口的差异,有一个最核心的线索:数据位宽和时钟频率的组合关系。MII是4位数据,25MHz时钟跑100M;RMII把数据位宽砍到2位,时钟提到50MHz;GMII是8位数据,125MHz时钟跑1000M;RGMII用8位数据在双沿采样,时钟还是125MHz。接口演进的方向说白了就是:用更少的引脚、更高的时钟效率去承载更高的速率,同时尽量降低PCB布线的难度和成本。
这个逻辑想通了,后面看每个接口的细节就会很顺。
2. 逐个拆解:MII、RMII、GMII、RGMII的工作原理与信号定义
2.1 MII:最原始的百兆标准接口
MII(Media Independent Interface)是IEEE 802.3u定义的百兆以太网标准接口,数据位宽4位,发送时钟和接收时钟都是25MHz(100M速率下)。整个接口的信号分成几组:数据信号、时钟信号、控制信号、管理信号。
标准MII接口一共20多根线,核心信号包括:
- TXD[3:0]:发送数据,4位并行
- RXD[3:0]:接收数据,4位并行
- TX_CLK:发送时钟,25MHz(100M)/ 2.5MHz(10M)
- RX_CLK:接收时钟,由PHY提供,25MHz(100M)/ 2.5MHz(10M)
- TX_EN:发送使能
- RX_DV:接收数据有效
- MDC / MDIO:管理接口时钟和数据线,用来读写PHY寄存器
- CRS / COL:载波侦听和冲突检测,半双工模式用
MII的时序特点:发送方在TX_CLK的上升沿把数据打好,接收方在上升沿采样。这个接口因为引脚多、布线占用面积大,现在已经很少在新设计里直接使用,但在很多老方案或者FPGA设计里还能见到。
MII的4位数据在100M速率下时钟25MHz,意味着每个时钟周期传输4位,4×25M=100Mbps,正好匹配百兆速率。逻辑很简单,时序要求也不苛刻,这是它当年能成为标准的重要原因。
2.2 RMII:引脚减半的百兆方案
RMII(Reduced MII)的出现就是为了解决MII引脚太多的问题。它在保持100Mbps速率的前提下,把数据线从4位砍到2位,时钟从25MHz提到50MHz,整体信号数量从20多根减少到不到10根。对于引脚资源紧张的MCU和小型化PCB来说,这是巨大的优势。
RMII接口的关键信号:
- TXD[1:0]:发送数据,2位并行
- RXD[1:0]:接收数据,2位并行
- REF_CLK:参考时钟,50MHz,收发共用同一个时钟
- TX_EN:发送使能
- RX_DV(CRS_DV):接收数据有效/载波侦听
- MDC / MDIO:管理接口
- 另外有些实现需要 RX_ER 信号
RMII和MII在工作机制上有本质区别,除了数据位宽减半、时钟翻倍之外,最需要注意的是收发共用一个参考时钟REF_CLK。这个时钟可以由MAC提供,也可以由PHY提供,还可以由外部有源晶振提供。正是“共同时钟”这个设计,让RMII在时序上比MII更敏感,实际布线时必须认真处理REF_CLK的质量。
STM32F407这类MCU内部集成了MAC,对外提供RMII接口,外部接PHY芯片时,REF_CLK的处理方式是很多新手最先踩坑的地方。后面第4节会专门展开讲。
2.3 GMII:千兆时代的全并行接口
到了千兆速率,MII这套思路继续沿用就变成了GMII(Gigabit MII)。数据位宽从4位变成8位,时钟从25MHz变成125MHz,8×125M=1000Mbps,匹配千兆速率。GMII的引脚数量比MII更多,超过24根,对PCB布线来说是个不小的挑战。
GMII核心信号:
- TXD[7:0]:发送数据,8位并行
- RXD[7:0]:接收数据,8位并行
- GTX_CLK:发送参考时钟,125MHz,由MAC提供
- RX_CLK:接收时钟,由PHY提供,125MHz(1000M)/ 25MHz(100M)
- TX_EN:发送使能
- RX_DV:接收数据有效
- MDC / MDIO:管理接口
GMII的时序要求比MII严格不少,因为125MHz的时钟频率下,信号的建立时间、保持时间窗口只有纳秒级,对PCB走线长度匹配、阻抗控制都提出了要求。所以GMII常见于FPGA、高性能网络处理器等场景,普通MCU很少直接引出GMII,因为引脚数量扛不住。
2.4 RGMII:高性价比的千兆接口
RGMII(Reduced GMII)是现在使用最广泛的千兆MAC-PHY接口方案。它的核心思路是:数据位宽保持8位,但使用DDR双沿采样,在125MHz时钟的上升沿和下降沿各传输一次数据,等效达到250M次采样/秒,8×2×125M=2000Mbps的传输能力,实际用于1000Mbps全双工。
RGMII信号数量锐减到12根左右:
- TXD[3:0]:发送数据,4位并行,上升沿和下降沿各传4位,合计8位
- RXD[3:0]:接收数据,4位并行,同理
- TX_CLK:发送时钟,125MHz
- RX_CLK:接收时钟,由PHY提供,125MHz
- TX_EN / TX_CTL:发送控制信号,上升沿传TX_EN,下降沿传TX_ER
- RX_DV / RX_CTL:接收控制信号,上升沿传RX_DV,下降沿传RX_ER
- MDC / MDIO:管理接口
RGMII最大的价值在于用12根线实现了千兆速率,不管对MCU还是对PCB布局都友好太多。很多自带千兆MAC的芯片(比如NXP的i.MX系列、瑞萨的RZ系列、部分STM32MP1)都支持RGMII。RGMII唯一让人头疼的地方是时序约束,双沿采样意味着对信号延迟、时钟偏斜特别敏感,需要在硬件设计和驱动层做专门的延迟补偿。
3. 接口对比:引脚数量、时钟频率、速率上限与适用场景
几个接口放到一张表里看,差异一目了然:
| 接口类型 | 数据位宽 | 时钟频率 | 采样方式 | 引脚数量(约) | 支持速率 | 适用场景 |
|---|---|---|---|---|---|---|
| MII | 4位 | 25MHz | 单沿 | 20+ | 10/100Mbps | 老设计、FPGA教学板 |
| RMII | 2位 | 50MHz | 单沿 | 8-10 | 10/100Mbps | 百兆MCU方案、STM32F407等 |
| GMII | 8位 | 125MHz | 单沿 | 24+ | 10/100/1000Mbps | FPGA、高性能网络处理器 |
| RGMII | 4位(双沿) | 125MHz | 双沿 | 12 | 10/100/1000Mbps | 千兆MCU/MPU、主流新设计 |
从MII到RMII,本质是面积换速度:引脚减半,时钟翻倍。从GMII到RGMII,本质是时间换面积:利用双沿采样,在同样的时钟频率下把吞吐量翻了一倍。
选型逻辑也很清楚:
- 如果做百兆、成本敏感、MCU引脚紧张,优先RMII
- 如果做千兆、板子上空间允许、MAC支持GMII,可以考虑GMII(但很少这样选)
- 如果做千兆、追求布线面积和电磁兼容性,RGMII是当前最主流的选择
- MII一般只在已有方案沿用或学习参考时用到
在实际项目中,真正让你头大的不是这几个接口的速率数字,而是它们带来的时钟架构差异和时序容差问题。RMII的50MHz共同时钟、RGMII的125MHz双沿采样,才是调试中最容易出幺蛾子的地方。
4. RMII接口的时钟架构与常见调试痛点:为什么你的网卡接收数据老是错
4.1 REF_CLK:RMII的灵魂信号
前面提到,RMII的收发共用一个50MHz参考时钟REF_CLK。这个时钟是谁提供的,直接决定了硬件电路怎么设计,也决定了驱动里要不要做特殊配置。RMII的REF_CLK有三种典型接法:
- PHY提供REF_CLK:外部晶振接在PHY的XI/XO引脚,PHY内部锁相环产生50MHz的REF_CLK输出给MAC。这种接法对MAC最友好,MAC不需要额外处理时钟。
- MAC提供REF_CLK:MCU从MCO引脚或其他时钟输出引脚产生50MHz时钟,接到PHY的REF_CLK输入。PHY的收发逻辑都参考这个外部时钟。
- 外部独立有源晶振提供REF_CLK:50MHz有源晶振同时接到MAC和PHY的REF_CLK输入。这种方式时钟质量最可控,但BOM成本稍高。
这三种接法在STM32F407上都有应用。官方评估板常见的是PHY提供50MHz时钟给MCU,或者MCU通过MCO1输出50MHz。很多人拿着开发板的原理图照抄,没仔细看时钟方向,结果自己画板子时晶振接错位置,或者MCO引脚没初始化,网络死活不通。
4.2 例1:STM32F407 + DP83848的RMII设计经验
STM32F407的MAC支持MII和RMII两种模式,通过复用功能寄存器切换。用RMII接DP83848时,典型的配置是这样的:
- PHY地址:DP83848的地址由硬件引脚PHYAD[4:0]决定,常见配置为0x01,驱动里要对应
- REF_CLK:如果选择MCU提供时钟,用PA8复用功能MCO1输出50MHz,接到PHY的XI引脚
- RMII数据引脚:PA1(ETH_RMII_REF_CLK,注意这个引脚在RMII模式下也有特殊功能)、PA2(MDIO)、PC1(MDC)、PA3(ETH_RMII_CRS_DV)、PA4(ETH_RMII_RXD0)、PA5(ETH_RMII_RXD1)、PB11(ETH_RMII_TX_EN)、PB12(ETH_RMII_TXD0)、PB13(ETH_RMII_TXD1)
驱动层面,在stm32f4xx_hal_eth.c里需要设置PHY时钟源。如果REF_CLK是外部输入给MCU的,ETH->MACCR的FES位(Fast Ethernet Speed)要正确配置,10M时清0、100M时置1。还要注意DM(Duplex Mode)位的设置。
关于“RMII接口网卡接收数据错误”,我遇到过的典型表现:
- 能建立链路(link up),但收包全是CRC错误
- 能发不能收,或者能收几个包就断
- 收发速率极慢,丢包严重
这类问题排查顺序很重要。先不要急着怀疑驱动,用示波器或者逻辑分析仪看REF_CLK是否稳定、频率是否为50MHz、幅度是否达到芯片要求。很多情况下问题出在时钟波形质量:晶振负载电容配错导致起振不稳,或者MCU的MCO输出驱动能力不足,导致高电平幅度不够。
如果时钟没问题,再排查CRS_DV信号。RMII里的CRS_DV是把标准MII的CRS和RX_DV合并后的信号,PHY在接收数据时拉高它。有些PHY芯片在接收单播包时CRS_DV的表现和接收广播包不一样,导致MAC认为载波一直存在,进不了接收状态机。这种情况需要检查PHY芯片寄存器里关于CRS_DV行为的配置,DP83848有相关寄存器可以调整CRS_DV的响应行为(比如接收空闲时是否保持高电平)。
4.3 例2:YT8512的RMII时钟配置误区
YT8512是国产PHY里用得比较多的一颗,Costdown方案常选它。但YT8512的RMII时钟配置和TI的PHY不太一样,很多人按DP83848的思路去配,结果翻车。
YT8512支持RMII的REF_CLK输入输出模式,但有个细节:部分型号或版本里,REF_CLK是PHY的输出时,频率源来自PHY内部的PLL,外部XI/XO需要接25MHz晶振而不是50MHz。如果按DP83848的习惯接了50MHz晶振,YT8512反而无法正常工作。
另外YT8512的上电初始化时序比较讲究,PHY芯片的VDDIO电压和MAC的IO电压必须匹配,否则MDIO读写不稳定,读出来的寄存器值全是0xFF或者随机值。很多网卡接收数据错误、驱动识别不了PHY型号,root cause其实是IO电平不匹配,而不是接口时序问题。
判断方法很简单:用MDIO读PHY的ID寄存器(寄存器2和3),看能不能读到合法的芯片ID。读不到就优先查供电、复位、时钟这三件事。
4.4 RMII调试的通用排查链路
如果遇到RMII网卡接收数据错误,我建议按下面这个顺序排查:
- 确认PHY能正常上电复位,检查供电电压和复位引脚时序
- 用MDIO/MDC读写PHY寄存器,确认PHY ID正确、基本配置生效
- 用示波器测量REF_CLK频率和幅度,确认50MHz稳定
- 检查MAC模式配置是RMII还是MII,很多MCU默认是MII模式
- 检查TX/RX数据引脚是否复用正确,用GPIO输入模式读一下引脚电平变化
- 用PHY的回环模式(loopback)隔离问题:PHY内部回环能通说明MAC-PHY接口没问题,问题在PHY到网线一侧;回环不通说明MAC-PHY接口本身有问题
- 查PCB布线,REF_CLK走线是否太长、跨分割、挨着大电流走线
5. RGMII的时序内涵与约束:为什么它比RMII更容易掉链子
5.1 双沿采样带来的挑战
RGMII的接收端是时钟双沿采样,对时钟和数据之间的相对延迟(skew)要求非常严格。在125MHz时钟频率下,一个时钟周期8ns,上升沿和下降沿之间的半个周期只有4ns,留给数据建立时间和保持时间的窗口非常窄。
数据从PHY到MAC(接收方向)的时候,PHY输出的数据是以它的TX_CLK(也就是MAC看到的RX_CLK)边沿为参考的。但PHY发送数据的时机和RX_CLK边沿之间的关系并不总是在理想位置,不同的PHY芯片行为还不一样。有的PHY把数据对齐到时钟上升沿,有的则故意在时钟和数据之间加一个1.5ns~2ns的内部延迟,目的是让接收端采样更容易。
RGMII规范里定义了一个内部延迟模式,就是PHY芯片在数据通路上自动加延迟,保证数据在时钟沿附近稳定。常见实现有两种:
- TX内部延迟:PHY在发送方向(MAC→PHY)的数据通路上加延迟
- RX内部延迟:PHY在接收方向(PHY→MAC)的数据通路上加延迟
不同的PHY芯片,延迟的默认值是开启还是关闭、能调整多少,差别很大。有些PHY通过寄存器位来控制(比如RTL8211系列有RXDLY、TXDLY相关的位),有些PHY则通过芯片引脚的外部上下拉电阻来配置。
5.2 RGMII接口时序约束的实践路子
在FPGA里做RGMII接口时,时序约束是绕不开的。你需要告诉综合工具:RXD[3:0]和RX_CTL信号相对RX_CLK的约束关系是什么。如果PHY没有开启内部延迟,那么数据相对时钟边沿可能只有1ns左右的窗口,普通IO的直接采样很容易不满足建立/保持时间。
解决思路一般有两种:
- 让PHY开启内部延迟模式:在驱动初始化时设置PHY寄存器,开启TX和RX方向的延迟。这种方案最简单,硬件不用改,只需要驱动配置正确。
- 在MAC侧用逻辑延迟/IO延迟:如果PHY不支持内部延迟,需要在MAC的IO上做延迟(比如FPGA内部的IODELAY、MCU的DCMI/ETH模块内部延迟校准)。
实际项目中,很多RGMII不通的问题,最后定位到就是PHY的延迟配置没开。芯片手册里关于这个功能的描述往往藏在寄存器说明的角落里,不仔细看根本找不到。建议拿到新PHY芯片,先在驱动里把PHY ID读出来,然后去手册里查对应ID的芯片版本号,再找延迟配置的默认值。
以RTL8211F为例,其寄存器0x14的bit 6和bit 5分别控制RX delay和TX delay的开关。默认值可能为0(关闭),这就导致MAC侧采样失败。设置方法一般是:
// 伪代码:读取PHY寄存器0x14,写入新值使能延迟 val = phy_read(phydev, 0x14); val |= (1 << 6) | (1 << 5); // 开启RX/TX delay phy_write(phydev, 0x14, val);当然,不同版本的RTL8211F这个寄存器定义可能不同,有的在0x1C、有的在0x15,务必以对应数据手册为准。
5.3 时序参数里那些“必须满足”的数字
RGMII规范中,接收方向的典型时序参数是这样一套:
- Tskew(时钟到数据的偏斜):通常要求在±0.5ns以内
- Tsetup(建立时间):数据在时钟沿之前必须稳定的最短时间,一般要求1ns左右
- Thold(保持时间):数据在时钟沿之后必须保持的最短时间,一般要求1ns左右
换算一下,如果PHY不做延迟,数据相对于时钟沿的偏移可能达到1.5ns甚至更大,这意味着接收端采样时可能刚好落在数据翻转的窗口里,采到错误电平。表现出来就是:能link up,但一跑吞吐测试就大量丢包、CRC错误,甚至完全不通。
在PCB布线层面,RGMII的每组数据线最好等长,时钟线不要比其他信号线长太多。建议数据线和对应时钟的走线长度差控制在±100mil以内,这也是很多参考设计里要求的。差分对的事这里不展开,RGMII是单端信号,重点考虑的是线间耦合和回流路径。
6. 基于应用场景的选型建议:百兆、千兆、不同主控怎么选
6.1 百兆方案优先选RMII,但不代表所有RMII都一样
百兆工业控制板、IoT网关、STM32F407/F429这类MCU方案,RMII是绝对的主流。原因前面说过:引脚少、布线面积小、MCU内部MAC支持。
但选RMII的时候要确认三件事:
- MCU的MAC是否支持RMII,不是所有带MAC的MCU都支持,有些老型号只有MII
- REF_CLK的方向和接法,根据MCU和PHY的能力决定,选最容易实现的方案
- PHY芯片的型号和来源,不同PHY的配置寄存器差异很大,驱动移植工作量不同
从我实际经验看,DP83848、LAN8720、YT8512都是百兆RMII方案里常见的PHY。LAN8720因为外围简单、价格低,在很多低成本方案里出现频率很高。但LAN8720的REF_CLK默认方向和硬件配置引脚有关,需要特别留意。
6.2 千兆方案看主控,RGMII适配比GMII更值得投入
如果主控是NXP i.MX6ULL、i.MX8、瑞萨RZ/G系列、Zynq或者STM32MP1这种带千兆MAC的芯片,接口选型基本就是RGMII。GMII虽然功能上更传统、时序更简单,但引脚数量让PCB设计非常痛苦,大多数现代设计不会主动选它。
RGMII方案在贴近量产时需要额外注意PHY的延迟模式配置,这个配置在Linux内核里的drivers/net/phy/xxx.c里往往有现成的处理逻辑。比如用RTL8211系列时,内核phy驱动里会读取PHY芯片的device tree配置,如果dts里配置了rx-internal-delay-ps和tx-internal-delay-ps,驱动就会在初始化时把对应的寄存器位设置好。用主线内核时,这一步基本是自动的;用厂家BSP时,很多功能被裁掉了,就得自己手动加。
6.3 几个选型决策的“非技术”因素
除了速率、引脚、时序,实际选型还要考虑几个容易被忽略的点:
- 驱动生态:Linux内核里有现成的PHY驱动吗?还是需要自己改?有些国产PHY的驱动补丁只放在厂家BSP里,主线内核根本不支持,后续升级内核会非常痛苦
- 量产稳定性:PHY芯片的供货稳定性和生命周期,工业项目一干就是五六年,芯片停产能让方案整体报废
- 发热和功耗:千兆PHY的功耗一般在几百毫瓦量级,散热设计不能马虎,工业温度范围-40℃到85℃也是一个硬指标
7. 实测经验:用回环模式快速定位RGMII/RMII链路故障
调试以太网接口,我最推荐先掌握一个技巧:PHY回环模式。这个概念很简单,就是让PHY芯片在内部把发送数据直接转给接收通路,数据不经过网线传输。这样分成两段来定位问题:
- MAC→PHY→(内部回环)→PHY→MAC,如果这条链路通,说明MAC和PHY之间的数字接口没大问题
- 如果回环测试正常,但接上网线就是不通,问题多半在PHY的模拟前端、变压器、网口连接器或者对端设备
不同PHY的回环使能位一般在寄存器0的bit 14,设置该位为1即可进入回环模式。以DP83848为例:
// 设置DP83848进入回环模式 unsigned int bmcr = phy_read(phydev, 0x00); bmcr |= (1 << 14); // 回环模式使能 phy_write(phydev, 0x00, bmcr);回环模式下,MAC发送一个ping包,在不连接网线的情况下,如果MAC能收到自己的回应(当然是PHY回环回来的),说明MAC-PHY链路基本正常。
这个技巧对RMII接收错误、RGMII丢包这类问题特别有效。我曾经遇到一个RGMII案例,现象是链路能link up但吞吐量只有带宽的十分之一,一开始怀疑驱动问题,折腾了两天没结果。后来用回环模式测试,发现回环模式下吞吐是满的,于是问题定位到PHY到变压器的模拟通道。一量波形,发现是网络变压器中心抽头没接对,焊盘虚焊导致信号幅度衰减严重。
8. 写在最后的板级设计经验
以太网接口的板级设计,很多坑其实是“规矩没做到位”导致的。信号完整性不是玄学,是有明确物理原因的。RMII和RGMII虽然都是单端信号,但在高频状态下,以下几点直接决定成败:
- 串阻:数据线上的串阻(通常22Ω或33Ω)不是可有可无的,它可以有效减小振铃和过冲,尤其对边缘速率快的芯片至关重要
- 参考平面:REF_CLK、RGMII的时钟线下面必须有完整的地平面,跨分割会直接导致时钟质量问题
- 滤波电容:PHY芯片每个电源引脚的0.1μF去耦电容必须靠近引脚放置,放远了等于白放
- 晶体走线:PHY晶振的走线要短、要粗,两边负载电容要对地,不要走直线穿到背面
- 软件留后门:设计时尽量支持MDIO读寄存器,有的MCU支持通过SWD或JTAG调试时访问ETH寄存器,这在量产阶段排除硬件故障时能省很多时间
最后再分享一个小习惯:我每次画以太网相关板子,都会把PHY芯片的中断引脚、复位引脚和CLKOUT引脚留到测试点,这样软件联调时即使没有逻辑分析仪,也能用万用表量引脚电平判断状态。别小看这几个测试点,到了现场排除故障的时候,它们能救命。