标准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) |
为什么要分开通告?优先级是这样排的:
- 100BASE-TX 全双工(最高优先级)
- 100BASE-TX 半双工
- 10BASE-T 全双工
- 10BASE-T 半双工(最低优先级)
嗯,这里要注意。如果你不想让PHY自动协商到100M,只想要10M,那你就把ANAR里的100M能力位清零。我曾经在项目里碰到过,某路由器用了一个便宜PHY,100M链路的抗干扰能力太差,最后被迫强制只通告10M。
初始化配置建议:
上电后,我习惯先读BMSR确认PHY状态,再读PHYIDR识别型号,然后根据设计需求写ANAR。写ANAR之后,一定要再置位控制寄存器(0x00)的AN使能位和重启自动协商位,PHY才会开始发FLP。
图:三个寄存器的角色关系
小结
今天这三个寄存器,几乎每个PHY驱动都会用到。BMSR看状态,PHYIDR做识别,ANAR管能力通告。记住它们的地址和关键位,后面讲控制寄存器、链路协商过程就会轻松很多。我自己做调试时,经常在初始化代码开头先打印这三个寄存器的值,能快速定位大部分PHY侧的问题。