Detect 状态:原理、跳转条件与调试要点

Detect 状态,说白了就是链路刚上电或复位后,两个设备互相“找对方”的阶段。别的状态都在忙数据交换、电源管理,Detect 只干一件事——确认对面有没有东西插着,以及对方的链路宽度。

我记得刚入行那会儿,第一块 PCIe 板卡死活 link 不起来。翻遍文档,最后发现是 Detect 阶段 Receiver 检测逻辑没使能。从那以后,我调试任何 PCIe 问题,第一件事就是看 LTSSM 是不是卡在 Detect 里。

Detect 在 LTSSM 中的位置

先看一张整体流程图,我把 Detect 相关的几个子状态拎出来,你就能明白它的上下游关系。

Detect 状态位置与跳转关系 Reset / Polling Detect.Quiet Detect.Active Detect.Wait Polling Detect (总入口) (无检测结果) 链路失败 Detect 只做一件事:检测接收端是否有 终端电阻 / 共模电压,判断对面设备是否在线。 Detect 失败→回到 Reset 或重新尝试 Detect 成功→进入 Polling 进行 bit lock 和 symbol lock

从图上你能看到,Detect 并不是单一状态——它内部还有 Quiet、Active、Wait 三个子状态。入口从 Reset 或 Polling 的某些条件流入。说白了,它是链路训练的第一个“守门员”。

Detect 的三个子状态

每个子状态有明确的时间窗口和检测手段。我整理了一张表,方便你对照。

子状态 典型持续时长 发送端行为 接收端行为
Detect.Quiet 12 ms(可超时) 不发送任何信号,等待共模稳定 静默检测,感应终端电阻是否存在
Detect.Active 单次脉冲约 10~20 ns 发出一个短脉冲(类似敲击) 根据回波或反射判断链路状态
Detect.Wait 12 ms 超时 等待更长时间,确认链路不存在 如果仍无信号,判定链路断开

这里有个容易被忽略的点——Detect.Quiet 阶段并不发送任何差分信号。我见过不少调试案例,工程师用示波器去点 PCIe 差分对,发现一根线有波形就以为链路正常了。实际上 Detect.Quiet 阶段波形完全可能是噪声。嗯,踩过这个坑的人不在少数。

跳转条件详解

跳转条件一句话概括就是:检测到有效终端电阻 → 进入 Polling;否则超时 → 回到 Reset 或重新循环。但具体实现中有几个细节很关键。

  • Detect.Quiet → Detect.Active:Quiet 超时(12 ms)后,自动转入 Active 发射检测脉冲。
  • Detect.Active → Detect.Wait:脉冲发出后未检测到有效反射,说明对方不存在,进入 Wait 做最终确认。
  • Detect.Active → Polling:脉冲反射正常,终端电阻匹配,链路宽度可判断 → 跳转到 Polling.Active。
  • Detect.Wait → Detect.Quiet:Wait 超时后仍无信号,链路失败,回退到 Quiet 重新检测(部分实现直接进入 Reset)。

调试要点:几乎所有 Detect 跳转都依赖一个硬件计数器——对 RP(Root Port)和 EP(Endpoint)都一样。超时时长由 PCIe Base Spec 规定,但具体实现可能有 ±30% 的偏差。我习惯在仿真阶段就让固件 dump 出 Detect 阶段的 Timer 值,对比 spec 检查是否符合预期。

常见调试错误与避坑指南

接下来这几个坑,是我在实际项目里反复撞过的,分享给你。

错误 1:共模电压不达标

曾经我有一个 PCIe Gen3 项目,RC 侧 Detect 总是失败。量了差分对波形,发现 Receiver 共模电压只有 0.25V——规范要求 0.45~0.55V。原因是电源退耦电容焊反了。这类问题在原理图 review 阶段如果能加上 Detect 检查 checklist 就能避免。

错误 2:链路宽度检测逻辑错误

8 个 lane 的卡只检测到 1 个 lane 进入 Polling,其余 lane 全部卡在 Detect.Wait。我遇到过,原因是 lane-to-lane 的 skew 超过了 Receiver 容忍范围,导致部分 lane 无法建立共模。解决方法是检查走线等长,特别是时钟和数据之间的飞行时间差。

调试技巧:如果你手上有逻辑分析仪(支持 PCIe 协议解码),直接在 LTSSM 状态机上设 Trigger——当状态从 Detect 跳转到 Polling 时抓取波形。重点看进入 Detect.Active 时刻的脉冲反射波形,反射波幅度 / 时延直接反映终端匹配质量。

说白了,Detect 就三个要点:共模电压、终端电阻、超时计数器。调试时优先排查这三个物理参数,90% 的问题都能定位。剩下那 10% 要么是链路宽度协商失败,要么是 PHY 内部状态机 BUG——那就要往 Expose 和 OT 方向走了。

一个小回顾

我个人建议在项目 bring-up 阶段,写一段简单的固件脚本,定期读 LTSSM 状态寄存器。如果状态长期(>50 ms)停留在 Detect.Quiet 或 Detect.Wait,直接打印告警。这招帮我在两个项目中节省了至少三天调试时间。

Detect 阶段虽然基础,但它决定了整条链路的生死。后面所有的 Polling、Configuration、L0 都要以它成功为前提。掌握 Detect,等于拿住了 PCIe 训练的第一把钥匙。