PCIe 协议基础:分层结构、事务层、数据链路层、物理层
做链路均衡之前,得先把 PCIe 的分层架构搞明白。我刚开始接触 PCIe 时,很多人一上来就讲均衡系数,结果连 TLP 和 DLLP 都分不清,调试起来一头雾水。说白了,链路均衡是物理层的活,但你如果不懂它上面两层在干什么,很难真正理解均衡参数为什么这么配。
PCIe 协议栈分三层,从下往上分别是:物理层、数据链路层、事务层。每层各司其职,又相互配合。下面这张图可以帮你快速建立整体印象。
事务层 —— PCIe 的“业务大脑”
事务层是最高层,直接跟软件打交道。你发一个内存读请求,写一个配置空间,或者传一个 IO 消息,最终都会在事务层打包成 TLP(Transaction Layer Packet)。
TLP 的结构不难记:开头是 帧起始(STP),接着是 TLP 头、数据负载(可选),最后是 ECRC(端到端 CRC)。头里包含了事务类型、地址、长度、标签、TC/VC 等信息。我踩过一个坑:有一次调试 FPGA 的 EP,TLP 头的某些 reserved 位没有按规范填 0,结果 RC 直接丢弃了包。嗯,以后再也不敢偷懒不查 spec 了。
事务类型主要有四种:
- Memory 事务 —— 最常用,读写内存映射空间。
- IO 事务 —— 传统遗留,新设计基本不用。
- Configuration 事务 —— 0 类型和 1 类型,用于枚举和配置。
- Message 事务 —— 中断(MSI/MSI-X)、错误报告、电源管理等。
你想想看,链路均衡出了问题,最直观的表现就是 TLP 重传变多、超时甚至链路降速。所以表面上看是事务层报错,根因却在物理层。
数据链路层 —— 可靠的“搬运工”
数据链路层负责在两端端口之间提供可靠传输。它做的事情很实在:接收事务层的 TLP,加上 序列号 和 LCRC,再封装成 DLLP(Data Link Layer Packet)发下去。收到 ACK 后删除副本,收到 NAK 就重传。
记忆口诀: TLP 过数据链路层 = 包身 + 序号 + CRC + 超时重传。没有 ACK 的链路,别想稳定跑。
数据链路层还负责两个关键功能:
- 流量控制(Flow Control) —— 接收方通告缓冲区可用大小,发送方按信用(Credit)发包。我曾经遇到过 RC 端信用值更新太慢,导致 EP 频繁被流控,性能直接腰斩。最后查出来是 DLLP 的信用更新包被物理层丢包了,又绕回链路均衡问题。
- 链路管理与错误检测 —— 包括链路宽度/速度变更协商、错误报告等。
| 功能 | 作用层次 | 常见问题 |
|---|---|---|
| ACK/NAK 重传 | 数据链路层 | 物理层误码导致重传风暴 |
| CRC 校验 | 数据链路层 | CRC 不匹配触发链路恢复 |
| 流量控制 Credit | 数据链路层 | Credit 同步丢失导致链路挂死 |
| 均衡参数 | 物理层电气子层 | 眼图闭合 → 误码 → 重传 → 掉速 |
物理层 —— 最“接地气”的一层
物理层分两大子层:逻辑子层 和 电气子层。逻辑子层负责编解码(Gen1/2 用 8b/10b,Gen3 之后用 128b/130b)、数据对齐、扰码。电气子层负责差分信号驱动、链路训练状态机(LTSSM)以及……咱们课程的核心——链路均衡。
LTSSM 里的几个主要状态:Detect、Polling、Configuration、Recovery、L0、L0s、L1、L2。链路均衡主要发生在 Polling 和 Recovery 状态。嗯,这里要注意:Recovery 不光是出错了才进,均衡参数改变也会触发 Recovery 重训。
均衡参数在哪里配?
在链路训练阶段,通过 TS1/TS2 有序集里的寄存器值完成握手协商。Gen3 开始,每次均衡都需要 RC 和 EP 交换 Preset、Hint、系数向量等。
层间协作 —— 一个完整的读写例子
假设软件发起一次 Memory Read 请求,你猜猜各层怎么配合?
- 事务层: 构造 Memory Read TLP(含地址、长度、Tag),发给数据链路层。
- 数据链路层: 加上序列号、LCRC,同时检查信用是否足够,排队等待发送。
- 物理层: 逻辑子层做扰码、编码;电气子层通过差分线发送出去,同时保持最佳的均衡系数以保证信号质量。
对端端口物理层先收信号,电气子层做均衡、时钟恢复,逻辑子层解码、解扰;数据链路层检查 LCRC,发回 ACK DLLP;事务层解析 TLP 头,去内存取数据,再原路返回 Completion。
你看,链路均衡不好,物理层采样就错,数据链路层 CRC 校验失败,重传不断。曾经我调一个 Gen3 x8 的板子,跑 memtest 总报 bus error,排查了三天,最后发现是 Preset 2 的均衡系数给错了。所以说,搞链路均衡,必须先懂层间关系。
避坑提醒: 不要只盯着物理层调参数。有时候事务层流量控制 deadlock、数据链路层 credit 溢出,表现也是链路不稳定。这时候调整均衡系数等于白费功夫。我的习惯是先用逻辑分析仪抓 DLLP 异常,确认是误码导致的重传,再去碰均衡。
至此,PCIe 的分层骨架你已经清楚了。下一节咱们会深入物理层的均衡机制——Preset、系数、握手时序,都是从这三层协作的视角展开的。
(本课内容基于 PCIe Base Specification Rev 5.0,v1.0)