Detect 状态:原理、跳转条件与调试要点
Detect 状态,说白了就是链路刚上电或复位后,两个设备互相“找对方”的阶段。别的状态都在忙数据交换、电源管理,Detect 只干一件事——确认对面有没有东西插着,以及对方的链路宽度。
我记得刚入行那会儿,第一块 PCIe 板卡死活 link 不起来。翻遍文档,最后发现是 Detect 阶段 Receiver 检测逻辑没使能。从那以后,我调试任何 PCIe 问题,第一件事就是看 LTSSM 是不是卡在 Detect 里。
Detect 在 LTSSM 中的位置
先看一张整体流程图,我把 Detect 相关的几个子状态拎出来,你就能明白它的上下游关系。
从图上你能看到,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 训练的第一把钥匙。