4. 标准MII寄存器详解(下):ANLPAR、ANE 与扩展状态寄存器
上一节我们聊了基本控制寄存器和状态寄存器,那些是芯片能跑起来的基础。但真正让两个 PHY 对上话、协商出最佳传输模式的,是自动协商那一套组合拳。今天要讲的三个寄存器,就是自动协商的关键信息载体。
我个人做项目时,常常在联调阶段卡在自动协商上——明明两边都支持千兆,怎么就是协商不上?这时候,抓这几个寄存器的值比看示波器管用多了。
4.1 ANLPAR 寄存器(寄存器 0x05)——读懂对方的“底牌”
ANLPAR 的全称是 Auto-Negotiation Link Partner Ability Register。翻译过来就是:自动协商链路伙伴能力寄存器。它存放的是对端 PHY 通过快速链路脉冲(FLP)发过来的能力宣告。
这个寄存器的位定义和咱们自己的 ANAR(寄存器 0x04)几乎一模一样,只不过这里面的数据是对方发过来的。我简单列一下重点位:
| 位 | 名称 | 含义 |
|---|---|---|
| 15 | Next Page | 对端是否还有下一页需要交换 |
| 14 | Ack | 确认位,对方已经收到了你的能力宣告 |
| 13 | Remote Fault | 对端检测到远端故障 |
| 12-9 | Technology Ability | 技术能力,定义支持的速率与双工组合 |
| 8-5 | Selector Field | 选择字段,通常为 00001 表示 IEEE 802.3 |
| 4-0 | Base Page | 基本页,低位表示 10BASE-T、100BASE-TX 等 |
有一点很关键:Ack 位(bit 14)在协商过程中会翻转为 1,表示对方已经成功收到你的能力宣告。我曾经遇到过一条网线接触不良,Ack 位死活不置 1,排查了半天才发现是线序有问题。
4.2 ANE 寄存器(寄存器 0x06)——自动协商的“扩展控制面板”
ANE(Auto-Negotiation Expansion)寄存器,名字叫“扩展”,实际上更像是一个状态指示寄存器。它的各位告诉你自动协商内部的细粒度状态。很多 PHY 芯片厂商会在它基础上增加一些私有位,但标准位就那么几个。
| 位 | 名称 | 说明 |
|---|---|---|
| 4 | Parallel Detection Fault | 并行检测故障,表示链路伙伴不支持自动协商 |
| 3 | Link Partner Next Page Able | 对端支持下一页交换 |
| 2 | Next Page Able | 本端支持下一页交换 |
| 1 | Page Received | 已收到一个新的能力页 |
| 0 | Link Partner Auto-Negotiation Able | 对端支持自动协商 |
这里面我比较看重的是 bit 0 和 bit 4。Bit 0 告诉你对方是有自动协商能力的正常 PHY,还是老旧设备。Bit 4 如果变成 1,那就麻烦了——说明并行检测失效,常见于对端PHY根本没有发出 FLP 脉冲的情况。
顺便一提,ANE 寄存器通常不需要我们改写,它只读就好。但有个别 PHY 芯片会用它来触发软复位,具体得看数据手册。
4.3 扩展状态寄存器(寄存器 0x0F)——多了一双眼睛
标准 MII 规范里,扩展状态寄存器的地址是 0x0F。它最早被 1000BASE-T 引入,用来报告一些基本状态寄存器里放不下的信息。它的位定义各家厂商会有差异,但核心的几位是通用的:
| 位 | 名称 | 含义 |
|---|---|---|
| 15 | 1000BASE-T Full Duplex | 如果为 1,表示本端支持千兆全双工 |
| 14 | 1000BASE-T Half Duplex | 千兆半双工支持 |
| 13 | 1000BASE-X Full Duplex | 光纤千兆全双工支持 |
| 12 | 1000BASE-X Half Duplex | 光纤千兆半双工支持 |
| 11-0 | Reserved / Vendor Specific | 保留或芯片私有定义 |
这个寄存器有用在哪?举个例子:基本状态寄存器(BMSR)的 bit 7 只能告诉你是否支持千兆,但具体是千兆全双工还是半双工,你要到扩展状态寄存器里看。我在调试百兆升千兆的兼容性问题时,习惯先读 BMSR 确认能力,再读这个寄存器确认具体模式。
4.4 这三个寄存器在自动协商中的“角色分工”
下面这张图帮你理清思路:自动协商过程中,ANLPAR 负责接收对方的“底牌”,ANE 告诉你协商过程中的各种状态,扩展状态寄存器则给千兆能力的细节补充信息。
嗯,这张图把流程串起来了。你想想看:本端PHY和对端PHY通过FLP脉冲交换能力,ANLPAR 负责接收对方的“底牌”,ANE 告诉你交换过程是否顺利(比如并行检测失败),而扩展状态寄存器则在你需要确认千兆模式的时候提供精准答案。读完这三个,你基本就知道链路怎么协商的了。
4.5 实操:怎么用代码读取这些寄存器
下面给出一段简单的伪代码,演示通过 MDIO 接口读取这三个寄存器。注意,实际地址偏移需要根据 PHY 和 MDIO 框架做调整。
// 假设 mdio_read 函数已经实现,参数为 phy_addr, reg_addr
// 先检查自动协商完成
uint16_t bmsr = mdio_read(phy_addr, 0x01);
if (!(bmsr & (1 << 5))) {
// 自动协商还没完成,等一会儿再读
delay(100);
bmsr = mdio_read(phy_addr, 0x01);
}
// 读 ANLPAR(寄存器 0x05)
uint16_t anlpar = mdio_read(phy_addr, 0x05);
printf("ANLPAR = 0x%04X\n", anlpar);
// 判断对方是否支持 100BASE-TX 全双工
if (anlpar & (1 << 8)) {
printf("Link partner supports 100BASE-TX full duplex\n");
}
// 读 ANE(寄存器 0x06)
uint16_t ane = mdio_read(phy_addr, 0x06);
if (ane & (1 << 4)) {
printf("WARNING: Parallel detection fault detected!\n");
}
// 读扩展状态(寄存器 0x0F)
uint16_t ext_status = mdio_read(phy_addr, 0x0F);
if (ext_status & (1 << 15)) {
printf("This PHY supports 1000BASE-T full duplex\n");
}
4.6 常见问题与我的排查套路
- ANLPAR 读出来全是 0 —— 大概率是自动协商还没完成,或者对端根本没发 FLP。先确认链路是否有信号,再检查对端是否启动了自动协商。
- ANE bit 4 为 1 —— 并行检测失败。通常是链路质量太差,或者对端是老旧 10BASE-T 设备。我遇到过一次是因为降压芯片的噪声耦合到网口,导致 FLP 报文被淹没。
- 扩展状态寄存器读到 0 —— 这款 PHY 可能不支持千兆,或者扩展状态寄存器被厂商挪作他用。查数据手册最稳妥。
我自己调试时,经常在 PHY 初始化代码后面加一段“诊断模式”,把这三个寄存器的值全部打印出来。连上对端设备,观察数值变化,基本一眼就能看出问题出在哪边。
好了,这一节的内容就到这里。自动协商的核心寄存器已经讲完了,下次如果调试中再遇到协商失败,你知道该从哪里下刀了。