基于Agilex的PCIe接口DMA传输与驱动调试 - 第2节

2.1 PCIe 拓扑结构:从树形到交换式互联

PCI Express(PCIe)采用点对点串行互联的拓扑结构,彻底取代了传统 PCI 的共享并行总线。在 Agilex FPGA 系统中,理解拓扑是配置 DMA 引擎和进行地址映射的前提。

2.1.1 核心组件与层级关系

一个标准的 PCIe 拓扑由以下四类组件构成:

  • 根复合体(Root Complex, RC):CPU 与 PCIe 域之间的桥梁,负责生成配置请求、管理中断和地址转换。在 x86 平台中,RC 集成在 CPU 内部;在 Agilex 系统中,RC 通常由 HPS(硬核处理器系统)或 FPGA 逻辑中的硬核 PCIe IP 实现。
  • 交换器(Switch):由上行端口(Upstream Port)和多个下行端口(Downstream Port)组成,负责在多个端点之间路由事务包。交换器内部包含一个虚拟 PCI 桥,用于管理总线编号和内存域。
  • 端点(Endpoint, EP):功能设备,如 Agilex FPGA 作为 EP 时,通过 PCIe 接口与 RC 交换数据。DMA 控制器通常位于 EP 内部。
  • 桥(Bridge):用于连接 PCIe 与其它总线(如 PCI、PCI-X),在纯 PCIe 系统中较少见。
Agilex 实战提示: 在 Agilex 开发板上,FPGA 通常配置为 EP 角色。RC 由 CPU 或 HPS 担任。当使用 lspci -t 命令查看拓扑时,Agilex EP 会出现在 CPU 根端口(Root Port)下的某个总线分支中。

2.1.2 拓扑结构示意图

下图展示了一个典型的 PCIe 树形拓扑,包含 RC、Switch 和多个 EP。Agilex FPGA 作为 EP 之一,通过 x4 或 x8 链路连接到 Switch 的下行端口。

PCIe 树形拓扑结构 PCIe 树形拓扑结构(RC → Switch → EP) 根复合体 (RC) 交换器 (Switch) 上行端口 (Upstream) 端点 EP1 (SSD 控制器) 端点 EP2 (Agilex FPGA DMA) 端点 EP3 (网卡) 说明: 每个端点通过独立的点对点链路连接到交换器。Agilex EP 通常使用 x4 Gen3 或 x8 Gen4 链路。 交换器内部通过虚拟 PCI 桥(VPB)管理总线编号,实现不同 EP 之间的隔离与路由。

2.1.3 总线枚举与设备发现

系统上电后,RC 通过深度优先遍历算法扫描 PCIe 总线,为每个设备分配总线号(Bus Number)、设备号(Device Number)和功能号(Function Number)(BDF)。在 Linux 中,可通过 lspci 查看:

# 查看 Agilex EP 的 BDF 信息
$ lspci -s 03:00.0 -vv
03:00.0 Memory controller: Intel Corporation Device 0000 (rev 01)
        Subsystem: Intel Corporation Device 0000
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0
        Interrupt: pin A routed to IRQ 47
        Region 0: Memory at 91000000 (64-bit, non-prefetchable) [size=16M]
        Capabilities: [40] Power Management version 3
        Capabilities: [50] MSI: Enable+ Count=1/1 Maskable- 64bit+
        Capabilities: [70] MSI-X: Enable- Count=8 Masked-
        Capabilities: [a0] Express (v2) Endpoint, MSI 00
        Capabilities: [100] Advanced Error Reporting
        Capabilities: [148] Device Serial Number 00-00-00-00-00-00-00-00
        Capabilities: [158] Power Budgeting <?>
        Capabilities: [168] Secondary PCI Express
        Kernel driver in use: pcie-dma-drv
调试技巧: 如果 lspci 无法看到 Agilex 设备,请检查:1) FPGA 配置是否完成(DONE 灯是否亮起);2) PCIe 参考时钟是否稳定;3) 链路训练状态机(LTSSM)是否进入 L0 状态。可使用 setpci 直接读取配置空间寄存器进行诊断。

2.2 事务层(TLP):PCIe 通信的核心协议

事务层是 PCIe 分层架构中最上层,负责将来自软件或 DMA 引擎的读写请求封装成事务层包(Transaction Layer Packet, TLP)。TLP 是 PCIe 通信的基本单元,所有数据交换(包括配置、内存、I/O 和消息)都通过 TLP 完成。

2.2.1 TLP 格式与字段

一个标准的 TLP 由头部(Header)、数据负载(Data Payload)和可选的ECRC(端到端 CRC)组成。头部长度根据地址类型分为 3DW(双字,12 字节)或 4DW(16 字节)。

字段 位宽 描述
Fmt 2 bits 格式:00=无数据 3DW, 01=有数据 3DW, 10=无数据 4DW, 11=有数据 4DW
Type 5 bits 事务类型:MRd(内存读)、MWr(内存写)、Cpl(完成)、CplD(带数据完成)等
TC 3 bits 流量类别(Traffic Class),用于 QoS 管理
TD 1 bit TLP Digest 存在标志(ECRC)
EP 1 bit 中毒位(Poisoned),指示数据负载损坏
Attr 2 bits 属性:顺序模型、宽松排序、无侦听等
Length 10 bits 数据负载长度,单位是 DW(双字),最大 1024 DW
Requester ID 16 bits 请求者 BDF(Bus:Device:Function)
Tag 8 bits 标签,用于匹配请求与完成
Address / 1st DW BE 32/64 bits 目标地址(内存/配置)或第一个双字的字节使能

2.2.2 内存读写事务流程

在 DMA 传输中,最常用的是内存写(MWr)和内存读(MRd)事务。以 Agilex EP 向 RC 内存写数据为例:

  1. EP 发起 MWr TLP:头部包含目标地址(RC 侧内存地址)、数据负载(DMA 数据)、请求者 ID(EP 的 BDF)和 Tag。
  2. Switch 路由:根据地址范围将 TLP 转发到 RC 的上行端口。
  3. RC 接收:将数据写入系统内存,并可选地返回完成(Cpl) TLP(对于 Posted 写,无需完成;对于 Non-Posted 写,需要完成)。
关键概念:Posted vs Non-Posted 事务
Posted 事务(如 MWr):发送后不需要接收方返回完成包,吞吐量高,但无错误反馈。
Non-Posted 事务(如 MRd、配置读写):必须等待完成包(Cpl/CplD)返回,延迟较大但可靠性高。
DMA 写通常使用 Posted 事务以获得更高性能;DMA 读必须使用 Non-Posted 事务。

2.2.3 TLP 路由方式

PCIe 支持三种 TLP 路由机制,由头部中的路由字段决定:

  • 地址路由(Address Routing):用于内存和 I/O 事务,根据目标地址进行路由。这是 DMA 传输中最常用的方式。
  • ID 路由(ID Routing):用于配置事务,根据 BDF(总线:设备:功能)进行路由。配置读写必须使用 ID 路由。
  • 隐式路由(Implicit Routing):用于消息事务(如 INTx 中断、电源管理事件),由消息类型隐式决定目标。
TLP 路由方式对比 TLP 三种路由方式对比 地址路由 内存 / I/O 事务 根据目标地址转发 DMA 传输默认方式 ID 路由 配置事务 根据 BDF 转发 枚举 / 配置空间访问 隐式路由 消息事务 由消息类型决定目标 中断 / 电源管理 Agilex DMA 路由选择: 1. 内存读写(DMA 数据传输)→ 地址路由,目标地址为 RC 侧物理地址。 2. 配置空间访问(驱动初始化)→ ID 路由,目标为 EP 的 BDF。 3. MSI/MSI-X 中断 → 隐式路由(内存写事务,但目标地址由 MSI 配置寄存器指定)。

2.3 数据链路层与物理层:可靠传输与电气连接

数据链路层和物理层位于事务层之下,共同保证 TLP 在物理链路上的可靠传输。理解这两层有助于诊断链路训练失败、比特错误和链路带宽问题。

2.3.1 数据链路层(Data Link Layer)

数据链路层的主要职责包括:

  • TLP 序列化与重传:为每个 TLP 分配序列号(Sequence Number),并附加 LCRC(链路 CRC)。接收方通过 ACK/NAK 协议确认或请求重传。
  • 数据链路层包(DLLP):用于链路管理,包括 ACK/NAK、电源管理、流控制(Flow Control)等。DLLP 不暴露给事务层。
  • 流控制(Flow Control):通过信用(Credit)机制防止接收缓冲区溢出。每个 VC(虚拟通道)独立管理信用。
DLLP 类型 功能 方向
ACK 确认已正确接收 TLP,释放重放缓冲区 双向
NAK 请求重传损坏或丢失的 TLP 双向
InitFC1/InitFC2 初始化流控制信用值 双向
UpdateFC 更新可用信用值,允许发送方继续发送 双向
PM_* 电源管理状态转换(如进入 L1 低功耗状态) 双向

2.3.2 物理层(Physical Layer)

物理层分为逻辑子层和电气子层,负责:

  • 8b/10b 或 128b/130b 编码:Gen1/Gen2 使用 8b/10b 编码,Gen3/Gen4 使用 128b/130b 编码以提高效率。
  • 链路训练状态机(LTSSM):管理链路状态转换,从 Detect → Polling → Configuration → L0(正常工作)→ Recovery(错误恢复)等。
  • 差分信号对(Lane):每个 Lane 由一对发送差分对(TX+/-)和一对接收差分对(RX+/-)组成。Agilex 支持 x1/x2/x4/x8 链路宽度。
Agilex 链路调试命令:
在 Linux 中,可通过 lspci -vvv -s <BDF> 查看链路状态:
LnkSta: Speed 8GT/s (Gen3), Width x4, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
如果显示 Speed 2.5GT/s (Gen1) 或 Width x1,说明链路训练未达到最佳状态,需检查 PCB 走线或参考时钟。

2.3.3 分层架构与数据流

下图展示了从软件到物理链路的完整数据流,以及各层之间的交互关系。

PCIe 分层架构与数据流 PCIe 分层架构与数据流(发送方向) 软件层(驱动 / DMA 引擎) 事务层(TL) 生成 TLP(Header + Data + ECRC) 数据链路层(DLL) 添加序列号 + LCRC,ACK/NAK 重传 物理层(PHY) 编码(8b/10b 或 128b/130b)+ 串行化 差分信号对(Lane) 接收方向: PHY 解串 → DLL 校验 序列号 + LCRC → TL 解析 Header → 软件读取数据

2.4 PCIe 配置空间:设备身份与资源映射

每个 PCIe 设备(包括 Agilex EP)必须实现配置空间(Configuration Space),用于系统软件识别设备类型、分配资源(内存、I/O、中断)和配置功能。配置空间通过配置读写 TLP(Type 0 或 Type 1)访问。

2.4.1 配置空间布局

PCIe 配置空间大小为 4KB(传统 PCI 为 256 字节)。前 256 字节为配置头(Configuration Header),后 3840 字节为能力结构(Capability Structures)。

偏移地址 寄存器名称 位宽 描述
0x00 Vendor ID 16 bits 设备制造商 ID(Intel = 0x8086,Altera = 0x1172)
0x02 Device ID 16 bits 设备型号 ID(Agilex 系列 ID 需查阅手册)
0x04 Command 16 bits 控制 I/O 空间、内存空间、总线主控、奇偶校验等
0x06 Status 16 bits 中断状态、能力列表、错误状态等
0x08 Revision ID 8 bits 版本号
0x09 Class Code 24 bits 设备类别(如 0x058000 表示内存控制器)
0x10-0x24 Base Address Registers (BAR0-BAR5) 32/64 bits each 设备内存/I/O 空间基地址,由 BIOS 或操作系统分配
0x34 Capabilities Pointer 8 bits 指向第一个能力结构的偏移地址
0x3C Interrupt Line 8 bits 中断向量号(由操作系统分配)
0x3D Interrupt Pin 8 bits 中断引脚(INTA# = 1, INTB# = 2, INTC# = 3, INTD# = 4)

2.4.2 能力结构(Capability Structures)

PCIe 设备通过能力结构实现高级功能,每个能力结构以能力 ID 和下一能力指针链接成链表。Agilex DMA 驱动需要关注以下能力:

  • PCI Express Capability (Cap ID = 0x10):包含链路状态(LnkSta)、设备控制(DevCtl)等寄存器,用于查询链路速度和宽度。
  • MSI Capability (Cap ID = 0x05):配置 MSI 中断,包括消息地址、消息数据和中断屏蔽。
  • MSI-X Capability (Cap ID = 0x11):配置 MSI-X 中断,支持更多中断向量(最多 2048 个),每个向量独立配置。
  • Power Management Capability (Cap ID = 0x01):管理设备电源状态(D0-D3hot)。
  • Advanced Error Reporting (AER) Capability (Cap ID = 0x01, Extended):增强错误报告,用于诊断链路错误。

2.4.3 BAR 空间与 DMA 地址映射

BAR(基地址寄存器)是配置空间中最关键的资源。Agilex EP 通过 BAR 向 RC 暴露内部寄存器或内存区域。DMA 驱动需要:

  1. 读取 BAR 大小:向 BAR 写入全 1,再读回,通过低比特位的 0 判断地址空间大小。
  2. 映射 BAR 到虚拟地址:使用 ioremap() 将物理地址映射到内核虚拟地址空间。
  3. 配置 DMA 描述符:通过 BAR 映射的寄存器设置源地址、目标地址、传输长度和方向。
Agilex BAR 配置建议:
- BAR0:通常映射为 64-bit 可预取内存空间,用于 DMA 描述符环形缓冲区。
- BAR2:映射为 32-bit 非可预取空间,用于控制/状态寄存器。
- 在 Quartus 的 PCIe IP 参数化界面中,可以设置 BAR 类型、大小和地址对齐方式。
- 使用 lspci -vvv -s