4. 寄存器1(BMSR):基本状态寄存器——链接状态与速率能力
BMSR 是PHY芯片的“体检报告”。
读这个寄存器,你就能知道PHY当前有没有连上线、能跑多快、有没有自协商能力。
我做调试时,第一件事就是读 BMSR。它能快速告诉我问题出在物理层还是上层。
4.1 位域总览
BMSR 是只读寄存器(部分位可写清零),地址是 寄存器1。总共16位,但只有低12位有意义。
4.2 核心位域解析
B15 [EEE能力]——节能以太网支持。如果PHY支持EEE,这个位就是1。
我碰到过一例:某款PHY在省电模式下不报EEE能力,导致交换机端协商失败。查了半天才发现是B15没置位。
B14 [自协商完成]——自协商有没有搞定?1表示完成,0表示正在进行。
注意:不是所有芯片都支持写1清零。有些PHY你读完后写1,这个位会复位成0。我个人习惯是:只读,不写。
B13 [远端错误]——对端PHY报错了会把这个位置1。
我遇到过对端是老旧设备,它的链路不稳定,远端错误位频繁置1,导致自协商反复重启。
重点:B12 [链接状态]
这是整个寄存器最重要的位。1表示链路已建立,0表示断开。
我上电后的第一件事就是轮询这个位。如果它是0,我根本不用看其他寄存器——先查线缆和对端。
B11 [Jabber检测]——PHY检测到长时间发送异常(比如超过发包时长)。正常情况下都是0。
我曾经在EMC测试环境下,PHY受到干扰导致Jabber置位。这个位偶尔会给你一个“误报”,所以不要一看到这个位就判断硬件坏了。
B10 [扩展寄存器存在]——指示是否支持寄存器0-15之外的扩展空间。大部分现代PHY都支持。
如果你需要读写寄存器16以上,先看这个位是否为1。
4.3 速率能力与自协商的关系
BMSR的速率能力位(B9-B5)告诉你:这个PHY的物理层支持哪些速率和双工模式。
| 位域 | 能力描述 | 对应速率/模式 |
|---|---|---|
| B9 | 100Base-T4 | 100M(四对线,已很少见) |
| B8 | 100Base-TX 全双工 | 100M / 全双工 |
| B7 | 100Base-TX 半双工 | 100M / 半双工 |
| B6 | 10Base-T 全双工 | 10M / 全双工 |
| B5 | 10Base-T 半双工 | 10M / 半双工 |
你要是问:B8和B6都置1,它实际会跑100M还是10M?
嗯,这就看自协商结果了。BMSR只告诉你“我能跑哪些”,不告诉你“当前在跑哪个”。当前工作在什么速率,得看另一个寄存器,比如ANLPAR(寄存器5)或MII状态寄存器。
调试经验:
我建议你在做自协商测试时,先读BMSR的B14(自协商完成),再读B12(链接状态)。两个位都置1,才表示链路正常。
千万别只看B12——硬件有时能建链,但自协商还没结束,速率就是错的。
4.4 读寄存器1的参考代码
写一个最简单的读BMSR的函数,我用的是MDIO接口。注意:地址是1,数据宽度是16位。
// 通过MDIO读取PHY寄存器1(BMSR)
uint16_t phy_read_bmsr(uint8_t phy_addr) {
uint16_t reg_value;
// 发送前导码 + 起始码 + 操作码 + PHY地址(5位) + 寄存器地址(5位)
// 这里省略MDIO时序细节,只示意
reg_value = mdio_read_register(phy_addr, 0x01);
return reg_value;
}
这个函数返回的16位数,你就可以按上表解析了。
注意:
BMSR的某些位,比如B13(远端错误)、B11(Jabber),是写1清零的。也就是说,你读完这个寄存器后,如果某个错误位是1,你往这个寄存器写1到该位,它就会清0。
不过我个人不喜欢对BMSR做写操作,因为不同厂商的PHY对这个寄存器的写行为定义略有差异。我一般只读,不看写。
4.5 BMSR常见状态组合速查表
我根据经验做了一个速查表,方便你快速定位问题。
| B14 (A.N.C.) | B12 (L.S.) | 含义 | 可能原因 |
|---|---|---|---|
| 0 | 0 | 链路断开,自协商未开始 | 线缆没插、对端PHY没电 |
| 0 | 1 | 链路建立但自协商没完成 | 对端是固定速率/双工,需要手动配置 |
| 1 | 0 | 自协商完成但链接断开 | 自协商握手OK,但后续链接检测失败 |
| 1 | 1 | 链路正常 | 正常工作状态 |
实践中,B14和B12同时为1的情况最常见。如果一直卡在B14=0 B12=1的状态,那大概率是配置了强制速率,但没有对应收到对端的自协商广告。
嗯,BMSR的内容讲到这里。你只要能看懂这16位,基本状态寄存器就算拿下了。