Detect 状态:链路训练的第一步

各位同学,咱们今天聊的是 LTSSM 里的第一个真正意义上的状态——Detect。为什么说它是第一步?因为在进入这个状态之前,链路可能还处于 Reset 或者刚上电的混乱阶段。Detect 要做的,说白了就是回答一个最基本的灵魂拷问:对面到底有没有设备接在那儿?

我刚开始做 PCIe 调试那会儿,觉得 Detect 不就是测个电平么,有什么好看的。结果有一次,板子回来死活训练不过,最后用示波器一抓,发现 Detect 阶段就卡住了……嗯,咱们先把这个状态吃透,后面踩坑的概率就会小很多。

3.1 进入条件

什么情况下 LTSSM 会跳进 Detect?主要有两种场景:

  • 冷复位(Fundamental Reset)或热复位(Hot Reset)后:这是最典型的情况。芯片刚上电,或者整个链路被强制复位,LTSSM 就从“Reset”状态流转到 Detect,开始探测链路对面的存在。
  • 从其他状态转入:比如在 Polling 状态检测到电气空闲超时,或者 Recovery 失败后,协议规定链路必须回到 Detect,重新开始探测。说白了,遇到搞不定的异常,LTSSM 的“兜底策略”就是退回 Detect 重来一遍。

我个人理解,Detect 就是 LTSSM 的“原点状态”。不管链路走到多深的 L1、L2 低功耗模式,只要退出复位或遇到不可恢复的错误,都会回到这里。

小提示:在实际的硬件设计中,Detect 进入前一般会先清空一些状态寄存器,比如物理层的“接收检测完成标志位”。这样能保证每次进入 Detect 都是一次干净的重置探测过程。

3.2 两个子状态:Detect.Quiet 与 Detect.Active

Detect 不是一步到位的,它内部还分了两个阶段。我习惯把它理解成“先安静地听,再主动地测”。

3.2.1 Detect.Quiet

这个子状态的名字很形象——“安静”。在这个阶段,发送器必须保持 电气空闲(Electrical Idle) 状态。什么意思?就是差分信号 D+ 和 D- 的电压差要在规定的阈值以内,不能有数据翻转。

具体要满足的条件:

  • 发送器驱动电压差必须小于某个阈值(通常为 0V 附近的小范围),称为“Tx Electrical Idle”。
  • 这个空闲状态至少要维持 1ms(毫秒)。为什么要等这么久?你想想看,如果对端还没稳定,你急着发检测信号,测出来的结果可能是错的。
  • 在 Detect.Quiet 期间,接收器处于等待状态,不发送任何信号。

我记得有一次在项目中,就是因为电源纹波太大,导致发送器无法真正进入电气空闲,总是有微弱的电压摆动。结果 LTSSM 一直卡在 Detect.Quiet 出不去,链路训练超时。最后还是靠调整电源去耦电容解决的。

3.2.2 Detect.Active

Detect.Quiet 保持 1ms 之后,链路自动转入 Detect.Active。这个阶段才是“真刀真枪”的探测环节。

具体动作:

  1. 发送器会产生一个 接收检测脉冲(Receiver Detection Pulse)。这个脉冲的幅度和宽度是严格规定的,不能太大,也不能太小。
  2. 脉冲发出后,发送器会测量 电压上升时间 或者 反射特性。简单说,就是看这个脉冲出去后,信号在链路上的“反应”是怎样的。
  3. 如果对端有接收器存在(即交流耦合电容 + 接收端阻抗),脉冲的上升沿会被拉长,电压变化相对平缓。反之,如果链路是断开的或者没有接收器,脉冲的边沿会非常陡峭。

说白了,就是用脉冲的边沿变化率来判断对面有没有“人”。

关键参数(以 PCIe Gen3 为例):
参数值说明
接收检测脉冲幅度600~1200 mVpp差分峰值幅度
接收检测脉冲宽度100~300 ps非常窄的脉冲
测量窗口时间10~100 ns采样上升沿的时间窗口
判定为“有接收器”的阈值上升时间 > 50 ps经验参考值

3.3 电气空闲检测

电气空闲检测在 Detect 状态里太重要了。我再强调一次,Detect.Quiet 阶段的“安静”不是随便说说的,必须严格按照电气空闲规范来。

电气空闲的定义:

  • 差分输出电压 VDIFF 的值小于 0V ± 175mV(即 -175~175mV 范围内)。
  • 共模电压 VCM 稳定在某个参考电平附近(通常为 0V 左右)。
  • 没有数据翻转,即信号保持稳定的直流电平。

为什么精准检测电气空闲这么关键? 我给你举个例子。假设对端设备突然掉电,它的发送器应该进入电气空闲。但如果你的接收器没有正确检测到这个空闲状态,就会误以为链路还正常。链路训练就会永远卡在错误的状态机里。我在调试一款 FPGA 实现的 PCIe 控制器时,就踩过这个坑——因为 FPGA 内部模拟比较器的阈值没校准,导致电气空闲检测一直失败。最后发现是参考电压的电阻分压选错了。

注意:电气空闲检测必须在接收器侧完成。发送器侧进入空闲后,接收器通过检测差分电压是否低于阈值来判断。这个阈值对噪声特别敏感,板级设计时一定要在差分对附近加足够的滤波电容。

3.4 去抖定时器

去抖定时器,英文叫 Deglitch Timer,这个名字很直白——就是为了消除短时抖动,防止误判。在 Detect 状态里,去抖定时器主要用在 Detect.Active 阶段的结束判定 上。

具体机制:

  • 当 Detect.Active 中的接收检测完成后,LTSSM 并不会立刻跳到下一个状态。它会启动一个去抖定时器,等待一段时间(通常是 12ms)。
  • 在这 12ms 内,链路必须持续保持 Detect.Active 完成后的稳定状态。如果期间有任何抖动或干扰,定时器会复位重新计时。
  • 只有去抖定时器倒计时结束,且接收检测结果没有发生变化,LTSSM 才会判定探测成功或失败,然后决定下一步动作。

为什么需要 12ms 这么久? 我个人的理解是:PCIe 链路需要对抗各种电气噪声,比如电源瞬态跌落、地弹、甚至插卡时的机械抖动。12ms 在电子世界里算是很长的时间了,足够覆盖绝大多数瞬态干扰。说白了,就是用时间来换可靠性。

避坑指南:曾经我在一个项目中,为了省成本使用了廉价的参考时钟源,结果时钟抖动让去抖定时器反复复位。链路训练就是过不去。后来换了低抖动的温补晶振,问题迎刃而解。这告诉我们:去抖定时器虽然能防噪声,但如果源头抖动太大,定时器也救不了你。

3.5 Detect 状态流程图

下面这张 SVG 图把 Detect 状态的整个逻辑串起来了。你可以把它当作本章的“思维导图”,边看边回忆刚才讲的内容。

Detect 状态机流程图 进入条件 Detect.Quiet 电气空闲 ≥ 1ms 是否检测到电气空闲? (差分电压 < 175mV) 等待 / 超时 链路异常,返回 Reset Detect.Active 发送检测脉冲,测上升沿 去抖定时器 12ms 稳定后判定结果 成功 → Polling 失败 → 回 Reset 关键时序:Quiet 1ms + Active 探测 + Deglitch 12ms

3.6 小结与个人体会

Detect 状态看起来简单,但它决定了整条链路能不能“活”过来。我做了这么多年 PCIe 调试,总结一句话:Detect 的成功率,本质上取决于物理层电气特性设计的健壮性。电源噪声、参考时钟抖动、耦合电容容差、PCB 走线阻抗——任何一个环节出问题,都会让 Detect 卡住。

最后分享一个我曾经踩过的坑吧。有次调试一个 PCIe 插卡设备,发现每次插入后链路训练都要失败一次,第二次才能成功。抓了波形才发现,第一次插入时 Detect.Active 阶段的接收检测脉冲被机械抖动干扰,去抖定时器反复复位。第二次时插卡已经稳定,训练就过了。后来我在固件里加了一个简单的重试机制:如果 Detect 失败,不立即报错,而是延迟 100ms 后重试一次。这样既不影响兼容性,又省去了硬件改版的麻烦。

好了,Detect 状态我们就讲到这里。记住:Quiet 的等待、Active 的探测、以及 12ms 的去抖保护,这三步是链路训练的基石。搞明白它们,你就能读懂后续所有状态机转换的“第一推动力”了。