标准MII寄存器详解(上):BMSR、PHYIDR、ANAR

好,咱们正式开始啃寄存器了。说实话,刚接触PHY的时候,我对着手册上那一堆16位寄存器也是头皮发麻。后来发现,只要抓住几个核心的,其他都是套路。今天先讲三个最基础的:状态寄存器、厂商ID、自动协商通告能力。

1. BMSR – 基本状态寄存器(地址0x01)

这个寄存器,说白了就是PHY的“健康报告”。上电第一件事儿,我一般都会读它,确认PHY是不是活着、链路是不是通了。

位域 名称 说明
15 100BASE-T4 是否支持T4编码(基本不用管)
14 100BASE-TX 全双工 支持100M全双工?1 = 支持
13 100BASE-TX 半双工 支持100M半双工?1 = 支持
12 10BASE-T 全双工 支持10M全双工?1 = 支持
11 10BASE-T 半双工 支持10M半双工?1 = 支持
10 保留 读为0
9 MF preamble 抑制 是否支持省略管理帧前导码
8 自动协商完成 1 = AN完成,0 = 进行中
7 远端错误 对端发送了无效代码(需读后清零)
6 自动协商能力 1 = 支持自动协商
5 链路状态 1 = 链路已建立,0 = 断开
4 Jabber 检测 是否发生过长时间非法发送
3:0 扩展能力 通常读为0

我常用的调试技巧:

读BMSR之前,先读一次“清空”一下。因为位5(链路状态)和位7(远端错误)是锁存的——链路断了再通,位5不会自动变1,除非你先读一次让它更新。我个人习惯写一个函数,连续读两遍BMSR,取第二次的值。

避坑指南: 位8(自动协商完成)不是只读的。有些PHY需要先置位控制寄存器的AN使能位,它才会开始自动协商。你读出来一直是0,不一定是PHY坏了,很可能是根本没启动AN流程。

2. PHYIDR – 厂商ID与型号(地址0x02、0x03)

PHYIDR1 和 PHYIDR2 合起来标识一颗PHY的“身份证”。我做过一个项目,板子上用的是两个不同品牌的PHY,代码里就是靠读这两个寄存器来动态选择驱动分支的。

PHYIDR1(地址0x02)

  • 位15:0 – OUI 的 3–18 位(共22位OUI的高16位)

PHYIDR2(地址0x03)

  • 位15:10 – OUI 的 19–24 位(低6位)
  • 位9:4 – 厂商自定义型号编号
  • 位3:0 – 版本修订号

举个例子:最常见的 Broadcom BCM5461,读出来是 0x0362_5E14。OUI 0x03625E 对应 Broadcom,模型号 0x01,修订 0x4。你想想看,有了这个信息,代码里做硬件适配就容易多了。

注意: 有些兼容PHY的ID是写死的。比如国产的某些PHY,会直接“借用”大厂的OUI。这时候单靠ID判断不太靠谱,我一般会再读一下扩展寄存器0x1E或0x1F做二次验证。

3. ANAR – 自动协商通告能力(地址0x04)

自动协商,说白了就是两个PHY互相“喊话”:“我能跑100M全双工,你呢?” 你能跑什么,就写在ANAR里。对面读到之后,取交集,选最高的那个。

位域 名称 说明
15 NP 下一页功能使能,一般置0
14:13 保留 写0
12 射频基座(RF) 远程故障指示,一般置0
11:10 确认(ACK) 自动协商握手确认,主机一般不直接操作
9 100BASE-T4 通告T4能力
8 100BASE-TX 全双工 通告100M全双工
7 100BASE-TX 半双工 通告100M半双工
6 10BASE-T 全双工 通告10M全双工
5 10BASE-T 半双工 通告10M半双工
4:0 选择器字段 通常为00001(IEEE 802.3)

为什么要分开通告?优先级是这样排的:

  1. 100BASE-TX 全双工(最高优先级)
  2. 100BASE-TX 半双工
  3. 10BASE-T 全双工
  4. 10BASE-T 半双工(最低优先级)

嗯,这里要注意。如果你不想让PHY自动协商到100M,只想要10M,那你就把ANAR里的100M能力位清零。我曾经在项目里碰到过,某路由器用了一个便宜PHY,100M链路的抗干扰能力太差,最后被迫强制只通告10M。

初始化配置建议:

上电后,我习惯先读BMSR确认PHY状态,再读PHYIDR识别型号,然后根据设计需求写ANAR。写ANAR之后,一定要再置位控制寄存器(0x00)的AN使能位和重启自动协商位,PHY才会开始发FLP。

图:三个寄存器的角色关系

BMSR 状态寄存器 PHYIDR 厂商ID ANAR 通告能力 链路是否建立? AN是否完成? OUI + 型号 + 版本 我支持什么速度/双工 三者协作流程 1. 上电读BMSR,确认PHY是否可访问 2. 读PHYIDR,识别厂商与型号 3. 写ANAR通告能力,触发自动协商 4. 轮询BMSR位8,等待AN完成

小结

今天这三个寄存器,几乎每个PHY驱动都会用到。BMSR看状态,PHYIDR做识别,ANAR管能力通告。记住它们的地址和关键位,后面讲控制寄存器、链路协商过程就会轻松很多。我自己做调试时,经常在初始化代码开头先打印这三个寄存器的值,能快速定位大部分PHY侧的问题。