第三章 常用PHY芯片寄存器:基本寄存器、状态寄存器、控制寄存器
好,聊到MDIO调试,寄存器是最底层的语言。PHY芯片的寄存器空间虽然大,但真正在调试中用得顺手的,其实就那么几个核心位置。我个人习惯把这些寄存器称作“三板斧”——基本寄存器、状态寄存器、控制寄存器。掌握这三类,大部分链路问题都可以理出头绪。
3.1 基本寄存器——PHY的身份信息
调试时最先要看的是什么?不是说马上查错误,而是先确认:我到底在和谁对话?PHY的基本寄存器就干这个事。
基本寄存器包括两个:
- 寄存器0(Control Register)——控制PHY的启动、复位、环回等操作
- 寄存器1(Status Register)——读取PHY的基本能力和当前状态
- 寄存器2/3(PHY ID Registers)——厂商标识和型号标识
这三个寄存器组成了PHY的身份档案。其实,IEEE 802.3标准规定所有PHY都必须实现寄存器0和1,所以这两兄弟是调试的起点。
我在项目中遇到过几次这样的情况:板子回来,MDIO能读到数据,但链路死活不通。我习惯先读一下寄存器2,发现读到的值是0xFFFF——这说明总线其实在浮空,读到的全是假数据。从那以后,我调试任何新板子,第一件事就是读PHY ID。
3.2 状态寄存器——PHY当前在干什么
状态寄存器(Register 1)是我日常调试点检次数最多的寄存器。说白了,它就是PHY的实时仪表盘。
我们重点看几个位段:
| 位段 | 含义 | 调试意义 |
|---|---|---|
| Bit 15 | 100BASE-T4能力 | 通过该位可以判断PHY是否支持T4模式 |
| Bit 14 | 100BASE-TX全双工能力 | 检查PHY是否支持100M全双工 |
| Bit 13 | 100BASE-TX半双工能力 | 检查PHY是否支持100M半双工 |
| Bit 12 | 10BASE-T全双工能力 | 检查PHY是否支持10M全双工 |
| Bit 11 | 10BASE-T半双工能力 | 检查PHY是否支持10M半双工 |
| Bit 5 | 远端错误 | 对端是否有错误信号 |
| Bit 2 | 链接状态 | 一票否决位:1=链接正常,0=链接断开 |
| Bit 0 | 扩展能力 | 是否有扩展寄存器可用 |
我个人在调试时,会先看Bit 2(链接状态)。为什么?链接状态是PHY硬件层直接给出的,不受软件干扰。如果是0,说明物理层就没通,不用去查上层协议了。如果是1但网络还是不通,那再往上查。
嗯,这里要注意,状态寄存器很多位是“锁存”的。也就是说,某个错误发生过后,除非你读它一次,否则它会一直保持置位状态。我遇到过很多朋友在调试时连续读寄存器1,发现某个位一会儿1一会儿0,跑来问是不是PHY坏了。其实不是,是第一次读时清掉了锁存。
3.3 控制寄存器——可以做什么改变
状态寄存器只是看,控制寄存器(Register 0)才是动手的。
控制寄存器主要控制PHY的工作模式和行为:
- Bit 15:软复位 —— 写入1可触发PHY软复位,复位后自动回0
- Bit 14:环回模式 —— 写入1进入环回模式,常用于MAC/PCS层调试
- Bit 13:速度选择高 —— 选择速率(与Bit 6配合)
- Bit 12:自协商使能 —— 1=开启自协商,0=关闭自协商强制速率/双工
- Bit 11:下电模式 —— 1=进入低功耗模式
- Bit 10:隔离模式 —— 1=MDI/MDI-X隔离
- Bit 9:重启自协商 —— 写入1重新开始协商过程
- Bit 8:全双工 —— 强制全双工模式(仅自协商关闭时有效)
- Bit 6:速度选择低 —— 与Bit 13组合选择速率
- Bit 3:碰撞测试使能 —— 用于自主测试
- Bit 0:重启 —— 某些PHY厂商用于软重启
速度选择位(Bit 13 + Bit 6)的组合挺重要:
| Bit 13 | Bit 6 | 速率 |
|---|---|---|
| 0 | 0 | 10BASE-T |
| 0 | 1 | 100BASE-TX |
| 1 | 0 | 1000BASE-T |
| 1 | 1 | 保留 |
我调试时常做的事:如果怀疑自协商有问题,我会先关掉自协商(Bit 12写0),然后强制设一个速率和双工。然后把寄存器1读回来——如果能正常链接,说明PHY硬件没问题,问题出在协商过程里。如果是协商过程的问题,再去查寄存器4、5、6、7这些协商伙伴能力寄存器。
3.4 控制寄存器扩展——1000BASE-T特有的页
1000BASE-T由于速率更高,控制内容更复杂。标准在寄存器9(1000BASE-T Control Register)和寄存器10(1000BASE-T Status Register)中增加了扩展内容。
寄存器9包含几个关键位:
- Bit 12:主从配置——决定谁发时钟谁收时钟
- Bit 11:主从自动协商使能
- Bit 9:发送器测试模式
- Bit 8:接收器测试模式
// 读PHY ID的伪代码示例
uint16_t read_phy_id(int phy_addr) {
uint16_t id_high = mdio_read(phy_addr, 2); // 寄存器2:高16位ID
uint16_t id_low = mdio_read(phy_addr, 3); // 寄存器3:低16位ID
// 组合成32位ID
uint32_t phy_id = ((uint32_t)id_high << 16) | id_low;
// 标准PHY ID结构:
// Bit 31:24 = OUI第3-10位
// Bit 23:18 = OUI第11-16位
// Bit 17:12 = 厂商型号
// Bit 11:6 = 版本号
// Bit 5:0 = 厂商自定义
return phy_id;
}
还有一点,寄存器0的Bit 15,软复位。操作完后需要等待一段时间再访问PHY。不同厂商等待时间不一样,有的100微秒,有的要2毫秒。我曾经犯过一个错:写复位后立刻读状态,结果全0。后来加了个毫秒延时,一切正常。所以,复位后的等待不能省。
最后,我想说说寄存器操作的一个总的原则——“写后读验证”。任何写寄存器操作,都读回来确认一遍。MDIO总线上可能被其他设备干扰,写成功的假象我踩过不止一次。