2. Detect状态:检测对端设备的存在与电气空闲

好,咱们正式开始啃LTSSM的第一个状态——Detect。

Detect是整个链路训练流程的起点。说白了,就是你的PCIe设备上电或者复位之后,要做的第一件事:看看对面有没有设备接在那儿。如果没有,那后面的所有训练都没有意义。

2.1 Detect状态的核心任务

Detect状态要完成的事情其实很简单,就两件:

  1. 检测对端设备是否存在——通过检测接收器是否终结来判断。
  2. 检测电气空闲状态——判断链路上是否有信号活动。

我个人习惯把Detect比作「敲门」。你敲了门,对方应答了,你才知道屋里有人。如果敲了半天没人理,那要么是空房间,要么是门坏了。

关键点:Detect状态不进行任何数据交换,只做电气层面的检测。它用的是差分信号的电气特性,而不是数据包。

2.2 三个子状态:Quiet → Active → Wait

Detect状态内部又分了三个小阶段。我画了个流程图,你先看一眼整体结构:

┌─────────────────────────────────────────────────────────┐
│                    Detect状态                           │
│  ┌─────────────┐    ┌──────────────┐    ┌───────────┐ │
│  │ Detect.Quiet│───→│ Detect.Active│───→│Detect.Wait│ │
│  │ 发送空闲信号 │    │ 发送检测脉冲 │    │ 等待结果  │ │
│  └─────────────┘    └──────────────┘    └───────────┘ │
│                          │                    │         │
│                          │  检测到接收器终结   │         │
│                          └────→ 进入Polling   │         │
│                                  状态         │         │
│                          │                    │         │
│                          │  未检测到,超时    │         │
│                          └────→ 重试或降级    │         │
└─────────────────────────────────────────────────────────┘

2.2.1 Detect.Quiet

进入Detect状态后,首先进入Detect.Quiet。

这个阶段,发送端会强制输出一个电气空闲(Electrical Idle)信号。所谓电气空闲,就是差分电压维持在0V附近,没有信号翻转。

为什么要先发空闲?

你想想看,如果前一个状态残留了一些信号电平,直接发检测脉冲可能会有误判。Quiet阶段就是「清场」,让链路先安静下来,确保后续检测的基准电压是干净的。

我的经验:我曾经在一个Gen3的项目中遇到过链路训练反复失败的问题。排查了很久,最后发现是Quiet阶段维持时间不够长,导致前一状态的电平没有完全泄放,后续检测脉冲被干扰了。增加Quiet阶段的计时器后,问题解决。这种坑很难找,建议你在调试时重点关注这个时间参数。

2.2.2 Detect.Active

Quiet阶段结束后,进入Detect.Active。这才是真正的「检测」环节。

发送端会发送一个检测脉冲(Detect Pulse),本质上是一对短的差分信号叠加在一个共模电压上。接收端那边通过检测接收器终结(Receiver Termination)的有无,来判断对端设备是否连接。

接收器终结检测有两种常见方法:

检测方法 原理 优点 缺点
阻抗检测法 测量差分线上的阻抗变化 精度高,不易受噪声干扰 实现电路相对复杂
电压摆幅检测法 测量脉冲发射后的电压响应 电路简单 容易受链路线长和寄生电容影响

我记得在早期Gen1/2的设计中,很多厂商用的是电压摆幅法,因为简单。但到了Gen3/4,随着速率提升,阻抗检测法逐渐成为主流。嗯,这也算是一个技术演进的小细节。

2.2.3 Detect.Wait

Active阶段发出脉冲后,进入Detect.Wait。这个阶段是等待检测结果。

  • 如果检测到接收器终结(对端存在),则迁移到Polling状态,开始真正的链路训练。
  • 如果超时仍未检测到终结,则重试。重试有次数上限,超过后进入Detect.Quiet或直接上报失败。

注意:有些低功耗场景下,PCIe设备会被配置为「在Detect.Wait超时后主动进入低功耗状态」,而不是一直死循环重试。具体行为取决于设备的能力和配置空间中的设置。

2.3 电气空闲检测

电气空闲检测是Detect状态另一个重要功能。搞过硬件的人都知道,信号线上的噪声是躲不掉的。尤其是当链路很长或者布板环境复杂时,你可能会在Detect阶段检测到「假的信号」。

PCIe协议规定,电气空闲的判断标准是:

条件1:|V_d+ - V_d-| < 65mV(Gen1/2)
条件2:持续时间超过一定时间阈值(通常为若干个UI,具体值由协议定义)

说白了,就是差分电压幅度要足够小,并且持续足够长的时间,才能被判定为「链路安静了」。

我踩过的一个坑:曾经有一次,我在实验室调试一块板子,发现Detect状态总是异常退出。查了好几天才发现,是电源纹波太大,导致差分线上始终有几十mV的周期性噪声,刚好卡在65mV的阈值附近。电气空闲检测被频繁打断,状态机就乱了。后来在电源上加了一颗去耦电容,问题才解决。所以,Detect阶段的稳定性,很大程度上取决于你的电源完整性设计。

2.4 速度协商与Detect的关系

有人可能会问:「Detect阶段要不要协商速率?」

答案是:不需要。Detect阶段只检测对端是否存在,不涉及任何速率协商。速率协商是在后面的Polling和Configuration阶段完成的。

但是,检测脉冲的发送速度是有讲究的。Detect阶段的检测脉冲通常以2.5 GT/s(Gen1速率)发送,因为这是所有PCIe设备都支持的基础速率。如果你直接用Gen3的速率去发脉冲,老旧设备可能根本识别不了。

重要原则:PCIe的速率协商是「从低到高」的。Detect阶段必须用最低速率进行,确保兼容性。

2.5 信号完整性对Detect的影响

Detect阶段最容易忽视的就是信号完整性(SI)问题。

检测终结的原理,本质上是反射测量法。发送端发出一个脉冲,脉冲遇到对端的接收器终结后,会产生反射波。通过分析反射波的幅度和时间,就可以判断终结是否存在。

但是,如果链路中存在阻抗不连续点(比如连接器、过孔、线宽变化),这些位置也会产生反射,造成误判。

我记得在一个Gen3项目上,因为连接器部分的差分阻抗做到了120Ω(标准是100Ω±10%),结果Detect阶段总是误报「设备不存在」。这条链路上实际是插着设备的,但因为反射波被连接器的阻抗不连续干扰了,检测电路以为是开路。这种问题,往往需要SI仿真才能提前发现。

2.6 小结一张图

我把整个Detect状态的流程和关键判断点总结成下面这张SVG图,你可以保存下来对照着看:

Detect状态迁移与电气空闲检测流程 Detect状态核心流程 上电/复位 Detect.Quiet:发送电气空闲 Detect.Active:发送检测脉冲 检测到终结? 进入Polling状态 重试或降级 电气空闲判定条件 V_d+ - V_d- < 65mV 且持续超过阈值