2. PCIe协议核心概念精讲

PCIe 不是一条“总线”,而是一套分层的高速串行互连协议。理解它的关键,是先建立“分层—包—空间—角色”这条主线:事务从软件发起,经事务层、数据链路层、物理层逐层封装,穿过链路到达对端后再逐层解封,最终落到目标设备的配置空间、内存空间或中断逻辑上。Zynq 的 PS 端 PCIe 控制器正是这条链路上的一个端点或根复合体实现,理解它的角色,才能正确配置 BAR、DMA 与中断。

一、三层架构:谁负责什么

PCIe 从高到低分为事务层(Transaction Layer)、数据链路层(Data Link Layer)和物理层(Physical Layer)。事务层负责生成和解析 TLP(Transaction Layer Packet),处理请求与完成、地址路由、流量控制信用;数据链路层负责 DLLP(Data Link Layer Packet),做 Ack/Nak 重传、CRC 校验和链路状态维护;物理层负责 LTSSM 链路训练、加扰、编码(8b/10b 或 128b/130b)和差分信号收发。分层的好处是:软件只关心 TLP 语义,链路可靠性由下层保证。

在 Zynq 中,PS 端 PCIe 控制器内部同样按这三层组织,并通过 GT(Gigabit Transceiver)与外部链路相连。配置时我们通常只接触事务层可见的寄存器与 TLP 行为,但调试链路问题时必须回到物理层看 LTSSM 状态。

二、TLP 包类型:请求与完成

TLP 是 PCIe 事务的载体,按功能可分为几类:Memory Read/Write(存储器读写,用于访问 BAR 映射的内存或寄存器)、I/O Read/Write(传统 I/O,现代设备少用)、Configuration Read/Write(配置空间读写,枚举阶段使用)、Message(消息,用于中断、电源管理等)、Completion(完成,携带读数据或写确认)。每个 TLP 头部包含 Requester ID、Tag、地址/长度、Traffic Class 等字段,Tag 用于匹配请求与完成。

一个典型流程是:根复合体发出 Memory Read TLP,端点收到后从目标地址取数,再返回带数据的 Completion TLP。若读请求超过 Max_Payload_Size,会被拆成多个 TLP;写请求则可能被合并。理解 TLP 类型,是分析 DMA 吞吐和延迟的基础。

三、配置空间与 BAR

每个 PCIe 功能都有 4KB 配置空间,前 64 字节是标准头,包含 Vendor ID、Device ID、Command、Status、Class Code 等;之后是能力结构(Capability),如 Power Management、MSI、PCIe Capability。配置空间通过 Configuration Read/Write TLP 访问,枚举时由根复合体逐总线、逐设备、逐功能扫描。

BAR(Base Address Register)是配置空间中的关键字段,用于声明设备需要多大地址窗口以及映射到系统内存的哪个位置。BAR 的低位指示是内存空间还是 I/O 空间、是否可预取、是 32 位还是 64 位;高位在写入全 1 后回读,可探测窗口大小。例如某 BAR 回读为 0xFFFF0000,说明窗口大小为 64KB。系统软件随后把基地址写入 BAR,设备即可通过该地址被 CPU 访问。Zynq 作为端点时,BAR 通常映射到 PS 的 DDR 或 OCM 区域;作为根复合体时,则需要为下游设备分配 BAR 空间。

四、DMA 与中断机制

DMA 让设备直接读写主机内存,无需 CPU 逐字节搬运。PCIe 端点通过 Memory Write TLP 把数据写入主机内存,通过 Memory Read TLP 从主机内存取数。Zynq PS 端 PCIe 控制器支持 DMA 引擎,可配置源地址、目的地址、长度和方向,并产生完成中断。实际使用中要注意地址对齐、Max_Payload_Size 和 Max_Read_Request_Size 对吞吐的影响。

中断机制主要有两类:INTx 传统引脚中断(通过 Message TLP 模拟)和 MSI/MSI-X 消息信号中断。MSI 允许设备向特定地址写入数据来触发中断,MSI-X 支持更多向量和独立掩码。Zynq 端通常使用 MSI/MSI-X 以获得更低延迟和更好的多核扩展性。配置时需在配置空间使能 MSI 能力,设置目标地址与数据,并在中断控制器中注册对应处理函数。

PCIe 分层架构与 TLP 事务路径(Zynq PS 视角) 根复合体 (RC) CPU / 系统内存 事务层 生成/解析 TLP 数据链路层 DLLP / Ack-Nak 物理层 LTSSM / 编码 配置空间 BAR / MSI 能力 DMA 引擎 源/目的/长度 PCIe 链路 (Lane 0..N) 差分信号 · 8b/10b 或 128b/130b · 加扰 TLP / DLLP 串行传输 端点 (EP) Zynq PS PCIe 控制器 事务层 解析/生成 TLP 数据链路层 CRC / 重传 物理层 GT 收发器 BAR 窗口 映射 DDR / OCM MSI/MSI-X 中断向量 Memory Read TLP Completion TLP DMA 写内存 DMA 读内存 MSI 中断消息 请求 TLP 完成 TLP DMA 数据流 中断消息

五、Zynq 中的角色:端点与根复合体

Zynq PS 端 PCIe 控制器可配置为根复合体或端点。作为根复合体时,它负责枚举下游设备、分配 BAR 空间、管理中断路由,通常用于连接 NVMe、网卡等外设;作为端点时,它被主机枚举,BAR 映射到 PS 内存,DMA 在主机与 PS 之间搬运数据。两种角色的配置差异主要体现在控制器寄存器、链路训练参数和地址映射策略上。

实际开发中,一个常见教学示例是:Zynq 作为端点,主机通过 BAR0 访问 PS 的 OCM 区域,BAR0 大小设为 64KB,基地址由主机枚举时分配;DMA 配置为从主机内存读取 1MB 数据写入 PS DDR,完成后通过 MSI 向量 0 通知主机。此时需要关注 TLP 的 Max_Payload_Size(例如 128 字节)和 Max_Read_Request_Size(例如 512 字节),它们直接影响 DMA 效率。

学习建议:先用配置空间读写确认设备被正确枚举,再验证 BAR 窗口可访问,最后调试 DMA 与中断。每一步都可用 TLP 抓包工具观察实际包类型与字段,把协议概念落到真实链路上。

总结来看,PCIe 的核心概念可以串成一条链:分层架构决定数据如何封装与传输,TLP 类型决定事务语义,配置空间与 BAR 决定设备如何被系统识别和寻址,DMA 与中断决定数据如何高效搬运和通知。Zynq PS 端控制器既是这条链的执行者,也是我们配置和调试的对象。掌握这些概念,后续的驱动开发与性能调优才有稳固基础。