2. PCIe体系结构:分层架构与核心概念
PCIe(Peripheral Component Interconnect Express)采用分层架构设计,从逻辑上划分为三个独立的协议层:事务层(Transaction Layer)、数据链路层(Data Link Layer)和物理层(Physical Layer)。这种分层设计使得各层职责清晰、接口标准化,便于驱动开发和硬件实现。
核心要点:PCIe分层架构的核心思想是对上层透明——设备驱动只需与事务层交互,无需关心数据如何通过链路传输。每一层只与相邻层通信,通过预定义的接口传递包和状态信息。
2.1 事务层(Transaction Layer)
事务层是PCIe分层架构中最上层,直接与设备核心逻辑或驱动软件交互。其主要职责包括:
- TLP(Transaction Layer Packet)生成与解析:将上层请求(如内存读/写)封装为TLP,或从接收的TLP中提取数据。
- 事务分类:支持四种基本事务类型——Memory、IO、Configuration、Message。
- 地址空间管理:处理32位/64位地址映射,支持BAR(Base Address Register)空间访问。
- 流量分类(TC)与虚拟通道(VC):支持QoS(服务质量)区分。
驱动开发提示:驱动通过配置空间中的BAR寄存器获取设备内存/IO基地址后,直接发起Memory Read/Write TLP即可访问设备寄存器或数据缓冲区。事务层自动完成地址到TLP的转换。
TLP包格式简介
TLP是PCIe通信的核心数据单元,其基本格式如下:
| 字段 | 长度(字节) | 说明 |
|---|---|---|
| 前缀(Prefix) | 0/4/8 | 可选扩展,用于未来协议增强 |
| TLP头(Header) | 12/16/20 | 包含事务类型、长度、地址、标签、完成者ID等 |
| 数据负载(Data Payload) | 0~4096 | 可选,最大为4KB(取决于Max_Payload_Size) |
| ECRC(End-to-End CRC) | 0/4 | 端到端校验,可选 |
TLP头格式根据事务类型有所不同,以最常见的Memory Read TLP为例:
Memory Read TLP Header (3DW格式, 12字节):
+--------+--------+--------+--------+
| Fmt[1:0] | Type[4:0] | TC[2:0] | Attr[2:0] |
+--------+--------+--------+--------+
| Length[9:0] | Tag[7:0] |
+--------+--------+--------+--------+
| Requester ID[15:0] | Address[31:2] |
+--------+--------+--------+--------+
- Fmt: 格式编码(00=3DW无数据, 01=4DW无数据, 10=3DW带数据, 11=4DW带数据)
- Type: 事务类型(00000=Memory, 00001=IO, 00100=Configuration等)
- Length: 数据负载长度(以DW为单位,1DW=4字节)
- Tag: 事务标签,用于匹配请求与完成
- Requester ID: 发起者总线号+设备号+功能号
- Address: 目标地址(32位或64位)
2.2 数据链路层(Data Link Layer)
数据链路层位于事务层和物理层之间,负责可靠传输和链路管理。其核心功能包括:
- TLP序列化与重传:为每个发送的TLP分配序列号(Sequence Number),接收方通过ACK/NACK DLLP确认,未确认的TLP自动重传。
- CRC校验:为TLP附加LCRC(Link CRC),接收方校验完整性。
- 流量控制(Flow Control):通过DLLP交换信用量(Credit),防止接收缓冲区溢出。
- DLLP(Data Link Layer Packet)管理:生成和解析链路管理包,如ACK、NACK、PM(电源管理)、FC(流量控制)等。
DLLP包格式简介
DLLP是数据链路层内部使用的短包,长度固定为6字节:
| 字段 | 长度(字节) | 说明 |
|---|---|---|
| DLLP类型 | 1 | 标识DLLP类型(ACK=0x00, NACK=0x01, FC=0x02, PM=0x03等) |
| 数据负载 | 2 | 根据类型不同,包含序列号、信用量或电源管理信息 |
| CRC | 3 | 16位CRC校验(实际使用3字节,含填充位) |
调试注意:当链路出现CRC错误或重传超时时,数据链路层会触发链路错误上报。驱动开发中,如果发现TLP请求无响应,应检查数据链路层状态寄存器(如PCIe STS寄存器中的链路错误位)。
2.3 物理层(Physical Layer)
物理层是PCIe分层架构的最底层,负责比特传输和链路初始化。它分为两个子层:
- 逻辑子层(Logical Sub-block):负责编码/解码(8b/10b或128b/130b)、加扰/解扰、弹性缓冲、通道对齐。
- 电气子层(Electrical Sub-block):负责差分信号驱动/接收、阻抗匹配、去加重、时钟恢复。
PLP(Physical Layer Packet)简介
PLP是物理层内部使用的包,主要用于链路训练和状态管理。常见的PLP类型包括:
- TS1/TS2(Training Sequence 1/2):用于链路训练、位锁定、通道对齐、速度协商。
- SKP(Skip):用于时钟补偿,调整弹性缓冲区。
- EIEOS(Electrical Idle Exit Ordered Set):用于退出电气空闲状态。
PLP不直接暴露给驱动开发,但理解其作用有助于诊断链路训练失败问题。
2.4 差分信号与通道(Lane)概念
PCIe物理层使用差分信号传输,每个通道(Lane)由两对差分线组成:
- 发送对(Tx+ / Tx-):一对差分线,用于发送数据。
- 接收对(Rx+ / Rx-):一对差分线,用于接收数据。
差分信号通过两根线上的电压差(Vdiff = V+ - V-)表示逻辑0或1,具有抗共模干扰、低电磁辐射、高速传输等优点。
Lane宽度与链路带宽
PCIe链路可以配置为×1、×2、×4、×8、×16、×32等宽度。每个Lane提供独立的双向数据传输通道,链路总带宽 = Lane数 × 每Lane带宽。
| PCIe版本 | 每Lane速率(GT/s) | 编码方式 | 每Lane有效带宽(GB/s) | ×16总带宽(GB/s) |
|---|---|---|---|---|
| PCIe 1.0 | 2.5 | 8b/10b | 0.25 | 4.0 |
| PCIe 2.0 | 5.0 | 8b/10b | 0.50 | 8.0 |
| PCIe 3.0 | 8.0 | 128b/130b | 0.985 | 15.75 |
| PCIe 4.0 | 16.0 | 128b/130b | 1.969 | 31.51 |
| PCIe 5.0 | 32.0 | 128b/130b | 3.938 | 63.0 |
带宽计算示例:PCIe 4.0 ×4链路,每Lane有效带宽约1.969 GB/s,总带宽 = 4 × 1.969 ≈ 7.876 GB/s(双向)。驱动开发中,BAR空间映射后的内存访问性能受限于链路带宽和延迟。
2.5 分层架构数据流总结
一个完整的PCIe数据发送流程如下:
- 事务层:驱动发起Memory Write请求,事务层构造TLP(含头+数据+ECRC),传递给数据链路层。
- 数据链路层:为TLP附加序列号和LCRC,生成DLLP(如FC更新),封装后传递给物理层。
- 物理层:对数据进行编码(8b/10b或128b/130b)、加扰,通过差分信号在Lane上逐比特发送。
接收流程相反:物理层解码 → 数据链路层校验CRC、确认序列号 → 事务层解析TLP并交付给驱动。
驱动开发关键点:驱动只需关注事务层TLP的构造和解析,以及通过配置空间获取BAR地址。数据链路层的重传、流量控制和物理层的信号编码对驱动完全透明。但理解分层架构有助于在调试时快速定位问题层次——例如TLP无响应可能是事务层地址错误,也可能是数据链路层链路断开或物理层训练失败。