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频率DC2.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 读/写操作流程

先看读操作:

  1. 控制器拉低MDC一段时间(准备状态)。
  2. 控制器输出32位帧头(全部为1)。
  3. 控制器输出操作码:10(表示读)。
  4. 控制器输出5位PHY地址(高位在前)。
  5. 控制器输出5位寄存器地址(高位在前)。
  6. 转向位:控制器释放总线(高阻),PHY开始驱动。
  7. PHY输出16位寄存器值。
  8. 空闲位:总线恢复高阻。

再来看写操作:

  1. 控制器拉低MDC一段时间(准备状态)。
  2. 控制器输出32位帧头(全部为1)。
  3. 控制器输出操作码:01(表示写)。
  4. 控制器输出5位PHY地址。
  5. 控制器输出5位寄存器地址。
  6. 转向位:控制器的驱动方向不变,写1位占位(不关心数据)。
  7. 控制器输出16位要写入的数据。
  8. 空闲位:总线恢复高阻。

我曾经:在调试一块多PHY交换机时,读寄存器一直返回固定值。最后用逻辑分析仪一抓,发现PHY地址写的是0x1A,但实际芯片strap pin配的是0x0A。一个bit之差,浪费了一个下午。所以我建议:第一次连板子时,先用读操作扫一遍所有PHY地址,看哪个能响应。

1.4 寄存器地址与功能概览

标准MII寄存器前16个(0x00~0x0F)是IEEE定义的,后面16个(0x10~0x1F)是厂家自定义。我挑几个最常用的:

地址寄存器名称关键位作用
0x00BMCR (Basic Mode Control Register)Bit 15: Reset, Bit 13: Speed, Bit 8: Duplex控制复位、速率、双工模式
0x01BMSR (Basic Mode Status Register)Bit 5: Auto-negotiate complete, Bit 2: Link status读取链路协商状态和连接状态
0x04ANAR (Auto-Negotiation Advertisment Register)Bit 9-5: Technology ability宣告本端支持的能力
0x05ANLPAR (Auto-Negotiation Link Partner Ability Register)Bit 9-5: Technology ability读取对端宣告的能力
0x0AMMD Access Control Register-用于访问扩展寄存器(MMD)

我建议:调试的时候先读BMSR(0x01)。Bit 2是link状态,如果这里就是0,那你压根不用管后面的事,先查网线、RJ45座、变压器。

另外,前16个寄存器都是16位宽,一次MDIO事务正好读完。后面厂家自定义的寄存器,很多是通过MMD(Managed Device)机制间接访问的,需要先写0x0A、0x0B等扩展寄存器。后面章节会详细讲。

1.5 MDIO协议知识体系

说了这么多,我画张图帮你串联一下:

MDIO协议知识体系 物理层时序: MDC时钟、MDIO双向数据、采样上升沿/变化下降沿 帧结构: 64个时钟周期 32位帧头(同步) → 2位操作码 → 5位PHY地址 → 5位寄存器地址 → 1位转向位 → 16位数据 → 空闲 读操作流程 控制器发送帧头 → 操作码10 → 地址 → 转向位 → PHY输出数据 写操作流程 控制器发送帧头 → 操作码01 → 地址 → 转向位 → 控制器输出数据 寄存器访问: 0x00-0x1F标准寄存器 + MMD扩展访问

这张图从左到右,从上到下,就是MDIO协议的核心逻辑:物理层时序决定了波形能不能跑对,帧结构决定了数据怎么组织,读/写操作决定了方向和控制权,寄存器地址决定了你要访问哪个功能。

你想想看,链路出问题时,我们读寄存器要么超时,要么乱码,要么返回0xFF。大多数情况都能归到这三类原因之一:时序没对上、帧格式错了、或者地址写错了。搞清楚了这一章,你已经能处理80%的MDIO基础问题了。