3. Polling状态下的链路发现过程归纳总结

Polling状态,说白了就是链路训练的“握手”阶段。发送端要努力告诉对端:“嘿,我在这里,准备连接了!” 而接收端则需要回应:“收到,我准备好了。” 这个过程看似简单,但很多隐藏问题恰恰就出在这个环节。

我个人习惯把Polling状态拆成两个核心子阶段来看:Polling.Active 和 Polling.Configuration。前者负责“发现”,后者负责“确认”。咱们一个个说。

3.1 Polling.Active:发送端的“广播”与接收端的“检测”

在这个阶段,发送端(我们通常叫它“Master”或“Upstream Port”)会连续发送TS1序列。TS1是一种特殊的数据序列,里面包含了链路训练的关键信息。

个人小经验: 我调试时,会先用逻辑分析仪抓TS1序列。看它是不是在稳定地、周期性地发送。如果序列间隔不均或出现长间隔,那就是板级或时钟问题。

TS1序列里包含几个重要字段,我整理了一个表格,方便大家对照排查:

字段 位宽 说明 排查要点
Link Number 5 bits 标识发送端所在的链路编号 必须为00000(单链路时),否则接收端可能不响应
Lane Number 5 bits 标识发送端在第几条Lane上 从0开始递增,用于接收端做位锁定
PAD 4 bits 填充位,通常为0000 一般不用排查,但异常时可能被误判
TS1 Identifier 8 bits 固定为0xAA(TS1标识) 用于区分TS1和TS2、IDLE序列

接收端在Polling.Active阶段要做的核心事情是:检测到TS1序列,并且完成位锁定(Bit Lock)。什么是位锁定?简单讲,就是接收端通过连续的比特流,找到数据采样的最佳时刻,保证每个bit都能被正确读取。

为什么位锁定会失败?

  • 时钟抖动太大:我遇到过因为PLL电源纹波过大,造成时钟抖动超标,导致位锁定一直失败。换了个更干净的LDO供电就解决了。
  • 通道噪声过高:PCIe的差分信号对噪声很敏感。如果你在PCB上走线太长或没做好屏蔽,噪声会淹没TS1序列。
  • 接收端没有正确上电:有的芯片在复位后需要一定延迟才能进入工作状态。如果发送端太早发TS1,接收端还没准备好。

一旦接收端成功检测到TS1并完成了位锁定,它就开始发送TS2序列作为回应。TS2和TS1结构很像,但标识符不同(TS2是0x55)。发送端收到TS2后,就知道接收端已经就位了。这时,链路会进入Polling.Configuration状态。

3.2 Polling.Configuration:交换配置参数,为后续训练打下基础

这个阶段的核心任务是交换链路的配置参数。这些参数听起来很抽象,但直接决定了链路能跑多宽、多快。

这个阶段里,Master和Slave会互相发送并确认对方参数。核心要交换的参数包括:

  • Lane Number:双方告知对方自己在哪条Lane上发送。
  • Link Number:确认双方在同一链路上。
  • Configured Link Width:协商链路宽度,比如x1、x2、x4、x8。
  • Configured Data Rate:协商速率,比如2.5 GT/s(Gen1)或5.0 GT/s(Gen2)。
  • Training Set Repeat Count:用于同步的计数。

你可能觉得,这些参数不都是芯片自动协商的吗?是的,但硬件的“自动”过程很脆弱。如果一方说“我想跑x8”,另一方说“我只能跑x4”,它们必须找到共同点。如果沟通不畅,进程就会卡住。

我曾经踩过的坑: 有一次,我调试一个x8的插卡,结果链路一直只跑x4。我抓了Polling阶段的配置参数日志,发现Master的“Configured Link Width”寄存器里写成了x4。原因是BIOS里有人把默认宽度设成了x4,没适配新卡。

所以,排查时要检查注册表配置,不要只看硬件。

参数交换通常是通过有序集合(Ordered Sets)中的字段来完成的。具体方式很复杂,但排查时只需关注:接收到的参数是否与预期一致,以及双方是否达成一致。

举个例子,如果Master发来的数据速率是5.0 GT/s,但Slave不支持,它会回复一个“不支持”的标识,然后双方会回退到2.5 GT/s。如果连这个回退都失败,链路就会在Polling.Configuration阶段反复超时。

3.3 链路发现的完整流程(一张图总结)

讲了这么多,我画了一张流程图,方便大家把整个“发现过程”串起来。你从左上角看起,一步步往下走,就会很清楚。

Polling状态链路发现流程图 发送端发送TS1序列 接收端检测TS1,位锁定 接收端回复TS2序列 进入Polling.Configuration交换参数 协商Link Width、Data Rate等参数 训练完成,进入L0状态 位锁定失败怎么办? 检查时钟抖动、通道噪声 参数不匹配,回退协商 检查注册表和PHY能力 如果一直卡在 Polling.Active

你仔细看这张图:从发送端发TS1开始,如果接收端能成功位锁定,流程就走绿色箭头继续走下去。一旦位锁定失败,链路就会在Polling.Active里反复重试,直到超时。我排查时,最喜欢用逻辑分析仪看这个起始阶段:如果TS1发出来了但没看到TS2响应,那问题多半出在接收端。

3.4 常见卡顿点与排查方向

从上面的流程可以看出,卡顿通常出现在以下几个环节。我整理了推荐排查动作,照着做能省不少时间:

  1. 段1:发送端发不出TS1
    • 查电源、时钟是否稳定
    • 查PHY的复位时序(我曾见过复位信号拉得不彻底,PHY一直处于复位状态)
  2. 段2:接收端无法位锁定
    • 用示波器看眼图,检查信号质量
    • 检查接收端的参考时钟是否与发送端同源(不一定必须同源,但抖动要达标)
  3. 段3:参数协商失败
    • 检查两端的PHY寄存器(比如链路宽度能力、速率能力)
    • 检查固件/BIOS设置,看是否有限制

一个我常用的调试技巧:

在Polling阶段,抓RTL中关键状态机的跳转信号。比如,记录下“收到TS1但未收到TS2”、“位锁定失败次数”等计数器。如果计数器的值在快速增长,说明链路上有间歇性问题或噪声干扰。这类问题肉眼很难在示波器上抓到,用计数器最直接。

好了,Polling状态的这两个核心环节咱们就算讲清楚了。链路发现过程,说白了就是“发TS1、位锁定、回TS2、参数交换”这几个关键动作。动作不走错,链路就顺利。一旦在某一步卡住,就按我上面列的表,一步一步查下去,总能找到原因。比漫无目的地改硬件配置强多了。