寄存器访问协议:MDIO/MDC协议详解

MDIO/MDC这套协议,说白了就是给PHY和MAC之间搭了一条“管理通道”。我当年第一次调千兆网卡的时候,折腾了三天才把寄存器读回来,后来发现根本不是配置问题,而是时序没对齐——嗯,那次之后我再看协议,眼睛就自动盯在MDC沿上了。

1. 物理层信号与基础时序

MDIO只有两条线:MDC(时钟)和MDIO(数据)。MDC由主设备(通常是MAC或CPU)驱动,最高频率可以跑到25 MHz,但实际设计里我习惯降到2.5 MHz左右,走线长一点也稳。MDIO是双向三态信号,需要外部上拉电阻——这个细节容易漏,记得加1.5kΩ上拉到1.8V或3.3V。

数据采样发生在MDC的上升沿,输出变化在下降沿。这点非常重要:MDC上升沿采集数据,MDIO在下降沿改变。我见过有人把采样沿搞反,读回来的寄存器永远是一堆乱码。

信号方向说明
MDC主设备输出时钟,空闲时保持高
MDIO双向三态数据,空闲时由上拉电阻拉高

2. Clause 22 帧格式(传统玩法)

Clause 22是IEEE 802.3中最早定义的MDIO协议。它支持最多32个PHY(地址0-31),每个PHY内部有32个寄存器(地址0-31)。结构紧凑,但扩展性有限。

帧结构固定32位(不算前导码和起始):

前导码(preamble) 32个'1' + 起始码(start) 01 + 操作码(opcode) + PHY地址(5bit) + 寄存器地址(5bit) + 转向位(TA) + 数据(16bit)

读写操作的区别在操作码:

  • 读操作:opcode = 10,先写地址,然后PHY返回数据。
  • 写操作:opcode = 01,一次完成地址+数据写入。

实际坑点:Clause 22的寄存器地址只有5位,只能访问0-31。有些PHY会通过页寄存器扩展,但这不属于标准,不同厂家兼容性很差。我记得有个项目中用了某个品牌PHY,页切换需要先写影子寄存器,坑了我整整两天。

3. Clause 45 帧格式(扩展利器)

Clause 45是为了解决地址空间不足而生的。它引入了“设备类型(DEVAD)”的概念,支持更灵活的寄存器层次。帧格式有两种:地址帧和数据帧,通过操作码区分。

帧类型操作码帧结构
地址帧(写地址)00前导码 + 起始 + 00 + PHYAD[4:0] + DEVAD[4:0] + TA10 + PORTAD[15:0]
写数据帧01前导码 + 起始 + 01 + PHYAD[4:0] + DEVAD[4:0] + TA10 + DATA[15:0]
读数据帧(地址为先)11先发地址帧,再发读数据帧获取结果

DEVAD可以看作“子设备号”,每个PHY最多有32个DEVAD,每个DEVAD内部地址空间从0到65535(16位)。寄存器数量直接爆炸,这就是为什么现代PHY都用Clause 45。

兼容性陷阱:Clause 45的帧格式与Clause 22完全不同,不能混用。有些MAC控制器支持自动切换,但需要一个配置位。我曾经遇到过MAC不支持Clause 45,但PHY默认工作在45模式,结果零通信。解决办法:在硬件初始化时读PHY ID寄存器,确定协议版本后再配置。

4. 读写时序关键点

无论哪个Clause,读写时序都遵循一个基础规则:写操作一次完成,读操作需要两帧。这里我画了一张时序简图,帮你视觉化理解:

MDIO协议架构与读写流程 MDC时钟 MDIO数据线 Clause 22帧格式 32个PHY × 32寄存器 Clause 45帧格式 地址帧 + 数据帧 寄存器映射表 标准寄存器 + MMD空间 读写时序 读操作:地址帧→TA→数据帧 写操作:数据帧一次完成 MDC上升沿采样 MDIO数据线复用

从图上你可以看到:MDC提供同步时钟,MDIO承载Clause 22或45的帧,最终导向寄存器映射表。读操作需要一次地址写入(或地址帧)再加一次数据读出,这是PHY内部状态机决定的。写操作则直接发送数据帧即可。

5. 寄存器映射实战

PHY的基本寄存器(0-15)在Clause 22和Clause 45中定义一致,但16-31是厂商自定义。我这里列几个最常用的:

寄存器地址名称关键位
0控制寄存器位15:软件复位;位13:回环使能;位8:全双工
1状态寄存器位5:自动协商完成;位2:链路建立;位0:扩展状态
4自动协商广告寄存器位8-5:速度选择;位4:双工模式
5链路伙伴能力寄存器读取对端能力,用于协商

个人习惯:调试眼图之前,我总会先读寄存器1确认链路建立,再读寄存器4和5看看协商结果。如果链路都没起来,调眼图就是空中楼阁。另外,Clause 45的MDIO帧中,ST(起始码)是固定的(00/10/11),如果PHY没响应,用示波器抓MDIO引脚,起始码最容易被干扰——别问我怎么知道的。

6. 避坑指南

  • MDIO引脚的上下拉:有些MCU内部弱上拉不够,外部必须加1.5kΩ上拉到1.8V或3.3V,否则MDIO空闲电平不稳,导致帧头识别失败。
  • Clause 22与45混用:如果MAC和PHY使用不同协议,通信直接失败。我的经验:在驱动加载时先发一个Clause 22读PHY ID(寄存器2,3),如果返回异常再尝试Clause 45。
  • TA转向位时序:转向位(TA)是2位,Clause 22要求TA10在IDLE状态由主设备释放总线,PHY驱动MDIO拉高。时序窗口只有1个MDC周期,如果上拉电阻偏大,上升沿变慢,可能采样错误。我曾经把PHY的100米外接到另一个板子上,MDIO走线长了30cm,信号反射导致TA位误判——后来加了RC滤波解决。