一、Polling状态:链路训练的第一道关卡

各位工程师朋友,今天我们来聊聊PCIe LTSSM中的Polling状态。说实话,这个状态在平时调试中经常被忽略,但一旦出问题,往往让人抓狂。我个人习惯把Polling状态看作是链路训练的「握手阶段」——双方先打个照面,确认彼此存在,再商量怎么通信。

1.1 Polling状态的目的与进入条件

Polling状态的核心目的就两个:

  • 位锁定(Bit Lock):让接收端能够正确识别每个bit的边界
  • 符号锁定(Symbol Lock):在bit锁定基础上,找到8b/10b编码的符号边界

说白了,就是让发送端和接收端先「对上眼」。只有这两个锁定都完成了,后续的数据传输才有意义。

那么什么时候会进入Polling状态呢?主要有以下几种情况:

  • 从Detect状态成功检测到对端设备后
  • 从L2/L3低功耗状态唤醒后重新训练
  • 链路出现错误需要重新初始化时

嗯,这里要注意一点:Polling状态是LTSSM中唯一一个「必须成功」的状态。如果Polling失败,链路会直接跳回Detect状态重新开始。我在项目中就遇到过因为PCB走线阻抗不匹配导致Polling反复失败的情况,折腾了两天才找到根因。

1.2 Polling.Active与Polling.Compliance子状态

Polling状态内部又分为两个子状态:

子状态 作用 典型行为
Polling.Active 正常训练,完成位锁定和符号锁定 发送TS1/TS2训练序列,等待对端响应
Polling.Compliance 测试模式,用于信号完整性验证 发送固定码型,不期望对端响应

Polling.Active 是我们日常工作中最常打交道的子状态。在这个状态下,发送端会持续发送TS1训练序列,接收端则尝试从中恢复时钟和数据,完成位锁定。

Polling.Compliance 则是个「特殊模式」。你想想看,如果链路硬件有问题,比如信号质量差,正常训练肯定过不去。这时候进入Compliance模式,发送端会发送固定的测试码型(比如D10.2),方便我们用示波器抓波形、测眼图。

小技巧: 我在调试Gen3链路时,经常先让设备进入Polling.Compliance模式,用示波器看眼图是否合格。眼图过关了,再回头排查协议层问题,能省不少时间。

1.3 位锁定与符号锁定过程

这两个锁定过程是Polling状态的核心,我们来拆解一下:

位锁定(Bit Lock)

接收端收到串行数据流后,首先要做的是恢复时钟。这个过程依赖CDR(时钟数据恢复)电路。CDR会不断调整采样相位,直到找到最佳的采样点。

为什么需要位锁定?因为PCIe是串行总线,数据是一bit一bit传过来的。如果没有位锁定,接收端连「这一bit是0还是1」都分不清,更别提后续处理了。

位锁定的时间通常在几微秒到几十微秒之间,具体取决于CDR电路的性能和信号质量。我记得有一次调试,发现某款FPGA的CDR锁定时间特别长,后来查手册才知道是配置寄存器设错了,把CDR带宽设得太窄。

符号锁定(Symbol Lock)

位锁定完成后,接收端已经能正确识别每个bit了。但PCIe数据是以10bit为单位的符号(Symbol)传输的(8b/10b编码)。符号锁定的目的就是找到每个符号的起始位置。

具体做法是:接收端在数据流中搜索特定的逗号序列(Comma Sequence)。对于8b/10b编码,逗号序列是K28.5(即0011111010或1100000101)。一旦找到逗号序列,接收端就知道符号边界在哪里了。

关键点: 符号锁定必须在位锁定之后才能进行。如果位锁定没完成,符号锁定肯定失败。反过来,符号锁定失败也不一定意味着位锁定有问题——也可能是对端发送的码型不对。

1.4 超时与重试机制

Polling状态也有超时机制,这是LTSSM健壮性的重要保障。具体来说:

  • Polling.Active超时:如果在24ms内没有完成位锁定和符号锁定,或者没有收到对端的TS1/TS2响应,就会超时
  • Polling.Compliance超时:通常没有严格超时,但建议在调试时自己加个看门狗

超时后的处理逻辑是这样的:

  1. 计数器加1
  2. 如果重试次数小于某个阈值(通常为4次),重新进入Polling.Active
  3. 如果重试次数达到阈值,跳回Detect状态重新开始
避坑指南: 我曾经遇到过一个案例,某款SSD在Polling阶段总是超时重试4次后跳回Detect,然后再次进入Polling,形成死循环。最后发现是PCB上PCIe参考时钟的走线太长,导致时钟抖动超标。所以,如果发现Polling反复失败,先检查时钟质量,别急着怀疑协议层。

这里我画了一张流程图,帮助大家理解Polling状态的整体逻辑:

Polling状态流程图 Detect状态 检测到对端 Polling.Active 内部子流程 1. 发送TS1序列 2. CDR位锁定 3. 逗号序列符号锁定 锁定成功? Configuration状态 超时? 重试 计数 次数<4? 是(重试) 否(回到Detect) 图例: 正常状态 判定节点 成功路径 失败/超时路径 内部子流程 注:Polling.Compliance为测试模式,不经过此流程

从这张图可以清楚地看到,Polling.Active内部有一个「锁定成功?」的判定节点。如果成功,就进入Configuration状态;如果失败且超时,就进入重试循环。重试超过4次,直接回到Detect重新开始。

这里有个细节值得注意:重试计数器在每次进入Polling.Active时都会递增,但一旦成功进入Configuration,计数器就会清零。所以如果链路质量时好时坏,可能会出现「成功一次,然后失败多次」的情况,这时候计数器不会累积,反而可能导致链路反复震荡。

实战建议: 如果你在调试中看到Polling状态反复进出,建议用逻辑分析仪抓一下TS1序列的交互情况。重点关注:
1. 对端是否回复了TS1?
2. 回复的TS1中是否携带了正确的链路号?
3. 位锁定和符号锁定的时间是否在正常范围内?
这三个问题排查完,90%的Polling问题都能定位。

好了,关于Polling状态我们就聊到这里。下一章我们会深入Configuration状态,看看链路训练中「协商」阶段的具体细节。到时候再跟大家分享一些我在Gen4链路调试中遇到的奇葩问题。


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