2. PCIe协议基础与Layerscape实现

PCIe 不是一条“更快的并行总线”,而是一套分层、带事务语义、可枚举、可热插拔的点对点串行互连协议。理解它,必须同时抓住两条线:一条是协议栈的分层与报文封装,另一条是 Layerscape 控制器如何把这些协议动作落到硬件寄存器与内存映射上。本节先建立协议骨架,再对照 Layerscape 的 PCIe 控制器特性,为后续配置空间访问、枚举和驱动调试打基础。

一、PCIe 的三层协议栈与报文封装

PCIe 协议栈自下而上分为物理层(PHY)、数据链路层(DLL)和事务层(TL)。物理层负责串行化、8b/10b 或 128b/130b 编码、链路训练与均衡;数据链路层负责链路级的可靠传输,用序列号、LCRC 和 ACK/NAK 保证相邻两个设备之间不丢包;事务层负责生成和解析 TLP(Transaction Layer Packet),承载内存读写、配置读写和消息事务。三层各司其职,上层报文对下层而言只是需要可靠搬运的负载。

TLP 是事务层的基本单位,典型字段包括:Header(含 Fmt、Type、Requester ID、Tag、地址或路由信息)、Data Payload(可选,最大由 Max_Payload_Size 决定)以及可选的 ECRC。DLLP(Data Link Layer Packet)不承载事务语义,只在链路两端之间传递 ACK/NAK、流控信用(Flow Control)和电源管理信息,因此它不会出现在配置空间或内存事务的路径上。理解 TLP 与 DLLP 的分工,是区分“事务问题”和“链路问题”的关键:配置读返回错误码,多半是 TLP 层或配置空间问题;链路反复重训、LCRC 错误,则更可能是 DLL/PHY 层问题。

PCIe 分层协议栈与 Layerscape 控制器映射 PCIe 协议栈(自上而下) 事务层 TL TLP 生成/解析 Mem / Cfg / Msg 事务 数据链路层 DLL 序列号 / LCRC / ACK-NAK DLLP:流控信用、电源管理 物理层 PHY SerDes / 编码 / 均衡 LTSSM 链路训练 链路 Lane 0..N x1 / x2 / x4 / x8 / x16 TLP 报文结构 Header(Fmt/Type/ID/Tag) Data Payload(可选) ECRC(可选) Max_Payload_Size 限制单包数据量 DLLP(链路本地) ACK / NAK 序列号确认 Flow Control 信用更新 Layerscape PCIe 控制器 RC / EP 双模 RC 模式:枚举、配置空间映射 Outbound / Inbound 窗口 ATU 地址转换,映射到 DDR 配置空间访问 CFG0/CFG1 + ECAM 映射 中断与 MSI/MSI-X INTx / MSI 控制器路由 LTSSM 状态与链路速率 Gen1/2/3/4,x1~x16 封装 加链路头 串行化 硬件实现 地址转换 寄存器映射

二、配置空间:从 256 字节到 ECAM

PCIe 配置空间是枚举和驱动识别的入口。传统 PCI 配置空间为 256 字节,其中前 64 字节是标准头:Vendor ID、Device ID、Command、Status、Class Code、BAR0~BAR5、Capabilities Pointer 等。PCIe 在此基础上扩展为 4KB 配置空间,新增 PCI Express Capability、MSI/MSI-X Capability、Power Management 等结构。访问方式有两种:一是通过 CFG0/CFG1 的 I/O 端口间接访问(传统机制),二是通过 ECAM(Enhanced Configuration Access Mechanism)把配置空间直接映射到一段内存地址,用普通内存读写指令访问。

在 Layerscape 上,RC 模式通常使用 ECAM 映射,把总线号、设备号、功能号编码进地址偏移。例如某 Layerscape 平台将 ECAM 基址设为 0x3000_0000,则 Bus 1、Device 0、Function 0 的配置空间起始地址为 0x3000_0000 + (1<<20) + (0<<15) + (0<<12)。驱动或 U-Boot 通过读取该地址的 0x00 偏移即可拿到 Vendor ID 和 Device ID,从而判断设备是否存在。若读回 0xFFFF_FFFF,通常表示该位置无设备或链路未训练完成。

三、枚举过程与 Layerscape 的硬件配合

枚举是 RC 发现拓扑、分配总线号和资源的过程。典型流程是:RC 从 Bus 0 开始扫描,读取每个设备/功能的 Vendor ID;若有效,则读取 Header Type 判断是单功能还是多功能、是桥还是端点;对桥设备继续分配下游总线号并递归扫描;同时读取 BAR,确定所需内存或 I/O 空间大小,并写入分配后的基地址。枚举完成后,系统获得一棵完整的 PCIe 设备树,每个设备都有唯一的总线号、设备号和功能号。

Layerscape PCIe 控制器在枚举中承担几个关键角色。第一,它提供 Outbound 窗口,把 CPU 对本地地址的访问转换成 PCIe 配置或内存事务发往链路对端;第二,它提供 Inbound 窗口,把外部设备发来的内存读写映射到本地 DDR 或寄存器;第三,它通过 ATU(Address Translation Unit)完成地址转换,使 RC 侧地址与 PCIe 总线地址解耦。实际调试中,如果枚举不到设备,应优先检查 LTSSM 是否进入 L0、参考时钟是否稳定、PERST# 释放时序是否正确,再检查 ATU 窗口和 ECAM 基址配置。

四、Layerscape PCIe 控制器特性对照

Layerscape 系列(如 LS1046A、LS2088A、LX2160A)的 PCIe 控制器通常支持多个控制器实例,每个控制器可独立配置为 RC 或 EP。以 LS1046A 为例,它提供 3 个 PCIe 控制器,支持 Gen1/Gen2/Gen3,链路宽度可配置为 x1、x2、x4,部分控制器支持 x8。控制器内部集成 SerDes、LTSSM、ATU、MSI 控制器和配置空间访问逻辑。与通用 PCIe 规范相比,Layerscape 的差异主要体现在:地址转换窗口数量有限,需要合理规划 Outbound/Inbound 映射;MSI 中断需要经过 GIC 路由,配置时需同时设置 MSI Capability 和 GIC ITS/SPI 映射;部分控制器支持 SR-IOV,但需要确认 RC 和 EP 两侧的 PF/VF 配置。

在 Layerscape 上调试 PCIe 时,一个实用顺序是:先确认 LTSSM 状态寄存器显示 L0,再确认 ECAM 能读到有效 Vendor ID,然后检查 BAR 分配是否与 ATU 窗口冲突,最后验证 MSI 中断能否正常触发。这个顺序能把“链路问题”和“配置问题”分开,避免在错误层面反复排查。

五、一个可复用的枚举检查清单

检查项 观察位置/方法 正常判据 异常时优先排查
LTSSM 状态 控制器状态寄存器 进入 L0 参考时钟、PERST#、SerDes 配置
ECAM 可读性 读取 ECAM 基址 + 偏移 0x00 Vendor ID ≠ 0xFFFF ECAM 基址、总线号分配
BAR 分配 读取 BAR0~BAR5,写全 1 再读回 得到有效空间大小 ATU 窗口冲突、地址空间不足
Outbound 映射 检查 ATU 窗口寄存器 CPU 地址可命中目标总线地址 窗口基址、大小、目标地址
MSI 中断 触发设备中断,观察 GIC GIC 收到对应 SPI/LPI MSI Capability、ITS 映射、使能位