3、链路训练状态机(LTSSM)总览:11个状态跳转与触发条件
LTSSM 这玩意儿,说白了就是 PCIe 链路训练的「总导演」。从复位开始到链路稳定,每一步该干什么、出了错怎么退、什么时候往前跳,全由它说了算。我最早啃 SPEC 时对着状态图看了三天才理清,后来在逻辑分析仪上抓过实际跳转,嗯,发现 SPEC 画的图跟现实还是有那么点差距的——后面我会讲到。
3.1 11 个状态是哪些?
LTSSM 定义了一套有限状态机,总共 11 个状态。它们分成四大类:
- 检测(Detect):物理链路是否存在?
- 轮询(Polling):收发器基本通信能力测试。
- 配置(Configuration):协商速率、宽度、反向等。
- 恢复(Recovery):链路坏了想重连、或者要改速率。
- 正常工作(L0、L0s、L1、L2):跑数据的省电模式。
我把所有状态列出来,方便你对照着记:
| 状态编号 | 状态名 | 归属类别 | 一句话作用 |
|---|---|---|---|
| 1 | Detect | 检测 | 检测对端是否存在(靠接收检测电路) |
| 2 | Polling | 轮询 | 发送 TS1/TS2 训练序列,建立 Bit Lock 和 Symbol Lock |
| 3 | Configuration | 配置 | 交换链路配置信息,完成宽度/速率协商 |
| 4 | L0 | 正常 | 链路完全正常工作,数据随便跑 |
| 5 | L0s | 正常 | 单方向低功耗,另一方向还醒着 |
| 6 | L1 | 正常 | 两方向都低功耗,需要唤醒退出 |
| 7 | L2 | 正常 | 深度休眠,连主电源都可能关 |
| 8 | Recovery | 恢复 | 链接质量下降或要改速率时重新训练 |
| 9 | Hot Reset | 复位 | 收到复位命令后重置链路状态 |
| 10 | Loopback | 测试 | 发环回数据用于测试(平时很少见) |
| 11 | Disable | 禁用 | 链路被强制关闭,不再训练 |
我在一次硬盘接口兼容性测试里,碰到过链路反复在 Polling 和 Configuration 之间来回跳,最后发现是 SerDes 的 CDR 锁定时间太长,导致训练序列没来得及对齐。那次排查让我彻底记住了这几个状态的前后顺序。
3.2 核心跳转路径——从清零到跑数据
一个典型的从复位到 L0 的路径是这样走的:
- Detect → 发送方定期发出脉冲,接收侧检测到 RC(接收检测) 信号就认为链路存在。
- Polling → 两边互发 TS1/TS2,完成 Bit Lock(位锁定)和 Symbol Lock(符号锁定)。这一步我们上一章刚讲过。
- Configuration → 通过 TS2 中的配置字段协商:8GT/s 还是 16GT/s?Lane 宽度是 x4 还是 x8?
- L0 → 配置完成,双方发 EIOS 进入正常数据流。
你可能会问:如果中途出错怎么办?比如 Polling 阶段收不到正确的 TS 序列?
LTSSM 的设计思想是「出错了就回退重试」,但不会退太多。具体的超时和重试次数在 SPEC 里都有规定。我记得有一个项目,FPGA 的 GTY 收发器在 Configuration 阶段因为 PLL 锁定抖动太大,导致链路在 Recovery 和 Configuration 之间死循环,最后我们不得不在 FPGA 里手动加上了一个 training retry counter——嗯,那是跟芯片工程师一起熬夜调出来的「土办法」。
PHY_STATUS 和 LINK_UP 信号。很多时候硬件已经跳进了 L0,但 LinkUp 没拉起来——那是内部状态寄存器的同步问题。
3.3 11 个状态的完整跳转图
下面这张 SVG 图展示了 LTSSM 核心状态之间的典型跳转关系。注意我只画了常规路径(为了可读性),SPEC 里的完整跳转有几十条,别被吓到。
3.4 触发条件:什么时候跳?
每个跳转背后都有明确的触发条件,我挑几个容易迷糊的讲一下:
- Detect → Polling:Receiver Detect 成功,只要任一条 Lane 检测到对端存在就跳(不要求所有 Lane)。
- Polling → Configuration:收到连续 8 个训练序列(TS1 或 TS2)并且 Symbol Lock 已经建立——注意,这里要求所有 Lane 都锁定了才跳。
- Configuration → L0:双方都完成了速率和宽度协商,并且发送了 EIOS(进入空闲状态序列)。
- L0 → Recovery:任意一条 Lane 的误码率高于阈值,或者收到对端发的训练序列。
有一个坑很多人踩过:Configuration 阶段有个“Equalization Phase”,在 8GT/s 以上必须做,如果主控端没发 Equalization TS2 或者 PHY 不支持,链路就会卡在 Configuration 里超时,然后跳回 Detect。我遇到过一块国产 SSD 控制器,它的 PHY 只支持到 5GT/s,插到 16GT/s 的槽位上就一直 Detecting→Polling→Configuration→Detect 循环,跑不起来。
Speed Change 标志位,能马上定位问题。
3.5 我在项目中用的速查表
下面这个表我每次写训练程序前都会瞄一眼,它把“常见问题→可能卡的状态→典型根因”列出来了:
| 现象 | 停留状态 | 常见根因 |
|---|---|---|
| 链路从未拉起 | Detect | 接收检测电路故障、对端未上电、REFCLK 不对 |
| 一直发 TS1 没反应 | Polling | CDR 未锁定、差分信号摆幅小、PCB 走线过长 |
| 反复进入 Recovery | Recovery → Polling | 信号完整性差、ESD 击穿、插入损耗超标 |
| 训练完成但数据错误 | L0 | DP/N 极性接反、Lane 映射错误(多见 x4/x8 配置) |
我个人习惯是把这张表贴在调试工位的墙上。有一次一个同事调了一整天没法让 NVMe SSD 被识别,我过去看了一眼——嗯,逻辑分析仪显示链路卡在 Polling,再查 CDR 锁定时间,发现 REFCLK 有 100ppm 频偏。调了时钟源的配置后,第一次训练就进了 L0。
LTSSM 总览就讲到这里。下一小节我们会深入每个状态的内部细节,特别是 Polling 阶段 Bit Lock 到 Symbol Lock 的微观过程——那才是真正的“坑”所在。