LTSSM 状态详解:从 Detect 到 Recovery 的修炼
各位做 Gen4 的小伙伴,链路训练说白了就是 LTSSM 在几个状态间来回跳。我刚开始接触 PCIe 时,看着那十几个状态头都大了。后来才发现,真正和调试密切相关的,也就 Detect、Polling、Configuration、L0 和 Recovery 这几个。其他状态要么是省电用的,要么是特殊场景才会碰到的。
这一章咱们就把这几个核心状态掰开揉碎。我会结合自己踩过的坑来聊,保证你听完就能上手排查。
状态总览:LTSSM 的核心状态机
先看一张我画的逻辑关系图。别嫌简单,链路训练就靠它撑场面。
你可能会问,为什么没把 L0s、L1、L2 画进来?说实话,那些省电状态在 Gen4 链路训练异常排查中碰到的概率很低。我们更关心的是“怎么跳进 L0”和“怎么从 L0 掉出来”。
Detect:发现就是胜利
Detect 是整个链路训练的起点。说白了,就是发送端往差分线路上灌一个脉冲,看对面有没有东西。
- 做的事情:交替发送 Electrical Idle(电气空闲)和检测脉冲,探测接收端是否存在。
- 成功条件:检测到接收器终端电阻,或者收到 TS1 有序集。
- 卡住的原因:端点没上电、差分线断、共模电压不对。
Polling:对暗号阶段
过了 Detect 就进入 Polling。这个状态有四个子状态:Polling.Active、Polling.Compliance、Polling.Configuration、Polling.Speed。
我记得第一次调试 Gen4 时,就被 Polling.Compliance 坑了很久。当时我是想跳过这个子状态直接配置,结果链路不断回滚。
| 子状态 | 作用 | 常见异常 |
|---|---|---|
| Polling.Active | 收发双方交换 TS1/TS2 有序集,做位锁和符号锁 | TS1 没对齐,时钟偏移过大 |
| Polling.Compliance | 让发端进入合规性测试模式(抖动测试用) | 误入该模式导致无法退出 |
| Polling.Configuration | 协商链路宽度、数据速率(Gen1/2/3/4) | 两边协商能力不匹配 |
| Polling.Speed | 完成速率切换(比如从 Gen2 切到 Gen4) | PLL 锁定不上,或者 Tx 再均衡失败 |
我的建议是,在逻辑分析仪上看链路是否长时间维持在 Polling.Compliance。如果超过 2ms,基本可以判断是主机或设备的 TS1 格式有问题。
Configuration:分车道,定速度
Configuration 是链路训练里信息量最大的状态。它要干三件事——分车道编号、协商宽度、协商速度。我个人习惯把这个状态拆成三个子阶段来看:
- 配置 Lane 编号:通过 TS1 里的 Lane Number 字段交换编号信息。
- 宽度协商:确认实际工作的 Lane 数量(x1 / x2 / x4 / x8 / x16)。
- 速度协商:从 Gen1 开始,逐步提升到 Gen4(或降级到 Gen3/2)。
这里容易出问题的地方在于速度协商。Gen4 要求在 24ns 内完成从 Gen1 到 Gen4 的切换,同时对接收端做均衡训练。我见过不少 PCIe 4.0 设备就是因为 TxFFE 系数没调好,在 Configuration 阶段反复回退到 Polling。
在 Configuration 阶段,Root Complex 会尝试 x4 宽度,但设备只回复 Lane 0 和 Lane 1 的编号。这时主机如果发现 Lane 2 和 Lane 3 无应答,会自动降级为 x2。你如果在示波器上看到宽度降级,别慌,这不是错误,是正常协商。
L0:稳定的数据传输态
L0 是大家都想待的状态。说白了,就是所有 Lane 都训练完成,数据包可以正常收发。
但 L0 也不是铁板一块。我遇到过一个案子,设备在 L0 下跑得好好的,突然掉进 Recovery。后来发现是电源纹波太大,导致接收端的 CDR 失锁。这种现象多发于用低端 DC-DC 的 PCIe 扩展卡上。
- 正常退出:进入 L0s(省电)或 L1/L2 睡眠。
- 异常退出:进入 Recovery(最常见),或者直接 Hot Reset。
Recovery:救火队长
Recovery 的地位很特殊。它不是异常状态,而是“尝试修复”的状态。链路在 L0 或 Configuration 中遇到不可纠正的符号错误、电气空闲违规、或者收到 Hot Reset,就会跳进 Recovery。
Recovery 内部也有子状态:Recovery.RcvrLock、Recovery.Equalization、Recovery.Speed、Recovery.Idle。整体思路是——重新锁住接收器、重新做均衡、重新协商速度,如果能成功就返回 L0;如果失败次数超限,就进入 Hot Reset 或 Down 状态。
| 子状态 | 作用 | 我在项目中观察到的典型场景 |
|---|---|---|
| Recovery.RcvrLock | 重新锁相环,找位锁 | 突然的高频噪声导致 CDR 失锁 |
| Recovery.Equalization | 重跑 Gen3/Gen4 均衡训练 | Tx 系数不够优,接收端 CTLE/DFE 无法收敛 |
| Recovery.Speed | 尝试回到原来的速率或降级 | Gen4 链路回退到 Gen3 |
| Recovery.Idle | 等待链路空闲,准备返回 L0 | 正常完成恢复后跳转 |
我建议你在调试时,用逻辑分析仪统计 Recovery 的触发次数和持续时间。如果平均恢复时间超过 1ms,说明均衡参数可能需要手动优化。
其他状态:Hot Reset、Disable、Loopback
这些状态在实战中出现的频率低一些,但我还是忍不住提两个点:
- Hot Reset:当 Recovery 重试次数超限(典型值是 4 次),链路进入 Hot Reset,相当于硬件重启。此时整个链路会回到 Detect 重新来过。
- Loopback:用于测试模式,数据从 Tx 环回到 Rx,不参与正常通信。如果你发现链路卡在 Loopback 出不来,大概率是主机端配置错了 Loopback 触发条件。
你看,LTSSM 的状态并不复杂。核心就五个——Detect、Polling、Configuration、L0、Recovery。你只要掌握了它们之间的跳转条件和常见卡住的原因,就能像个老手一样,对着逻辑分析仪三分钟定位问题。嗯,也不说大话……至少能少走一半弯路。