MDIO协议标准:IEEE 802.3 Clause 22 vs Clause 45
如果你做过以太网PHY调试,肯定绕不开MDIO。但你可能遇到过这种情况:按照Clause 22的时序去读一个10G PHY的寄存器,结果读回来的数据全是0xFF。我刚开始也犯过这个错——直到我仔细翻了芯片手册,才发现那家伙用的是Clause 45。
这两个版本的MDIO,说白了就是一个旧协议、一个新协议。Clause 22是1998年的老标准,只支持32个PHY,每个PHY有32个16位寄存器。而Clause 45是2002年推出的,专为10G/40G/100G这类复杂器件设计,地址空间大了很多。我们做调试,首先得搞清楚手上用的是哪个版本,不然连读写都做不对。
1. 为什么会有两个版本?
早期的以太网PHY功能简单,IEEE 802.3 Clause 22定义的MDIO接口足够用。后来随着10GBASE-T、光模块、背板以太网的出现,器件内部需要管理的寄存器越来越多,Clause 22的32个寄存器地址显然不够用。
于是IEEE推出了Clause 45,引入了“设备地址(DEVAD)”和“端口地址(PORTAD)”两级寻址,理论上能支持32个端口,每个端口最多32个设备,每个设备又有65536个16位寄存器。这下地址空间几乎无限了。不过要注意,Clause 45的时序和帧格式跟Clause 22完全不同,不能混用。
2. 核心差异速览表
先把最关键的几个区别列出来,后面再一个个细讲。这张表我建议你打印出来贴在工作台上,调试时一眼就能对照。
| 对比项 | Clause 22 | Clause 45 |
|---|---|---|
| 帧开始码(ST) | 01 (2-bit) | 00 (2-bit) |
| 操作码(OP) | 读:10, 写:01 | 地址:00, 读:11, 写:01, 读后增地址:10 |
| 目标地址字段 | PHY地址(5bit) + 寄存器地址(5bit) | 端口地址(5bit) + 设备地址(5bit) |
| 数据字段 | 16位数据 | 16位数据,但地址写入/读取时数据含义不同 |
| 最大PHY/器件数 | 最多32个PHY | 32端口 × 32设备(共1024个目标) |
| 寄存器地址空间 | 每个PHY 32个寄存器(0~31) | 每个设备 65536个寄存器(0~65535) |
| MDC时钟频率 | 通常2.5MHz,最快可达25MHz | 同样,取决于器件规格 |
| 帧间距(Inter-Frame Gap) | 2个MDC周期(空闲) | 2个MDC周期(要求更严格) |
| 预充电(Idle/Preamble) | 32个MDC周期的1 | 32个MDC周期的1(有时可省略) |
3. 帧格式:最直观的区别
Clause 22的帧格式很传统:先发32个1做预充电,然后2位ST码(01),2位OP码,5位PHY地址,5位寄存器地址,2位转向(TA),16位数据。总共64个MDC周期(不含预充电)。
Clause 45的帧格式分两种:
- 地址帧(Address Frame):OP码=00,后面跟端口地址、设备地址,再跟16位寄存器地址。用于告诉器件接下来要读或者写哪个寄存器。
- 数据帧(Data Frame):OP码=11(读)、01(写)、10(读后增地址),后面跟同样的端口/设备地址,然后TA,再跟16位数据。
我个人习惯先看ST码。如果抓到的ST是01,妥妥的Clause 22;如果是00,就是Clause 45。这个判断最快,不用管后面的OP码。
4. 关键细节:地址 vs 数据分离
Clause 45最核心的改变是地址和数据分离。Clause 22是一次性把PHY地址和寄存器地址都放进帧里,然后直接读写数据。Clause 45需要先发一个地址帧告诉器件“我要操作哪个寄存器”,然后再发数据帧读写实际数据。
为什么会这样设计?因为Clause 45的器件内部寄存器太多,用5位根本不够。通过地址帧可以指定16位的寄存器地址,这样就能寻址65536个寄存器。我当时调试一个40G背板PHY,里面光控制PCS的寄存器就有两百多个,用Clause 22根本没法搞。
5. 操作码的含义变化
Clause 22只有两种操作:读(10)和写(01)。Clause 45增加了“地址帧(00)”和“读后增地址(10)”。这个“读后增地址”非常有用,特别是在连续读取队列或统计寄存器时。
我用过一次,读一个10G PHY的误码计数寄存器,需要连续读32个地址。每次读完后地址自动加1,省掉中间发地址帧的时间,速度能快好几倍。不过要注意,不是所有Clause 45器件都支持读后增地址,调试前先查手册确认。
6. 转向时间(TA)的差异
两个版本都有2位转向时间(Turn Around),但Clause 22要求写操作时主机在第1个TA位输出Z(高阻),第2个TA位输出0;读操作时主机在第1个TA位输出Z,然后器件在第2个TA位输出0。Clause 45的TA时序类似,但多了地址帧场景——地址帧里没有TA位,而是紧跟着16位寄存器地址。
嗯,这里要注意:用逻辑分析仪抓波形时,看到TA位是“ZZ”说明是读操作,主机在等器件应答;看到“Z0”是写操作。如果波形里根本没有TA位,那基本就是Clause 45的地址帧了。
7. 预充电和帧间距
两版都要求空闲时MDIO保持高阻抗(通过上拉电阻拉到高),并且每个帧前有32个MDC周期的预充电(全部为1)。但Clause 45的某些器件允许省略这32个1,只要满足片选确认条件就行。我个人建议不要省,兼容性最好。
帧间距方面,Clause 22要求至少2个MDC周期的空闲(MDIO高阻),Clause 45要求一样。但我遇到过一个Marvell的PHY,Clause 45模式下要求至少4个周期的间隔,否则会丢帧。所以实际调试时,我习惯用8个周期的间距,安全第一。
8. 用一张图看清区别
下面这张SVG对比了Clause 22和Clause 45的完整帧结构。注意看ST码的颜色、地址字段的拆分方式,以及Clause 45如何用地址帧+数据帧分两步完成一次寄存器操作。
9. 调试中的避坑指南
- ST码读错:有些逻辑分析仪默认把ST码显示为“01”,但实际上是Clause 45的“00”。我遇到过这种情况,必须看二进制原始数据,别相信显示出来的“ST=0x1”这种简写。
- TA位驱动冲突:Clause 45读操作时,主机在TA的第1位必须释放MDIO,让器件在第2位拉低。如果主机没释放,两强驱动会打架,波形中间出现毛刺。我曾经因为这个烧坏过一个PHY的MDIO引脚——还好只是IO损坏,芯片没挂。
- 帧间距不够:有些SoC的MDIO控制器写死了Clause 22的帧间距(2周期),但Clause 45器件要求更宽松。如果读回的数据错位,试着在代码里插入几个空闲周期。
- 设备地址混淆:Clause 45中“设备”不是物理PHY,而是PHY内部的逻辑功能块(如PCS、PMA、PMD)。比如一个10G PHY,端口0的设备0可能是铜介质PMA,设备1可能是FEC。读错设备地址,数据自然不对。
好了,Clause 22和Clause 45的核心区别就这些。记住最关键的判断方法:先看ST码,再看帧里有没有地址帧。下次你抓MDIO波形时,应该一眼就能认出用的哪个版本了。