2. 设备树基础:设备树语法、节点、属性、reg、compatible、interrupts 等核心概念
设备树(Device Tree,DT)是一种描述硬件资源的数据结构,它使用节点(node)和属性(property)的树形层次结构,将不可枚举的硬件信息从内核代码中剥离出来。在 PCIe 控制器配置中,设备树是描述 RC(Root Complex)和 EP(Endpoint)拓扑、地址空间、中断路由的核心载体。本节将系统讲解设备树的语法、节点结构、关键属性及其在 PCIe 场景下的具体用法。
2.1 设备树语法基础
设备树源文件(.dts)采用一种类 C 的文本格式,经过 DTC(Device Tree Compiler)编译为二进制设备树 Blob(.dtb)。其基本语法规则如下:
- 节点(Node):以
node-name@unit-address形式定义,@后的地址用于区分同名节点。 - 属性(Property):键值对,值可以是字符串、整数、字节数组、字符串列表等。
- 标签(Label):为节点或属性起别名,便于引用,如
pcie0: pcie@1e0000000。 - 包含文件:使用
#include引入 .dtsi 头文件,实现 SoC 级复用。 - 根节点:
/表示设备树的根,所有设备节点挂载其下。
&pcie0 标签引用并覆盖属性,如 status = "okay" 使能控制器。
2.2 节点结构与层次关系
设备树节点形成一棵从根节点开始的树。每个节点代表一个硬件设备或总线,子节点表示挂载在该总线上的设备。PCIe 控制器节点通常位于 SoC 内部总线(如 AXI、AHB)之下,其子节点对应 PCIe 总线上的设备。
2.3 核心属性详解
设备树属性是描述设备特征的关键。以下表格列出了 PCIe 控制器配置中最常用的属性及其含义:
| 属性名 | 值类型 | PCIe 场景含义 | 示例 |
|---|---|---|---|
compatible |
字符串列表 | 匹配驱动,格式为 "vendor,device" | "fsl,imx8mq-pcie" |
reg |
地址/长度对 | 定义控制器寄存器基址和配置空间 | <0x1e0000000 0x100000> |
interrupts |
中断描述符 | 指定 PCIe 控制器中断号和触发类型 | <0 0 4> (GIC SPI) |
ranges |
地址转换表 | 将 PCIe 总线地址映射到 CPU 地址空间 | <0x81000000 0x0 0x40000000> |
bus-range |
整数对 | PCIe 总线号范围 | <0x00 0xff> |
num-lanes |
整数 | PCIe 链路宽度 | <4> (x4) |
max-link-speed |
整数 | 最大链路速度代次 | <3> (Gen3) |
status |
字符串 | 设备使能/禁用 | "okay" 或 "disabled" |
2.4 reg 属性:地址空间描述
reg 属性是设备树中最核心的地址描述属性,它由一个或多个地址/长度对组成。对于 PCIe 控制器,reg 通常包含以下内容:
- 控制器寄存器基址:DWC(DesignWare Core)或 PLDA 等 IP 核的配置寄存器空间。
- 配置空间基址:ECAM(Enhanced Configuration Access Mechanism)映射的 PCIe 配置空间。
- IO/内存空间基址:可选,用于非透明桥或特定 EP 场景。
pcie0: pcie@1e0000000 {
compatible = "fsl,imx8mq-pcie";
reg = <0x00 0x1e0000000 0x0 0x100000>, // 控制器寄存器
<0x00 0x1e0100000 0x0 0x100000>; // 配置空间 ECAM
reg-names = "dbi", "config";
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
ranges = <0x81000000 0x0 0x00000000 0x0 0x40000000 0x0 0x00010000>,
<0x82000000 0x0 0x40010000 0x0 0x40010000 0x0 0x3fff0000>;
bus-range = <0x00 0xff>;
num-lanes = <4>;
max-link-speed = <3>;
interrupts = <0 122 4>;
interrupt-parent = <&gic>;
status = "okay";
};
#address-cells = <3> 表示 PCIe 地址使用 3 个 32 位单元描述(总线号+设备号+功能号+偏移),#size-cells = <2> 表示长度使用 64 位。这是 PCIe 设备树节点的标准配置。
2.5 compatible 属性:驱动匹配
compatible 属性是设备树与 Linux 驱动之间的桥梁。内核通过设备树匹配表中的 of_match_table 来查找对应的驱动。PCIe 控制器的 compatible 通常遵循 "vendor,soc-ip" 格式:
| SoC/平台 | compatible 字符串 | 对应驱动 |
|---|---|---|
| NXP i.MX8MQ | "fsl,imx8mq-pcie" |
dw_pcie_host.c / dw_pcie_ep.c |
| Xilinx ZynqMP | "xlnx,zynqmp-pcie" |
pcie-xilinx.c |
| Rockchip RK3588 | "rockchip,rk3588-pcie" |
pcie-dw-rockchip.c |
| Intel Agilex | "intel,agilex-pcie" |
pcie-altera.c |
2.6 interrupts 属性:中断路由
PCIe 控制器的中断描述涉及多个层级。设备树中的 interrupts 属性定义控制器本身的中断(如 MSI 中断、错误中断),而 PCIe 设备的中断通过 interrupt-map 和 interrupt-map-mask 属性进行路由。
2.7 其他关键属性
除了上述核心属性,PCIe 设备树节点还包含以下重要属性:
ranges:定义 PCIe 总线地址到 CPU 物理地址的转换规则。格式为<child-bus-address parent-address length>,其中 child-bus-address 包含地址类型标志(如 0x81000000 表示 IO 空间,0x82000000 表示 64 位内存空间)。dma-ranges:描述 PCIe 设备 DMA 地址到 CPU 地址的映射,用于 IOMMU/SMMU 场景。msi-parent:指定 MSI 中断控制器,如 GICv3 ITS 或专用 MSI 控制器。num-ib-windows/num-ob-windows:DWC 控制器特有的 inbound/outbound 窗口数量配置。snps,enable-cdm-check:DWC 控制器特有的 CDM(Configuration Dependent Module)检查使能。
2.8 RC 模式与 EP 模式的设备树差异
PCIe 控制器可以配置为 RC(Root Complex)或 EP(Endpoint)模式,两种模式在设备树中的描述存在显著差异:
| 配置项 | RC 模式 | EP 模式 |
|---|---|---|
device_type |
"pci" |
不设置或 "pci-ep" |
ranges |
必须定义,映射 PCIe 地址到 CPU | 通常不定义,由 RC 端分配地址 |
bus-range |
定义总线号范围 | 不定义,EP 不管理总线 |
num-lanes |
定义链路宽度 | 定义链路宽度 |
max-link-speed |
定义最大速度 | 定义最大速度 |
interrupts |
控制器中断 + MSI | 控制器中断 + 传统 INTx |
ep-gpios |
不适用 | EP 复位/使能 GPIO |
| 子节点 | 挂载 PCIe 总线设备 | 无子节点,或挂载 EP 功能接口 |
// RC 模式设备树片段
pcie_rc: pcie@1e0000000 {
compatible = "fsl,imx8mq-pcie";
device_type = "pci";
reg = <0x00 0x1e0000000 0x0 0x100000>,
<0x00 0x1e0100000 0x0 0x100000>;
ranges = <0x81000000 0x0 0x00000000 0x0 0x40000000 0x0 0x00010000>,
<0x82000000 0x0 0x40010000 0x0 0x40010000 0x0 0x3fff0000>;
bus-range = <0x00 0xff>;
num-lanes = <4>;
max-link-speed = <3>;
interrupts = <0 122 4>;
status = "okay";
};
// EP 模式设备树片段
pcie_ep: pcie-ep@1e0000000 {
compatible = "fsl,imx8mq-pcie-ep";
reg = <0x00 0x1e0000000 0x0 0x100000>,
<0x00 0x1e0100000 0x0 0x100000>;
num-lanes = <4>;
max-link-speed = <3>;
interrupts = <0 122 4>;
ep-gpios = <&gpio3 20 GPIO_ACTIVE_LOW>;
status = "okay";
};
device_type = "pci" 或 ranges 属性,会导致内核枚举 PCIe 总线时产生地址映射冲突。EP 模式应避免使用这些 RC 专属属性。
2.9 设备树编译与调试
编写完 .dts 文件后,需要通过 DTC 编译为 .dtb 文件。以下是常用命令和调试技巧:
- 编译:
dtc -I dts -O dtb -o output.dtb input.dts - 反编译:
dtc -I dtb -O dts -o output.dts input.dtb - 检查语法:
dtc -I dts -O dtb -o /dev/null input.dts(无输出表示语法正确) - 内核调试:在内核启动参数中添加
earlycon和of_devlink可查看设备树解析日志。 - 用户空间查看:
ls /proc/device-tree/可查看当前系统加载的设备树结构。
status = "disabled" 禁用 PCIe 控制器,待确认其他硬件正常后再使能。同时使用 reg-names 属性为每个 reg 段命名,提高代码可读性。
2.10 本章小结
设备树是嵌入式 Linux 系统中描述 PCIe 控制器配置的核心语言。本章涵盖了以下关键知识点:
- 设备树的基本语法和节点层次结构,以及 PCIe 场景下的三级节点模型。
- 核心属性
compatible、reg、interrupts在 PCIe 控制器中的具体含义和用法。 - RC 模式与 EP 模式在设备树描述上的关键差异,以及常见配置陷阱。
- 设备树编译、反编译和调试的基本方法。