2、Auto-Negotiation 失败:协商状态与寄存器分析

Auto-Negotiation 失败,这是车载 PHY 调试里最常见的“硬骨头”。说它常见,是因为只要线束、连接器、电源或者对端芯片有一点不对劲,最先崩掉的就是它。我自己接触过的项目里,至少有六成的链路不通问题,归根结底都是协商阶段卡住了。

那什么是 Auto-Neg?说白了,就是让链路两端的 PHY 互相打个招呼,确认一下彼此都能支持什么速度、什么工作模式(全双工还是半双工)。车载环境下我们常用 100BASE-T1 或 1000BASE-T1,协议不同,但协商的核心逻辑是差不多的。

核心要点: Auto-Neg 不是靠猜的,PHY 内部有专门的协商状态机。我们要做的就是通过寄存器把这个状态机正在干什么、卡在哪一步给读出来。

认识协商状态机

每一个 PHY 内部都有一个状态机在跑,它负责侦听链路状态、发送协商脉冲、等待对端回应。我习惯把它简化为三步走:

  1. 链路检测 — 物理层信号是不是稳定了?电平是不是正常?
  2. 能力交换 — 两端互相发 FLP 或 NLP 脉冲,告诉对方自己能跑多快。
  3. 确认与完成 — 双方确认达成一致,协商完成,进入数据传输准备状态。

每一步都有对应的寄存器状态来指示。如果你看到协商失败,那一定是这三步里某一步没走通。

协商失败的典型案例

嗯,这里我直接说一个真实排故经历。我记得有一次测试台架上,某以太网节点怎么都通不了。仪器显示物理层已链接,但 ping 不通。我用示波器看波形也没发现明显畸变,最后用读寄存器的方式才发现:

  • PHY 的协商状态一直停留在 能力交换阶段。
  • 它对端始终没有发回有效的确认脉冲。
  • 后来检查发现,对端 PHY 的一个电源纹波超标,导致其协商引擎间歇性复位。

你看,示波器看了半天看不出名堂,但寄存器直接告诉我卡在哪一步了。

如何通过寄存器快速定位

大多数车载 PHY 都遵循 IEEE 定义的基本寄存器格式,但厂商会有扩展。下面这张表是我整理的核心寄存器位,你排查时优先看这些:

寄存器地址 寄存器名称 关键位 含义
0x00 BMCR (基本模式控制) Bit 12 (AN Enable) 1 = Auto-Neg 使能,0 = 强制模式
0x01 BMSR (基本模式状态) Bit 5 (AN Complete) 1 = 协商完成,0 = 进行中/失败
0x01 BMSR Bit 4 (Remote Fault) 1 = 对端报告故障
0x01 BMSR Bit 2 (Link Status) 1 = 物理链路已建立
0x05 ANAR (Auto-Neg 广播器) 技术能力选择字段 查看本地宣告了哪些速率
0x06 ANLPAR (从机能力寄存器) 技术能力选择字段 查看对端宣告了哪些速率
0x14–0x18 扩展状态 (各厂商不同) 具体协商状态码 厂商自定义,能精确指出状态机位置
个人小习惯: 我每次连接完硬件后,都会先读一下 0x01 的 Bit 2 确认物理链路有没有建立。如果这个位是 0,那后面都不用看了,先查硬件连接。

常见失败场景与对应寄存器特征

这里总结几个我在项目中遇到过的模式,你可以当作排查清单来用。

失败场景 寄存器表现 常见原因
物理链路无状态 0x01 Bit 2 = 0,Bit 5 = 0 线缆断路、连接器松动、对端断电
协商不成功,但链路已建 0x01 Bit 2 = 1,Bit 5 = 0 两端速度/模式不匹配、错误码率过高
协商完成,但远端故障位为 1 0x01 Bit 5 = 1,Bit 4 = 1 对端 PHY 自身故障、主端配置错误
本地宣告能力缺失 0x05 读到的能力字段不全 配置引脚焊接问题、内部 EEPROM 加载失败
双方宣告能力正常,但协商反复回滚 0x01 Bit 5 在 0 和 1 之间跳动 电源噪声、时钟抖动、接近电磁干扰
注意避坑: 我曾经遇到过一种情况,BMSR 的 Bit 5 已经为 1(协商完成),但物理层就是跑不起来。后来发现是 PHY 芯片的某个内部 FSM 仍有错误复位,但寄存器没有及时更新。所以读寄存器也不能全信,最好搭配示波器看波形上的准备信号(比如 SQE 测试包)。

排查步骤总结

好了,讲了这么多,我帮你把思路理成一个流程。如果你现在面前有一块协商失败的板子,按下面步骤一步步来:

  1. 读 0x01,确认 Link Status(Bit 2)。 如果是 0,先查物理层线缆、接插件、电源。
  2. 确认 Auto-Neg 是否使能。 读 0x00 的 Bit 12,如果是 0,手动写 1 开启。
  3. 等待并轮询 0x01 的 Bit 5。 给 PHY 一些时间(典型 1-2 秒),监控它是否从 0 变 1。
  4. 如果 Bit 5 始终为 0,去读 0x05 和 0x06。 对比本地宣告能力和对端宣告能力,看是否有一方没宣告出正确的能力。
  5. 如果 Bit 5 变成 1 但链路还是不通,检查 Bit 4(Remote Fault)。 如果为 1,则问题出在对端,查对端的 PHY 状态和配置。
  6. 最后,翻扩展寄存器。 厂商通常会在 0x14–0x18 附近放置详细的协商状态码,精确到“正在等待下一个 FLP”或“收到无效码型”。

这套流程走完,80% 的协商失败问题都能抓到根因。剩下的 20%,可能就是 PCB 布局带来的信号完整性问题或温度导致的漂移——那就得配合示波器和眼图测试了。

给自己加个脚本: 我个人习惯写一个简单的 shell 脚本,通过 MDIO 自动轮询上述那几个关键寄存器,每隔 100ms 打印一次状态变化。排查的时候一边连设备一边跑脚本,比手动一个个读快多了。

Auto-Neg 不是黑盒。你只要学会跟它的寄存器“聊天”,它就会把所有问题都告诉你。下次学员问我“为什么协商失败了”,我会让他先读 0x01,而不是先换线。