3. 链路训练失败常见现象:LTSSM卡死、降速、链路不稳定

调试PCIe链路训练,说白了就是在跟状态机打交道。LTSSM是个很严谨的家伙,每一步都按协议走。但一旦受到EMI干扰,它就乱套了。我调试过的板卡里,链路训练失败的表现大致就三种:卡死、降速、忽快忽慢的不稳定。今天咱们就逐一拆解。

3.1 LTSSM卡死:状态机停在了不该停的地方

卡死是最容易发现的问题。板卡插上后,系统不认设备,或者lspci里根本看不到。我用逻辑分析仪抓LTSSM状态时,发现它锁死在某个状态就是不往前走。

常见卡死位置:

  • Detect.Quiet —— 收不到Receiver Detection信号,根本不知道对面有设备
  • Polling.Active —— TS1/TS2训练序列来回发,但始终无法达成位锁定
  • Configuration.Linkwidth.Start —— 链路宽度协商卡住,比如只认到x1链路但实际是x8
  • Recovery.RcvrLock —— 进入Recovery后重新锁相失败,循环跳转

为什么会卡死?我个人习惯先看时钟。PCIe Reference Clock的抖动如果超标,PLL就锁不住。我记得有个项目,板卡在高温下老卡死在Polling阶段,拿示波器一量,REFCLK的峰峰值抖动到了120ps,远超规范要求的86ps。源头是时钟走线太靠近一颗DC-DC电感,EMI耦合进去了。

避坑指南: 我曾经被一块卡死板卡折腾了两天。每次复位后跑几分钟就卡,后来发现是PCIe金手指的CEM连接器有一根地弹片没焊好,回流路径阻抗高了,AC耦合电容端的共模噪声直接把Receiver的EQ训练打乱了。嗯,这种机械问题跟EMI搅在一起,确实让人头大。

3.2 链路降速:握手时悄悄退回了低速率

降速比卡死更隐蔽。设备能用,但跑在Gen1或Gen2上,明明双方都支持Gen3。你查链路状态,看到的是Speed Negotiation失败了。

降速的本质,是训练阶段的信号质量没通过接收端的眼宽/眼高检查。PCIe协议里有个叫Preset和Coefficient的握手过程——说白了就是发端调整去加重和摆幅,收端说“好了,我看到了”。但EMI噪声会把眼图变胖,收端误以为误码率太高,就主动回退一个级别。

PCIe版本 速率 常见降速原因(与EMI相关)
Gen3 (8 GT/s) 高 CTLE+DFE均衡受窄带EMI干扰,RX眼宽不足
Gen2 (5 GT/s) 中 Preset Cursor值因共模噪声抖动触发最小BER回退
Gen1 (2.5 GT/s) 低 主要靠差分信号摆幅容忍度,EMI影响相对较小

我建议遇到降速时,别急着换芯片。先抓一组PCIe EQ训练过程的寄存器Dump,看看是哪个系数协商失败。有一次我发现是Full Swing阶段的电压裕量不够,改了一下TX De-emphasis参数就解决了——但根本原因还是板上的VRM噪声耦合到了差分对上。

3.3 链路不稳定:间歇性的丢包和重启

这是最磨人的一种。设备可以工作,但时不时掉个Link,然后重新训练。你测一整天可能只出现两三次,跑压力测试时就频繁触发。

小技巧: 我习惯在系统里打开AER(Advanced Error Reporting),看Correctable Error Counter。如果这个计数在每分钟内超过10个,基本可以判定链路裕量不足。配合打EMI测试时就更容易复现。

链路不稳定的EMI根源,往往是周期性的窄带干扰。比如板上的DDR时钟谐波落在PCIe频段内,或者某个异步Buck Converter的开关频率直接骚扰了Reference Clock的PLL带宽。你想想看,DDR4的3200MHz时钟的三次谐波就在9.6GHz附近,正好落在Gen5的16GHz频段二次谐波上——这是个典型的跨频耦合陷阱。

3.4 三种现象的排查优先级

我个人习惯按这个顺序排查:
卡死 → 降速 → 不稳定

为什么?卡死说明基础物理层都没通,先搞定电气完整性。降速是次一级问题,往往跟EQ和共模有关。不稳定最难捉,通常是系统级EMI噪声在特定工作模式下才激活。我从电路板设计角度排了个检查表:

  • 先量REFCLK的频谱,看有没有意外的Clock Spur
  • 再用近场探头扫PCIe差分对的共模辐射点
  • 最后用示波器在CEM连接器处看眼图的抖动分离(RJ vs DJ)
# 一段简单的检查脚本(在Linux下查看PCIe链路状态)
# 查看当前链路速度和宽度
sudo lspci -vvv -s 01:00.0 | grep -E "Speed|Width"
# 查看AER错误计数
sudo cat /sys/bus/pci/devices/0000:01:00.0/aer_dev_correctable
# 触发LTSSM状态Dump(需要内核debugfs支持)
sudo cat /sys/kernel/debug/pci/0000:01:00.0/ltssm_state

重点: 链路训练失败不一定是PCIe IP核的锅。我遇到过一例,CPU端Root Complex的PLL供电纹波过大,导致Gen3的EQ永远无法Lock。换上低噪声LDO后,百分百通过。所以排查时永远从供电质量和时钟质量开始。

下面这张图总结了三种现象的关联关系,我平时画在白板上当debug路线图用:

链路训练失败EMI关联图 链路训练失败现象与EMI关联 EMI / 噪声干扰 现象1: LTSSM卡死 Detect/Polling/Config 位锁定失败 / PLL失锁 现象2: 链路降速 Speed Negotiation回退 EQ系数协商失败 现象3: 链路不稳定 间歇性丢包/重训练 Correctable Error递增 调试核心思路 先从REFCLK和供电找问题 → 再排查差分共模辐射

你看,三种现象其实是同一类问题的不同严重程度表现。EMI噪声大到了打乱PLL锁定阶段,就是卡死;只影响到EQ参数协商,就是降速;噪声强度刚好在裕量边界上跳变,就成了间歇性不稳定。嗯,遇到问题时别慌,按这个框架一步步往下走就行。