1. MDIO协议概述:作用、历史与基本概念
做嵌入式的人,谁没跟PHY芯片打过交道?你想想看,CPU要联网,得经过MAC和PHY,而PHY就像个“黑盒子”。怎么跟它对话?怎么配置它的模式、读取它的状态?MDIO协议,就是干这个的。说白了,它是一条串行总线,专门用来管理以太网PHY和部分交换芯片。
我个人习惯把MDIO比作“数字外科医生的探针”——不打乱数据传输,却能精准地读写内部寄存器。嗯,这里要注意:MDIO和MDC是配套的,一个数据线,一个时钟线,典型的主从结构。
1.1 为什么需要MDIO?
早期的PHY芯片,配置全靠外部引脚。比如某款10M PHY,用二进制跳线选择速度和双工模式。一旦量产,想改配置?只能换电阻。我当初做过一个产品,现场出了问题想远程调PHY,结果只能派人去拨开关……后来换了带MDIO的PHY,一句话就能搞定。
所以MDIO的核心作用是:在运行期间对PHY进行实时监控和动态配置。包括:
- 读取链路状态(Link up/down、速率、双工模式)
- 配置休眠/唤醒、节能模式
- 管理自动协商(Auto-Negotiation)
- 调试网络异常(比如CRC错误计数)
划重点:没有MDIO,你就是个“睁眼瞎”。有了它,PHY所有内部寄存器都展现在你面前。
1.2 历史片段:从慢速到高速
MDIO最初出现在IEEE 802.3u(1995年)中,当时叫MII管理接口。那时候PHY只有几个基本寄存器。后来随着千兆、万兆以太网发展,标准升级到Clause 45(2000年),支持更多设备(MMD)和更大地址空间。
| 标准版本 | 出台年份 | 最大设备数 | 寄存器空间 | 典型场景 |
|---|---|---|---|---|
| Clause 22(MII) | 1995 | 32 | 32(5位地址) | 百兆以下PHY |
| Clause 45(MMD) | 2000 | 32个设备×256路 | 65536(16位地址) | 千兆/万兆PHY、PMA/PMD |
你看,2000年已经过去二十多年,但Clause 45依然是主流。我在调试一款25G以太网PHY时,就用Clause 45协议访问内部的PMA寄存器——地址空间大,用起来很爽。
1.3 基本概念:帧结构
MDIO通信是通过固定格式的帧来完成的。每次操作,主设备(通常是MAC或CPU)发出一个帧,从设备(PHY或MMD)在特定时钟沿回应。帧结构长这样(我手写个伪代码你就明白了):
// MDIO管理帧结构(Clause 22写操作示例)
// 32位前导码 + 起始码(2) + OP码(2) + PHY地址(5) + REG地址(5) + 转向(2) + 数据(16)
// 总长度:32 + 2 + 2 + 5 + 5 + 2 + 16 = 64位
bit[31:0] preample = 0xFFFFFFFF // 32个连续1
bit[1:0] start = 2'b01 // 起始码固定01
bit[1:0] op = 2'b01 // 01=写, 10=读
bit[4:0] phy_addr = 5'b00001 // 目标PHY编号
bit[4:0] reg_addr = 5'b01010 // 寄存器地址
bit[1:0] ta = 2'b10 // 转向周期:主发10,从发在后半段
bit[15:0] data = 16'hA5A5 // 写入的数据
嗯,这里要注意:读操作时,转向周期的第1个时钟由主设备驱动高阻(Z),第2个时钟由从设备驱动数据位。所以读取的帧会在TA阶段多一个小变化。
经验之谈:我刚开始写MDIO驱动时,总搞混OP码和TA的时序。后来画了个时序图贴在工位上——对着波形数时钟,一次就调通了。
1.4 基本概念:寄存器模型
每个PHY至少包含16个基本寄存器(Clause 22),地址0x00~0x0F。其中前几个是固定的:
- 寄存器0x00:控制寄存器(复位、自协商、回环)
- 寄存器0x01:状态寄存器(Link up、速率、全双工)
- 寄存器0x02~0x04:PHY标识符(两个字节的厂商ID和型号)
- 寄存器0x05~0x0F:厂商自定义寄存器
Clause 45将寄存器空间扩展到16位地址,分设备类型(Device Type),每个设备又有独立的地址空间。比如设备3是PMA/PMD,设备7是PCS。我在调试某款Marvell PHY时,发现需要同时读Clause 22的基本寄存器(用于链路状态)和Clause 45的PMA寄存器(用于信号质量)。
注意:Clause 22和Clause 45的地址编码方式不同,不能混用。很多PHY芯片同时支持两种模式,但需要通过操作码(OP码)来区分。如果发错了帧,PHY可能没有反应,甚至返回错误数据。
1.5 电气特性:别让信号失真
MDIO是双向半双工总线,MDC由主设备产生。电气参数主要参考IEEE 802.3标准:
| 参数 | 最小值 | 典型值 | 最大值 | 单位 |
|---|---|---|---|---|
| MDC频率 | — | 2.5 | 25 | MHz |
| MDIO上升/下降时间 | — | 3 | — | ns |
| 高电平输入 | 2.0 | 3.3 | 5.0 | V |
| 低电平输入 | 0 | — | 0.8 | V |
| 输出驱动电流 | 4 | 8 | — | mA |
实际项目中,2.5MHz是比较稳妥的选择。我曾经把MDC提到10MHz,结果在长线缆上读到错误校验——波形已经变形了。后来降低到2.5MHz,稳稳地搞定。
还有一个容易忽略的点:MDIO上拉电阻。标准要求MDIO必须通过一个1.5kΩ~10kΩ的电阻上拉到VDD。否则空闲时总线浮空,会导致通信冲突。我见过一个烂设计,工程师忘了加上拉,结果PHY偶尔能读偶尔不能读——排查了半天。
一句话总结:MDIO的电气层面并不复杂,但频率、上拉和PCB走线直接影响稳定性。调不通时,先拿示波器看看MDC和MDIO的波形——数字工程师最该信任的,就是波形。
好了,到这里MDIO协议的基本骨架你应该心里有数了。我们接下来用一张图梳理一下本章的知识脉络——画得比较简,但核心关系都在。
这张图把MDIO协议的核心维度都串起来了。底层是管理接口,上面分出帧结构、版本演化和电气三大部分,每个部分又细化到具体知识点。你品一品:无论以后遇到什么PHY,只要你能搞清楚这三个维度,基本就能搞定。