LTSSM 状态机基础归纳总结

为什么 LTSSM 这么重要?

LTSSM 全称是 Link Training and Status State Machine。说白了,它就是 PCIe 链路的“交通警察”。从上电开始,到正常传数据,再到链路出问题后的恢复,全都靠它管着。

我当年做第一个 PCIe 项目时,遇到链路死活 Link Up 不了,量波形、读寄存器、翻 spec,最后发现是 LTSSM 在 Configuration 和 Recovery 之间来回跳。从那以后,我就养成了一个习惯:不管什么问题,第一件事先看 LTSSM 停在哪个状态。

Hot Reset 这个场景更特殊——它不是从 L0 直接掉下去的,而是需要先通过 Recovery 再进 Hot Reset。如果状态机理解不透,你连它什么时候复位了都不知道。

核心观点:LTSSM 是一切链路行为的地基。抓 Hot Reset,本质就是跟踪 LTSSM 的某一条特定路径。

LTSSM 的核心状态

PCIe 5.0 规范里定义了 11 个状态,但实际工作中我们最常打交道的也就七八个。这里我把它们列出来,你想想看,是不是都见过?

状态16 进制编码一句话说明与 Hot Reset 的关系
Detect0x00检测对端是否存在Hot Reset 结束后可能回到这里
Polling0x01建立比特锁定不直接参与
Configuration0x02协商链路宽度和速率不直接参与
L00x03正常工作,数据收发进入 Hot Reset 的起点
L0s0x04快速省电,可瞬时恢复不影响 Hot Reset
L10x05深度省电不影响 Hot Reset
Recovery0x0A重新训练或切换速率必经之路,Hot Reset 命令在此下发
Hot Reset0x0B复位链路,但不影响配置空间本身就是目标态
Loopback0x0C测试模式无关
Disabled0x0D链路禁用无关

个人习惯:我喜欢把 LTSSM 状态编码记在调试卡的便签纸上。现场抓包时,一眼就能看出当前在哪个环节。

关键状态转换——Hot Reset 是怎么发生的?

正常情况下,链路在 L0 跑数据。如果需要复位链路,有两种方式:

  • 软件触发:Host 写 Bridge Control Register 中的 Secondary Bus Reset 位。
  • 硬件触发:物理层检测到 Hot Reset 有序集(TS1/TS2 中的 hot reset bit)。

无论哪种,LTSSM 都必须先进入 Recovery 状态。Recovery 里会收发 TS 有序集,当双方都确认要 Hot Reset 后,才同步跳入 Hot Reset 状态。在 Hot Reset 里呆够 2 ms 后(也可以更长),再重新回到 Detect 开始重训练。

我遇到过一种坑:系统在 Recovery 里因为速率协商失败,直接回了 L0,根本没进 Hot Reset。你一看寄存器,Hot Reset 位没置上,还以为没触发。其实是因为 Recovery 里的 timeout 导致它“逃跑”了。

注意:Hot Reset 不会清空配置空间寄存器(除了 Bus Master、Memory Space、I/O Space 等控制位),这点和 Fundamental Reset 完全不同。别搞混了。

为什么 Recovery 是 Hot Reset 的“咽喉”?

你可能会问:为什么不直接从 L0 跳进 Hot Reset?

原因很简单——链路状态必须同步。Recovery 阶段双方用 TS 有序集交换意图,确保你也要复位、我也要复位,然后一起跳。如果直接跳,对端还在 L0 发数据,就乱套了。

Recovery 里有个子状态叫 Recovery.Equalization,我之前调试时发现,如果 Equalization 失败,LTSSM 会卡在 Recovery 里反复重试,根本不会去执行 Hot Reset 命令。所以监控时不能只盯着 Hot Reset 状态,得先确认 Recovery 是否顺利通过。

一张图看懂 LTSSM 与 Hot Reset 路径

下面这张 SVG 图把主要状态和转换画出来了。红线标出的就是 Hot Reset 的完整路径,你看一次就能记住。

LTSSM 状态机与 Hot Reset 路径 Detect Polling Configuration L0 Recovery Hot Reset L2 (其它电源态) 接收 TS 后跳转 2 ms 后 正常恢复 📌 说明 红色箭头为 Hot Reset 触发路径:L0 → Recovery → Hot Reset。 虚线表示可选回流路径。实际监控时,重点观察 Recovery 内的 TS 有序集是否携带 Hot Reset 标记。 Hot Reset 结束后链路回到 Detect 重新开始训练。

实战中怎么监控 LTSSM 状态?

最直接的办法就是读 Port Logic 里的 LTSSM State 寄存器(通常叫 PCI_EXP_LNKSTS 或者芯片厂商自定义寄存器)。每个状态对应一个独立 bit,或者用 4-bit 编码。

举个例子,在 Xilinx 的 PCIe IP 里,你可以这样读:

// 假设 base_addr 是 PCIe 配置空间基地址
uint32_t link_status = readl(base_addr + 0x12); // Link Status Register
uint32_t ltssm_state = (link_status >> 16) & 0x1F;

switch (ltssm_state) {
    case 0x03: printf("L0\n"); break;
    case 0x0A: printf("Recovery\n"); break;
    case 0x0B: printf("Hot Reset\n"); break;
    default:   printf("Other: 0x%X\n", ltssm_state);
}

我的做法:我会写一个后台线程,每 1 ms 采样一次 LTSSM 状态,存入环形缓冲。等 Hot Reset 发生后,回放缓冲看前 10 ms 的状态变化。这样 Recovery 的进入和退出细节一览无余。

避坑指南——Hot Reset 场景的几个常见陷阱

  • 误把 Hot Reset 当 Fundamental Reset:我曾经读错寄存器,以为 Hot Reset 清空了所有配置,结果发现 BAR 还在,但 Bus Master 被清了。后来才明白 Hot Reset 只清控制位,不清基址。
  • Recovery 里的 Equalization 失败导致永远不进 Hot Reset:有一回客户报链路复位不生效,我抓了 LTSSM 日志,发现 Recovery 反复倒腾 Equalization,最后超时回到了 L0。解决办法是调大 Equalization Phase 的 timeout 值。
  • 2 ms 计时不准确:有些硬件实现里 Hot Reset 的持续时间是硬编码的,但 spec 允许延长。如果你在 2 ms 后立刻读状态,可能还在 Hot Reset 里,误以为有问题。我的建议是等到 5 ms 以后再看。

警告:不要靠单一寄存器判断 Hot Reset 是否完成。要同时检查 LTSSM 状态、Link Up 状态、以及链路速率是否恢复。三个指标吻合了,才叫真正复位完成。