第4章 链路训练的初始化过程:复位、检测、配置

各位做PCIe的兄弟,链路训练这事儿,说白了就是让两端的设备互相认个门。系统上电之后,信号还在乱飘,两个端点根本不认识彼此。必须一步一步来:先让它们知道对方存在(检测),再对齐数据(位锁定、符号锁定),最后谈好通道宽度和工作频率(配置)。这章我就把最开始的这几个阶段掰开揉碎跟你讲清楚。

4.1 复位

复位是整个链路训练的起点。没有干净的复位,后面全白搭。PCIe的复位体系其实挺讲究,三种复位场景必须分清楚:

  • Fundamental Reset(基本复位):上电、冷重启或拉低PERST#管脚。这个复位会把整个PCIe逻辑清空,LTSSM(链路训练与状态机)回到Detect状态。
  • Hot Reset(热复位):通过发送TS1有序集(Ordered Set)里的热复位比特触发。通常用于软件发起的二级总线复位,不会改变链路速率握手结果。
  • Function Level Reset(FLR):只复位某个PCIe功能,不碰物理层。主要用于虚拟化场景。

我个人的习惯是:排故障时先拿示波器看PERST#波形。这个复位信号必须满足PCIe电气规范里的时序要求——有效宽度至少100微秒,并且在上电稳定后释放。我在项目中遇到过一块FPGA板子,PERST#漏接了上拉电阻,导致每次冷启动都有一半概率训练失败。嗯,这种坑,调过几个板子你就懂了。

关键时序约束:PERST#到REFCLK稳定之间的时间窗口(T_PERST-CLK)必须≥100μs,REFCLK稳定后至少再等100μs才能释放PERST#。这是PCIe CEM规范里的硬性要求。

4.2 检测阶段

复位释放之后,LTSSM立刻进入Detect状态。检测干两件事:看看对端有没有接上,以及(可选地)评估一下链路的信号质量。

检测又分成两个子状态:

  • Detect.Quiet:发送端先闭嘴100ms以上(静默周期),确保没有任何之前残留的边沿跳变。这个叫“静默检测”,防止错把噪声当信号。
  • Detect.Active:发送端打出接收器检测脉冲(Receiver Detection pulse)。对面的接收端如果有终端电阻(约50Ω对地),这个脉冲就会反射回来产生一个可测的电压差。内部比较器一比较,就知道对面有人了。

这里有个坑:有些仿真的板卡干扰太大,接收检测脉冲被旁路电容吃掉了,导致发送端一直认为对端不存在。我调试过一个客户板子,就是因为在差分对上加了一对ESD管,结电容太大,把检测脉冲衰减到阈值以下。后来换成了低电容TVS管,问题解决。

检测条件结果下一步状态
检测到接收器存在Receiver DetectedPolling
未检测到接收器No ReceiverDetect.Quiet(循环)或退出
检测超时(约12ms)超时回到Detect.Quiet重新开始

检测成功之后,LTSSM就进入Polling状态。但很多人会把Polling和Configuration搞混,我简单说说区别:Polling是做比特级和符号级同步,Configuration才是讨价还价的阶段。

4.3 配置阶段

配置阶段是链路训练里最复杂、也最容易出问题的一环。它其实包含Polling状态(虽然叫轮询,但已经在做对齐)和Configuration状态(真正协商链路参数)。为了表述清晰,我把它们合在一起讲,因为在实际项目中这两个状态经常连续考察。

4.3.1 Polling——位锁定与符号锁定

进入Polling后,发送端连续发送TS1有序集。TS1里有COM符号(一个特殊的K码)和链路编号、通道编号等信息。接收端收到后,先做位锁定(找到数据流的时钟边界),再做符号锁定(找到8b/10b或128b/130b编码中的符号边界)。

这个阶段失败的原因多半是信号质量太差。我见过一个案例,通道间的skew超标,导致不同lane上的COM符号到达时间差超过了接收端FIFO的容忍值。结果就是位锁定成功,但符号锁定失败,一直卡在Polling里打转。解决方法是调整PCB走线等长,或者在芯片的PHY寄存器里手动加大跨lane的de-skew深度。

调试小技巧:如果链路一直卡在Polling,优先用逻辑分析仪抓TS1的COM符号。检查所有lane是否都能收到COM,并且每个COM后面跟着正确的链路号。如果有lane收不到,大概率是物理层断路或阻抗异常。

4.3.2 Configuration——链路宽度与速率协商

位和符号都锁定后,进入Configuration状态。图4-1展示了从复位到L0的完整初始化流程,重点关注Configuration内部的子状态转换。

PCIe链路训练初始化流程(复位→检测→配置→L0) PCIe 链路训练初始化流程 Fundamental Reset Detect.Quiet(静默100ms) Detect.Active(接收器检测) 检测到接收器? 否 → 返回Detect.Quiet Polling.Active(位/符号锁定) Configuration(链路宽度/速率协商) L0 正常操作 注意:每次复位后必须 从Detect.Quiet开始 不可跳过任何状态。

在Configuration状态内部,设备会发送TS1和TS2有序集来交换链路能力。具体过程是:

  1. Configuration.Linkwidth:双方告知自己支持的lane数量,取最小值决定最终链路宽度(x1、x2、x4、x8、x16等)。
  2. Configuration.Lanenum:为每条lane分配编号(0~n-1),并补偿lane之间的相对位移差。
  3. Configuration.Complete:双方确认参数一致,然后进入L0状态开始正常数据传

如果在这个阶段协商失败,比如一方宣称只支持x1,另一方宣称只支持x16,但实际链路只能跑x4(例如因为PCB只有4根差分对),那么LTSSM会回退到Detect状态重新开始。我记得有一次帮客户分析一个服务器主板,Gen3 x16卡始终只能跑到x8,排查半天发现是插槽的sideband信号(PRSNT1#/PRSNT2#)连接错误,导致接口卡片以为是x8规格。这种硬件设计上的疏忽,你在原理图评审时一定要多看一眼。

注意事项:Configuration阶段的超时计时器是24ms(PCIe Base Spec规定)。如果在24ms内没有完成所有子状态转换,LTSSM会强制回到Detect重新训练。实际调试中可以用PCIe分析仪的链路训练分析功能设置“训练超时触发”,捕获异常时的TS1/TS2交换序列,一看便知是哪一步卡壳。

4.4 实战小结

  • 复位:检查PERST#时序,确保≥100μs有效宽度,REFCLK稳定后再释放。
  • 检测:接收器检测失败的常见原因——过大的ESD电容、终端电阻缺失、差分布线开路。
  • 配置:如果链路宽度不对,先查sideband信号(PRSNT#)和REFCLK频率选择(SRNS/SRIS兼容性)。

链路训练的前三段说难也不难,但出问题往往都是些不起眼的细节。我个人习惯在板卡调通之前先用眼图模式检查所有lane的差分信号质量,因为不管是检测阶段还是配置阶段,信号完整性都是基础。好,接下来你自己做实验时,可以拿一块带PCIe接口的板子,用示波器量PERST#和REFCLK的时序关系,看看是不是符合规范——这是读懂链路训练日志的第一步。