3、寄存器0(BMCR):基本控制寄存器
好,咱们正式开始看寄存器了。寄存器0,也就是 BMCR(Basic Mode Control Register),是 PHY 芯片里最核心的控制寄存器之一。基本上你第一次上手一个 PHY,第一步要读写的多半就是它。
我习惯叫它“总开关”。你想让 PHY 复位?靠它。想切速率、改双工模式?也是它。想开启环回测试?还是它。说白了,整个链路层的协商策略,都得通过 BMCR 来下达指令。
3.1 BMCR 位域总览
BMCR 是一个 16 位的寄存器,地址偏移为 0x00。它的复位值通常是 0x1000(具体看芯片,但自动协商使能位默认置 1 是通用做法)。我把每个位域的定义整理成了下面的表格,你可以对照着看:
| 位域 | 名称 | 说明 | 复位值 |
|---|---|---|---|
| 15 | Reset | 软件复位,写入1立即复位,完成后自清零 | 0 |
| 14 | Loopback | 环回使能,1=内部环回模式 | 0 |
| 13 | Speed Selection (LSB) | 速率选择低位,与位6组合使用 | 0 |
| 12 | Auto-Negotiation Enable | 自动协商使能,1=开启 | 1 |
| 11 | Power Down | 省电模式,1=进入掉电状态 | 0 |
| 10 | Isolate | 隔离模式,1=电气隔离 | 0 |
| 9 | Restart Auto-Negotiation | 重启自动协商,写入1触发,完成后自清零 | 0 |
| 8 | Duplex Mode | 双工模式,1=全双工,0=半双工 | 0 |
| 7-6 | Collision Test | 碰撞测试使能(很少用,通常写0) | 0 |
| 5-0 | Speed Selection (MSB) 及其他 | 预留或厂商自定义,读取通常为0 | 0 |
关键复位值:位12(Auto-Negotiation Enable)默认置1,意味着大多数PHY上电后第一件事就是开始协商。如果你不想走协商,就必须先清掉这个位,再手动配速率和双工。
3.2 关键位域深度解析
3.2.1 位15:Reset——软件复位
这个位很简单。写入 1,PHY 内部就会执行一次完整的硬件复位流程,所有寄存器和状态机回到初始态。操作完成后,硬件会自动把这位清零。千万别傻等,要用轮询的方式确认:
// 伪代码示例:触发软件复位
phy_write(BMCR, 0x8000);
do {
status = phy_read(BMCR);
} while (status & 0x8000); // 等待自清零
我个人习惯,每次改关键配置前都会先发一次软复位,确保 PHY 状态干净。有时候 NG 了,把这一套复位+重配流程跑一遍,问题就解了。
我曾经踩过坑:连续两次写入复位位,中间间隔太短,PHY 根本没完成第一次复位流程,导致第二个复位信号被忽略。后来我强制在两次复位之间加了至少 100ms 延时,再没出过事。
3.2.2 位14:Loopback——环回使能
这个位用来做板级调试。写入 1 后,PHY 内部会把发送数据直接环回到接收路径,不经过网线。我最常用的场景是:验证 MAC 和 PHY 之间的 MII/RGMII 接口是不是通的。环回一发,抓一下 RX 端的数据,有没有问题立马知道。
这里要注意一点:环回模式通常只工作在特定的速率和双工下。有些 PHY 只支持 100M 全双工环回,你在 10M 半双工下开环回,根本没反应。
小提示:环回模式下,链路状态寄存器(BMSR)里的 Link Status 位可能依然是 Up。别被骗了,Ring 是假的。
3.2.3 位12:Auto-Negotiation Enable——自动协商使能
这一位是整个 BMCR 里最容易被误解的。很多新手以为置 1 就能自动协商成功。其实它只是“使能了自动协商功能”,能不能协商出结果,还得看对端支不支持,以及双方的能力集有没有交集。
我建议:只要链路两端都支持协商,就尽量保持这个位为 1。虽然手动硬编码速率和双工看着更“可控”,但遇到不同厂家设备混插时,自动协商的兼容性远比你想象的好。
速率选择的真谛,其实是位13和位6的组合:
| 位13 | 位6 | 速率 |
|---|---|---|
| 0 | 0 | 10BASE-T |
| 0 | 1 | 100BASE-TX |
| 1 | 0 | 1000BASE-T |
| 1 | 1 | 保留(部分PHY用作其它功能) |
3.2.4 位11:Power Down——省电模式
写入 1,PHY 进入低功耗状态,主时钟可能关闭,收发器停止工作。对功耗敏感的产品,比如 IoT 设备,经常需要动态切换这个位。我见过有人写驱动时,在空闲时把 PHY 掉电,有数据来了再唤醒。你想想看,这个位操作不好,坑也不少。有些 PHY 退出掉电后,必须重新配置一次 BMCR,否则会丢包。
注意:掉电模式下,MDIO 接口通常仍然可用。所以配置完 Power Down 后,你还得能读回正确值。如果发现读不回寄存器,赶紧检查一下是不是 MDIO 时序本身就有问题了。
3.2.5 位9:Restart Auto-Negotiation——重启协商
这个位写入 1,会触发一次完整的协商过程。重协商期间,Link 会中断。如果你正在跑业务流量,千万别随手敲一发。我一般在调试阶段才主动调用,产品正常工作时,由链路状态变化自动触发即可。
3.2.6 位8:Duplex Mode——双工模式
1 是全双工,0 是半双工。单独配这个位时,必须同时关掉自动协商(位12清0),否则硬件会以协商结果优先。很多工程师发现配完 BMCR 没生效,一查,原来自动协商还开着,你写的值被覆盖掉了。
3.3 BMCR 的操作流程
下面这张 SVG 图,是我画的一个典型配置流程。你自己对着跑一遍,基本不会出错:
3.4 一些避坑经验
- 写了读不回:写完 BMCR 后务必回读一次。我遇到过 PHY 的 MDIO 时序不满足要求(时钟高电平太短),导致写入不成功。回读可以发现这类问题。
- 自动协商打断业务:如果你通过位9触发重协商,链路会断几秒。在生产中,最好只在链路断掉或者 PHY 初始化时做这个操作。
- 复位后别立刻配:有些 PHY 复位后需要大约 50ms 的稳定时间才能响应 MDIO 操作。如果你复位完马上写 BMCR,写进去的值可能被忽略。
- 厂商自定义位:位5-0虽然有标准定义,但很多厂商会拿来做私有功能。换 PHY 型号时,务必重新看 datasheet,不要直接把老代码搬过来用。
总结一下:BMCR 是 PHY 控制的入口。记住它的复位值是 0x1000(位12=1自动协商使能)。你在调试时,绝大部分链路问题追到 BMCR 这一步就能解决。把今天这张表格、流程和坑记住,后面的寄存器学起来会顺畅很多。