1. MDIO协议基础:时序、帧结构、寄存器访问
MDIO,全称Management Data Input/Output,是IEEE 802.3规范里定义的一种串行管理接口。说白了,就是用来读取和配置PHY芯片内部寄存器的。
我做调试这行十几年了,可以很负责任地告诉你:MDIO是链路问题的“第一道防线”。波特率、协商状态、中断标志,这些东西都得靠它才能读出来。
这一节,咱们先把它最核心的三个东西讲清楚:时序怎么走、帧长什么样、寄存器怎么读怎么写。搞懂这些,后续的调试技巧才有落脚点。
1.1 物理层时序
先看最基本的。MDIO总线只有两条线:
- MDC(时钟):由MAC侧或管理控制器驱动,最大频率一般是2.5MHz或更高(有些系统允许到12.5MHz)。
- MDIO(数据):双向线,主设备(控制器)和从设备(PHY)都可以驱动。
时序上,MDIO是在MDC的上升沿采样数据,下降沿改变数据。这个规则很简单,但我见过很多新手踩坑。
个人习惯:信号完整性问题最容易出现在这里。MDC的上升沿要干净,不要有毛刺。我一般会在示波器上量一下上升时间,超过3ns就要处理了。
具体参数,我列个表方便你对照:
| 参数 | 最小值 | 最大值 | 说明 |
|---|---|---|---|
| MDC频率 | DC | 2.5 MHz | 有些PHY支持更高,看数据手册 |
| MDC高电平时间 | 160 ns | - | 保证建立时间 |
| MDC低电平时间 | 160 ns | - | 保证保持时间 |
| MDIO数据采样时间 | 10 ns | - | 上升沿前需稳定 |
嗯,这里要注意的是:MDC频率不要随便提。有些板子在开发板上能跑,但产线上批量出问题,一查就是MDC过冲把PHY的输入引脚搞坏了。我曾经有个项目,因为MDC太快,导致读寄存器偶尔返回0xFF,浪费了两天查原理图。
1.2 帧结构:一次MDIO读/写到底长什么样
每帧64个时钟周期,按顺序拼起来的。我建议你先画一张图在脑子里:
| 帧头(32位) | 操作码(2) | PHY地址(5) | 寄存器地址(5) | 转向位(1) | 数据(16) | 空闲(2) |
拆开来看:
- 帧头(32位):32个连续“1”。这是同步头,告诉PHY:要开始通信了。
- 操作码(2位):
01表示写,10表示读。 - PHY地址(5位):0x00~0x1F,最多支持32个PHY。有些厂家把地址焊死在芯片里,有些支持strap pin配置。
- 寄存器地址(5位):0x00~0x1F,也是5位。这就是为什么标准MII寄存器只有32个的原因。
- 转向位(1位):读操作时,这里用来切换总线控制权。写操作时,是PHY的“高阻态”位。
- 数据(16位):真正要读或写的寄存器内容。
- 空闲(2位):高阻态,准备下一次帧。
注意:读操作和写操作的转向位逻辑不一样。写操作时,控制器一直驱动总线;读操作时,控制器在转向位释放总线,由PHY来驱动后面的数据位。如果你读到数据全为0或全为F,大概率是转向位附近的时序或驱动冲突出了问题。
1.3 读/写操作流程
先看读操作:
- 控制器拉低MDC一段时间(准备状态)。
- 控制器输出32位帧头(全部为1)。
- 控制器输出操作码:
10(表示读)。 - 控制器输出5位PHY地址(高位在前)。
- 控制器输出5位寄存器地址(高位在前)。
- 转向位:控制器释放总线(高阻),PHY开始驱动。
- PHY输出16位寄存器值。
- 空闲位:总线恢复高阻。
再来看写操作:
- 控制器拉低MDC一段时间(准备状态)。
- 控制器输出32位帧头(全部为1)。
- 控制器输出操作码:
01(表示写)。 - 控制器输出5位PHY地址。
- 控制器输出5位寄存器地址。
- 转向位:控制器的驱动方向不变,写1位占位(不关心数据)。
- 控制器输出16位要写入的数据。
- 空闲位:总线恢复高阻。
我曾经:在调试一块多PHY交换机时,读寄存器一直返回固定值。最后用逻辑分析仪一抓,发现PHY地址写的是0x1A,但实际芯片strap pin配的是0x0A。一个bit之差,浪费了一个下午。所以我建议:第一次连板子时,先用读操作扫一遍所有PHY地址,看哪个能响应。
1.4 寄存器地址与功能概览
标准MII寄存器前16个(0x00~0x0F)是IEEE定义的,后面16个(0x10~0x1F)是厂家自定义。我挑几个最常用的:
| 地址 | 寄存器名称 | 关键位 | 作用 |
|---|---|---|---|
| 0x00 | BMCR (Basic Mode Control Register) | Bit 15: Reset, Bit 13: Speed, Bit 8: Duplex | 控制复位、速率、双工模式 |
| 0x01 | BMSR (Basic Mode Status Register) | Bit 5: Auto-negotiate complete, Bit 2: Link status | 读取链路协商状态和连接状态 |
| 0x04 | ANAR (Auto-Negotiation Advertisment Register) | Bit 9-5: Technology ability | 宣告本端支持的能力 |
| 0x05 | ANLPAR (Auto-Negotiation Link Partner Ability Register) | Bit 9-5: Technology ability | 读取对端宣告的能力 |
| 0x0A | MMD Access Control Register | - | 用于访问扩展寄存器(MMD) |
我建议:调试的时候先读BMSR(0x01)。Bit 2是link状态,如果这里就是0,那你压根不用管后面的事,先查网线、RJ45座、变压器。
另外,前16个寄存器都是16位宽,一次MDIO事务正好读完。后面厂家自定义的寄存器,很多是通过MMD(Managed Device)机制间接访问的,需要先写0x0A、0x0B等扩展寄存器。后面章节会详细讲。
1.5 MDIO协议知识体系
说了这么多,我画张图帮你串联一下:
这张图从左到右,从上到下,就是MDIO协议的核心逻辑:物理层时序决定了波形能不能跑对,帧结构决定了数据怎么组织,读/写操作决定了方向和控制权,寄存器地址决定了你要访问哪个功能。
你想想看,链路出问题时,我们读寄存器要么超时,要么乱码,要么返回0xFF。大多数情况都能归到这三类原因之一:时序没对上、帧格式错了、或者地址写错了。搞清楚了这一章,你已经能处理80%的MDIO基础问题了。