第3章:Detect状态详解
3.1 进入Detect状态的前因后果
链路训练始于Detect。说白了,这是物理层告诉软件“我插上设备了”的第一步。
当LTSSM从Polling或Configuration状态退回来,或者复位后首次启动,都会落到Detect。我个人习惯把Detect看作“物理握手”的起点——这里不关注速率协商,不关注链路宽度,只关心一件事:对面到底有没有东西?
Detect又细分为三个子状态:Detect.Quiet → Detect.Active → Detect.Wait。每一步都有明确的判断逻辑,任何一个环节失败,训练就会卡死。
3.2 电气空闲检测:你真的空闲了吗?
进入Detect.Quiet后,发送端必须先把TX置于电气空闲(Electrical Idle)。什么是电气空闲?差分电压维持在±0V附近,不再发送任何信号。
我还记得第一次遇到一个案例:某颗芯片在复位后总是无法进入Detect.Active,用示波器量TX引脚,发现差分电压一直有微小的毛刺,始终不满足Idle判定阈值。实际上PCIe规范要求电气空闲的差分电压值必须小于65mV,持续至少一个UI。毛刺导致接收端认为链路还在活动,永远进不了下一步。
- 发送端将TX差分电压拉低至±65mV以内
- 接收端持续检测至少1个UI(一个符号周期)
- 接收端内部认为RX引脚满足Idle条件,才认为电气空闲有效
你想想看,如果链路一端检测到空闲,另一端没检测到,两边状态机就失步了。所以在故障排查时,我建议先用示波器双通道观察差分对,确认Idle电平是否干净。
3.3 阻抗检测:物理接触的“称重”
Detect.Active才是真正的“摸人”阶段。发送端会发出一串检测脉冲(Refresh或Common Mode Voltage变化),然后测量接收端反射回来的阻抗变化。PCIe要求接收差分阻抗为100Ω±15%,如果偏差太大,接收端直接被判为“无效”。
实际项目中我遇到过一个问题:连接器焊接不良,导致单端阻抗漂到60Ω。发送端认为阻抗异常,一直拒绝进入Detect.Wait。后来用TDR(时域反射计)才发现是连接器3号引脚虚焊。
| 阻抗范围 | 判定结果 | 可能原因 |
|---|---|---|
| 85Ω ~ 115Ω | 正常,允许进入下一状态 | 良好焊接、合格PCB叠层 |
| 80Ω ~ 85Ω 或 115Ω ~ 120Ω | 边界值,可能不稳定 | PCB走线宽度偏差、连接器阻抗不连续 |
| < 80Ω 或 > 120Ω | 检测失败,卡在Detect | 短路、开路、电容过大或过小 |
3.4 信号检测逻辑:不止看电平
Detect.Wait是最后一个子状态,等待接收端确认“我确实收到了一个有效信号”。接收端会检测RX差分信号是否超过接收阈值(通常为175mV差分峰值)。但这里有个陷阱:单端噪声也可能触发信号检测。
我曾经在实验室调一块FPGA板,示波器上看RX端差分信号只有100mV,但噪声基底有80mV。接收端误判为有信号,直接跳过了Detect进入Polling。结果Polling阶段反复失败,因为实际信号质量太差。这种“假信号检测”最隐蔽,因为链路层日志里会显示Detect成功,后面才出错。
所以要真正判断信号检测是否可靠,我建议用以下方法:
- 用示波器检测差分信号峰值,确认大于175mV
- 检查共模电压是否稳定在0V ~ 0.6V之间
- 排除电源噪声耦合,必要时加磁珠或电容滤波
如果以上都通过,那么Detect硬件检测基本没问题。
3.5 Detect状态流程图
3.6 故障点归纳总结
我们常遇到的Detect故障就三种,但每种都够折腾半天:
- 电气空闲不达标:TX端发送Idle时残留毛刺,或RX端检测器灵敏度过低/过高。我建议先检查DC耦合电容是否漏电,其次看电源纹波。
- 阻抗检测失败:PCB走线误差、连接器接触不良、外接线缆阻抗不匹配。拿TDR扫一下实体链路,比猜强百倍。
- 信号检测误判:最麻烦。要么是噪声超过175mV导致误触,要么是信号太弱(<175mV)导致漏检。我会用差分探头测眼图,同时看共模噪声。
为什么会卡在Detect?其实核心问题就一个:物理层没建立起最基本的连接。电气空闲、阻抗、信号检测这三者必须全部通过,才能说“物理链路OK”。任何一项出问题,后续所有状态都白搭。
我个人的排障方法很直:先看电气空闲波形,再看TDR阻抗曲线,最后看信号检测阈值。按这个顺序来,基本两三轮就能定位。不要一上来就去翻LTSSM寄存器——寄存器只能告诉你结果,不能告诉你物理层哪根针出问题了。