2. Polling 状态机详解:进入条件与时序归纳

链路训练刚开始,第一个真正有戏份的状态就是 Polling。别小看它,很多莫名其妙的链路卡顿,根因就在这儿。我个人习惯是先看状态机到底怎么跳进来的,再看它在里面怎么转,最后才是超时和退出。顺序对了,定位问题才能快。

2.1 进入 Polling 的前置条件

从 Detect 状态出来后,链路已经完成了阻抗检测和去抖。这时候两个方向上的 Receiver 都检测到电气空闲退出(Electrical Idle Exit),并且各自至少收到一个有效的 FTS 序列。说白了,物理层已经握手确认——对面确实有颗活着的芯片。

为什么会强调“至少一个 FTS”?我在项目中遇到过一种情况:链路明明能跑,但 Gen4 死活训练不过,抓 Link EQ 日志发现 Receiver 检测逻辑认为没退出电气空闲,导致反复回退到 Detect。后来定位是 RC 端的去抖阈值设置偏大,FTS 被当噪声滤掉了。这个坑我后面会再提。

进入 Polling 的完整条件可以归纳为下面几条:

  • Detect.Quiet 状态中检测到接收器存在
  • Detect.Active 状态完成了电气空闲退出检测
  • 至少收到一个有效的 FTS 序列
  • 无电气空闲重新进入(否则回退到 Detect)

嗯,这里要注意:很多平台实际实现中,FTS 检测窗口只有几个微秒。如果对端发送器刚上电时序抖动偏大,很可能第一个 FTS 就丢了。所以调试时我会先看寄存器里 Polling 进入次数,如果反复进入,十有八九是 Detect 阶段留下的尾巴没扫干净。

2.2 Polling 的子状态流转

Polling 不是一站到底。它内部拆了四个子状态,每个干不同的事。

核心图:Polling 状态机子状态流转与关键检查点
Polling 状态机子状态流转图 Polling.Active 发送/接收 TS1 序列 Polling.Configuration 交换 TS1/TS2,协商 Lane Polling.Speed 升速协商,速度切换 收到 8 个 TS1 收到 TS2 回环 Polling.Compliance 仅用于测试 / 调试验证 未收到有效 TS1 且超时 → Configuration.Lanenum 速度协商完成后跳转 速度协商完成 调试要点 1. Polling.Active 是入口,所有 TS1 交换从这里开始 2. Compliance 是测试分支,正常训练不会走这边 3. Speed 完成后必须收到 Configuration.Lanenum 才能继续 4. 任一步骤超时都会回退到 Detect.Quiet

2.3 子状态逐个拆解

2.3.1 Polling.Active

这是第一个落脚点。两端设备都开始发送和接收 TS1 有序集。每个 TS1 里包含了 Link Number、Lane Number、Speed 等信息。你想想看,如果这一阶段收不到 8 个连续的 TS1,状态机就不会往 Configuration 跳。

我踩过的坑是:某款 FPGA 开发板的 TS1 序列里 Link Number 设成了 0xFF,而对接的 Root Complex 要求范围 0~31,结果一直停在 Active 不前进。最后用分析仪抓波形才发现 TS1 里 Link Number 字段全是 F。所以调试时我建议先检查 TS1 内容,不要只看有没有收到。

2.3.2 Polling.Configuration

收到 8 个 TS1且 其中有 2 个是回环匹配的,就进入 Configuration。这个子状态的作用是进一步确认 Lane 的编号和排列。之后会发送 TS2,并期望收到对方的 TS2 回环。如果这一步 TS2 收不对,链路会一直在这里兜圈。

2.3.3 Polling.Speed

这是处理速率协商的地方。如果两端都支持 Gen3/Gen4,就会在这个状态里完成升速。注意,升速过程中 TS1/TS2 的发送速率会切换。我记得在 Gen4 早期芯片里,Speed 状态切换时的 PLL 锁定时间差异导致大量链路训练失败。

2.3.4 Polling.Compliance

这个分支只有调试或测试时才会走进来。正常链路训练不会走这里。如果状态机进了 Compliance,要么是软件强制设了 Compliance 模式,要么是硬件在 Active 阶段收不到有效 TS1 后超时进入作为兜底。实际项目中很少见,但一旦见到,基本可以确认对端发送器有问题。

2.4 关键时序参数归纳

Polling 阶段有一组时间参数决定了“等多长时间才算完”。这些参数在 Spec 里有,但不同芯片的实际实现可能会有偏差。我把最关键的列出来。

时序参数 典型值 说明
Polling Active 超时 12 μs 从进入 Active 开始计算,必须在此时间内收到有效 TS1
TS1 序列间隔 ~ 如单 Lane 每次约 20 UI 每个 TS1 长度固定,连续发送需满足最小间隔
FTS 序列要求 Gen1/Gen2:至少 2 个 FTS Detect 阶段遗留要求,Polling 入口需保证已经完成
Speed 切换稳定时间 按具体速率,通常 < 1 μs PLL 重锁和 Rx 均衡训练的硬件开销
Polling 总超时 最大 2 ms(由各实现决定) 超过此时间未完成所有子状态则回退 Detect
个人技巧: 调试时我特别喜欢看 Polling 总超时计数器的寄存器值。如果它频繁归零重置,就能反推出训练到了哪个子状态回退了。配合逻辑分析仪的链路数据,定位效率翻倍。

2.5 Polling 退出条件与常见行为模式

正常退出 Polling 只有一个方向——进入 Configuration.Lanenum。异常退出则有几种:

  • 超时回退 Detect:任一子状态超时都会触发整个 Polling 失败,重新走 Detect。这是最常见的卡顿场景。
  • 进入 Compliance:调试模式,不走正常链路训练。
  • 电气空闲退出:如果链路在 Polling 过程中重新检测到电气空闲,立刻回退。

我整理了一个常见退出模式的速查表,方便你对照波形或寄存器日志快速定位。

Exit 类型 触发条件 后续状态 常见根因
正常退出 Speed 协商完成 → Configuration.Lanenum 时序正常,各阶段都收到预期序列
Active 超时退出 12 μs 内未收到 8 个连续 TS1 → Detect.Quiet 对端未发送 TS1 或 TS1 内容异常
Configuration 超时退出 未收到 TS2 回环 → Detect.Quiet Lane 编号协商不一致,或 TS2 信号质量差
Speed 超时退出 升速过程中 PLL 锁定失败 → Detect.Quiet 时钟源不稳定,或 Rx 均衡配置不匹配
Compliance 模式 软件强制或超时兜底 → 维持在 Compliance/回退 测试模式或对端不可用
避坑提醒: 我曾经调试一个 Retimer 场景,发现每次进入 Polling.Speed 后链路必断。最后定位是升速过程中 Retimer 内部的 Tx 均衡参数未刷新,导致 Gen3 Eye 完全闭合。这种问题只看寄存器很难发现,最好在 Speed 切换瞬间抓一下示波器的眼图。

2.6 调试中值得注意的细节

总结几条自己的经验,给各位参考:

  • Polling 阶段卡住的案子,80% 以上跟 TS1/TS2 内容异常有关。先抓波形确认 Link Number 和 Lane Number 字段是否在合法范围内。
  • 不要只依赖超时计数。有些芯片会在子状态间循环而不出发总超时,你需要 Check 每个子状态的停留时间。
  • 如果测量到 Polling 持续时间总是接近 2 ms 的上限,说明训练过程非常勉强,链路质量大概率有问题。
  • 速查 TS1 的速率标识位(Speed ID),确认两端是否真的在尝试匹配目标速率。

Polling 是整个训练流程里信息密度最高的阶段之一。把它的状态流转和时序参数吃透,后续排查 Configuration 和 L0 的卡顿会轻松很多。