Detect状态详解:链路检测的物理层机制与固件干预点

Detect状态,说白了就是PCIe链路训练的“握手阶段”。设备插上去,两边怎么知道对方存在?靠的就是Detect。我刚开始接触LTSSM时,总觉得这步很简单——不就是检测一下有没有设备吗?后来踩过坑才明白,Detect状态里的门道,远比你想的多。

Detect状态分为三个子状态:Detect.QuietDetect.ActiveDetect.Wait。咱们一个一个说。

Detect.Quiet:先安静一下

进入Detect.Quiet时,发送端会做什么?什么都不做。嗯,你没看错,就是保持静默。

为什么要静默?因为要确保链路上没有残留信号。你想想看,如果前一个设备刚断开,链路上可能还有电荷没泄放完。这时候直接发检测信号,结果会被干扰。所以先等一段时间,让链路“安静”下来。

这个等待时间,规范里叫Tx Detection Timer,一般是12ms。我个人习惯在固件里把这个时间设成可配置的,因为不同板卡的寄生电容不一样,有时候12ms不够,有时候又太长。

关键点:Detect.Quiet期间,发送端必须保持电气空闲(Electrical Idle)。接收端则处于未知状态,等待发送端来“摸”它。

Detect.Active:摸一摸,看有没有人

Detect.Active才是真正的检测阶段。发送端会发出一个检测脉冲,然后看接收端的反射回来是什么样子。

原理其实很简单:如果链路上有设备,接收端的阻抗会拉低,反射回来的信号幅度就小;如果没设备,链路是开路的,反射信号就大。通过比较发射和反射的幅度,就能判断有没有设备。

这里有个坑——交流耦合电容。PCIe链路中间有电容隔直,检测脉冲是交流信号,电容会把它传过去。但如果电容老化或者焊得不好,信号衰减严重,就可能误判成“没设备”。

避坑指南:我曾经遇到一个案例,板子冷启动时偶尔检测不到设备。查了半天,发现是电容容值偏小,低温下更明显。后来在固件里加了重试机制,Detect失败后自动再试一次,问题就解决了。

Detect.Active的检测结果有两种:

  • 检测到接收端:进入Detect.Wait
  • 没检测到:回到Detect.Quiet,再试一次

规范里规定,连续检测失败多少次后要报错?嗯,不同版本不一样。Gen1/Gen2是3次,Gen3以后放宽到5次。我个人建议固件里把这个次数做成可调的,调试阶段设大一点,量产时再收紧。

Detect.Wait:等一等,别急

Detect.Wait是一个过渡状态。发送端已经确认有设备了,但还不能直接进入Polling。为什么?因为接收端可能还没准备好。

你想想看,接收端刚上电,内部PLL可能还没锁定,时钟还不稳。这时候发训练序列过去,接收端根本解不出来。所以Detect.Wait的作用就是给接收端一点准备时间

这个等待时间,规范里叫Polling Active State Timer,一般是12ms。但实际项目中,我见过需要等20ms的板卡。所以固件里最好留个余量。

子状态 主要动作 典型时间 固件干预点
Detect.Quiet 保持电气空闲 12ms 可配置等待时间
Detect.Active 发送检测脉冲 ~2μs 重试次数、阈值调整
Detect.Wait 等待接收端就绪 12ms 超时时间、跳过条件

固件干预点:什么时候该出手?

Detect状态看起来是硬件自动完成的,但固件其实有多个干预点。我总结了一下,主要有这几个:

  1. 超时处理:硬件检测超时了,固件要不要重试?还是直接报错?
  2. 阈值调整:检测脉冲的幅度阈值,固件可以动态调整。比如低温环境下,适当提高阈值。
  3. 跳过Detect:某些场景下(比如从L1退出的恢复),可以直接跳过Detect,进入Polling。固件需要配置对应的寄存器。
  4. 状态上报:Detect失败时,固件要记录错误日志,方便后续分析。

个人经验:我习惯在固件里加一个“Detect状态机监控”功能。每100ms读一次LTSSM状态寄存器,如果发现卡在Detect超过500ms,就主动复位链路。这个功能帮我抓到了不少硬件问题。

核心逻辑流程图

下面这张图,把Detect状态的三个子状态和固件干预点串起来了。你可以把它当作调试时的参考。

Detect状态机与固件干预点 Detect.Quiet 保持电气空闲 Detect.Active 发送检测脉冲 Detect.Wait 等待接收端就绪 超时 检测到设备 检测失败,重试 固件干预点 ① 超时处理:硬件检测超时,固件决定重试或报错 ② 阈值调整:动态调整检测脉冲幅度阈值 ③ 跳过Detect:从L1恢复时,可配置直接进入Polling ④ 状态上报:记录Detect失败日志,便于调试 Detect状态是链路训练的第一步,固件干预可以大幅提升兼容性 典型时间线 Quiet(12ms) → Active(~2μs) → Wait(12ms) → 进入Polling

调试小技巧

最后分享几个我在调试Detect状态时常用的方法:

  • 看LTSSM寄存器:大部分控制器都有LTSSM状态寄存器,直接读就能知道当前在哪个子状态。卡在Detect.Quiet还是Detect.Active,原因完全不同。
  • 量一下检测脉冲:用示波器看发送端的差分信号。如果Detect.Active时没有脉冲出来,说明硬件没工作;如果有脉冲但没反射回来,可能是链路断了。
  • 改一下重试次数:调试阶段把重试次数设成10次,看看是不是偶尔能成功。如果10次里能成功1次,说明是时序问题;如果一次都不成功,那就是硬件问题了。

总结一下:Detect状态虽然简单,但它是链路训练的基础。Quiet负责清场,Active负责检测,Wait负责等待。固件在这三个点都可以介入,关键是要知道什么时候该出手,什么时候该放手。

嗯,Detect就讲到这里。下一章咱们聊Polling状态,那是真正开始“握手”的地方。


公众号:蓝海资料掘金营,微信deep3321