第一章 MDIO 协议概述与背景
做嵌入式开发的朋友,十有八九都跟 PHY 芯片打过交道。插上网线、网口灯亮、数据收发…… 这些背后其实藏着一条不起眼的串行总线——MDIO。你可能用过它,但未必真正把它搞清楚。
我个人习惯把 MDIO 叫做“PHY 芯片的后门”。为什么这么讲?你想想看,PHY 芯片正常工作时只管收发数据,但它的状态、配置、错误信息,全靠 MDIO 才能读出来。没有 MDIO,PHY 就像一个黑盒子。
1.1 什么是 MDIO?
MDIO,全称 Management Data Input/Output,一种管理数据输入输出总线。它专门用来访问以太网 PHY 芯片的内部寄存器。千兆以太网标准 IEEE 802.3 第 22 条和第 45 条详细定义了它的电气特性和协议帧格式。
MDIO 总共两条线:
- MDC(Management Data Clock):管理时钟,由 MAC 或 CPU 侧主动提供。
- MDIO(Management Data Input/Output):双向数据线,用于传输读写命令、地址和数据。
说白了,就是主设备(MAC/CPU)通过这两根线,跟 PHY 芯片对话:告诉它要读哪个寄存器,或者写什么值进去。PHY 再乖乖回复数据。
| 信号 | 方向 | 描述 |
|---|---|---|
| MDC | 主 → 从 | 时钟,频率最高 2.5 MHz(IEEE 802.3 规定) |
| MDIO | 双向 | 数据线,时分复用发送命令与接收响应 |
1.2 为什么需要 MDIO?
PHY 芯片的本质是物理层收发器,处理信号编码、解码、电平转换、自动协商这些脏活累活。但问题来了——我们怎么知道 PHY 的工作状态?自动协商结果是什么?链路是否建立?有没有远端错误?这些信息都存在 PHY 内部的寄存器里。
没有 MDIO,就无法:
- 读取状态:比如链接状态、速度、双工模式。
- 动态配置:比如强制设为百兆全双工,而不是靠自动协商。
- 调试排错:比如读出中断状态寄存器,定位链路闪断原因。
我记得有一次调试一款工业交换机,现场链路频繁闪断。拿示波器量 TX 输出波形正常,但 MDIO 接口读出的 Link Status 寄存器一直在 0/1 之间跳变。后来发现是 PHY 的电源纹波太大,导致芯片内部锁相环失锁。要不是 MDIO 能实时读寄存器,这种间歇故障根本没办法定位。
1.3 MDIO 协议帧结构(IEEE 802.3 Clause 22)
这是最常用的 MDIO 帧格式,用来读写 32 个地址(0~31)、每个地址 16 位 的标准寄存器。PHY 芯片最少有 0~15 共 16 个基本寄存器,扩展寄存器走 Clause 45。
一个完整的 Clause 22 读写帧总长度固定:
- 前导码:32 个连续 "1"
- 起始码:01
- 操作码:读 10 / 写 01
- PHY 地址:5 位
- 寄存器地址:5 位
- TA 转换:2 位(读操作为 Z0,写操作为 10)
- 数据:16 位
- 闲置:至少 1 位高阻
帧结构表格就像这样:
| 段名 | 位宽 | 读 | 写 |
|---|---|---|---|
| Preamble | 32 | 全 1 | 全 1 |
| Start | 2 | 01 | 01 |
| Opcode | 2 | 10 | 01 |
| PHYAD | 5 | PHY 地址 | PHY 地址 |
| REGAD | 5 | 寄存器地址 | 寄存器地址 |
| TA | 2 | Z0 | 10 |
| Data | 16 | 从 PHY 读取 | 写入 PHY |
| Idle | ≥1 | 高阻 | 高阻 |
其中 TA 段的 Z0 比较恶心人:主设备在 TA 的第一位释放总线(高阻),同时 PHY 接管总线,然后在第二位驱动 0 作为应答。这一步时序如果没处理好,就可能读到错误数据。我曾经因为 GPIO 输入输出切换慢了半拍,导致数据位错位,查了一天才发现。
1.4 PHY 的标准寄存器简表
IEEE 802.3 规定了 0~15 共 16 个基本寄存器,这里列几个最常用的:
| 地址 | 名称 | 功能 |
|---|---|---|
| 0 | BMCR | 基本模式控制寄存器(复位、速度、环回、自动协商开关等) |
| 1 | BMSR | 基本模式状态寄存器(链接状态、自动协商完成、远端故障等) |
| 2 | PHY IDR1 | PHY 标识符高 16 位 |
| 3 | PHY IDR2 | PHY 标识符低 16 位 |
| 4 | ANAR | 自动协商通告能力 |
| 5 | ANLPAR | 自动协商链路伙伴能力 |
你想想看,只要读寄存器 0~3,就能拿到 PHY 的型号、复位状态、链接情况。很多驱动初始化流程就是:
读 ID → 软复位 → 配置速度/双工 → 开启自动协商 → 轮询链接状态。
1.5 一句心里话
MDIO 协议本身并不复杂,就是一条串行总线读写 16 位寄存器。但实际项目中翻车的点却不少:上拉电阻没加、MDC 频率超标、GPIO 模拟时序被中断打断、PHY 地址设错了(很多芯片默认 0x00 但需要拨码配置)……
我最早接触 MDIO 是在一个路由器项目上,MCU 的 MAC 内部没有 MDIO 控制器,只能用两个 GPIO 脚模拟。写了一个下午,连 PHY ID 都读不对。后来拿逻辑分析仪抓波形,发现是 MDC 空闲时没拉低,PHY 分不清帧边界。加了一条 MDC 空闲低保证,问题瞬间解决。
所以本章先把 MDIO 的来龙去脉讲清,下一节开始就是真正的实战——手把手写代码读写 PHY 寄存器,你跟着一起写一遍,一定会有感觉。
1.6 本章小结
MDIO 总线是连接 MAC 与 PHY 的管理通道,只靠两根线就能完成 16 位寄存器的读写。它的帧结构虽然固定,但实际编码时要注意时钟极性、TA 时序和 PHY 地址。掌握 MDIO 是调试 PHY 的基础技能,不管你是做交换机、路由器,还是工业以太网,都绕不开它。