3. DTS常用属性
设备树(Device Tree Source, DTS)通过一系列标准属性来描述硬件设备的特征、资源需求和连接关系。掌握这些核心属性是编写正确设备树文件的基础,也是实现设备树覆盖(Overlay)与热插拔驱动的关键前提。本章将逐一详解最常用的五大属性:compatible、reg、interrupts、status 和 gpios。
学习提示: 这些属性并非孤立存在,它们共同构成了内核与设备驱动之间的“契约”。理解每个属性的语义、格式和约束,能帮助你在调试设备树问题时快速定位错误。
3.1 compatible 属性:设备与驱动的匹配钥匙
compatible 属性是设备树中最核心的字符串属性,它指定了设备的“兼容性”标识。内核通过该属性查找并绑定对应的设备驱动。
- 格式: 一个或多个字符串,按优先级从高到低排列。
- 命名规范: 通常采用
"厂商,设备型号"的形式,例如"ti,am335x-uart"、"fsl,imx6q-uart"。 - 匹配机制: 内核驱动中的
of_match_table会与设备节点的compatible值进行精确匹配。匹配成功则调用驱动的probe函数。
实战案例: 一个 I2C 触摸屏节点的 compatible 属性可以同时声明多个兼容型号,确保驱动向后兼容。
// 设备树节点
i2c_touch: touch@38 {
compatible = "edt,edt-ft5406", "edt,edt-ft5x06";
reg = <0x38>;
interrupt-parent = <&gpio1>;
interrupts = <13 IRQ_TYPE_EDGE_FALLING>;
};
上述代码中,内核会优先尝试匹配 "edt,edt-ft5406",若失败则尝试 "edt,edt-ft5x06"。这种机制允许一个驱动支持多个硬件版本。
3.2 reg 属性:定义设备地址空间
reg 属性用于描述设备在总线上的地址范围,通常由一组或多组 (地址, 长度) 对组成。它直接对应硬件寄存器的物理地址空间。
| 属性字段 | 含义 | 示例值 |
|---|---|---|
| address-cells | 父节点中定义,表示地址字段占用的 32 位单元数 | <1> 或 <2> |
| size-cells | 父节点中定义,表示长度字段占用的 32 位单元数 | <1> 或 <2> |
| reg | 实际的地址-长度对列表 | <0x10000000 0x1000> |
常见错误: 忘记在父节点中正确设置
#address-cells 和 #size-cells,会导致内核解析 reg 时出现地址错位或长度错误。
// 父节点定义地址格式
soc {
#address-cells = <1>;
#size-cells = <1>;
// 子节点使用 reg 属性
uart0: serial@10000000 {
compatible = "ns16550a";
reg = <0x10000000 0x1000>; // 基地址 0x10000000,长度 0x1000
interrupts = <33>;
clock-frequency = <1843200>;
};
gpio0: gpio@10001000 {
compatible = "brcm,bcm2835-gpio";
reg = <0x10001000 0x100>; // 基地址 0x10001000,长度 0x100
interrupts = <17>;
gpio-controller;
#gpio-cells = <2>;
};
};
在驱动代码中,通过 of_iomap() 或 platform_get_resource() 函数获取 reg 属性定义的物理地址,并将其映射到内核虚拟地址空间。
3.3 interrupts 属性:中断资源描述
interrupts 属性用于描述设备使用的中断号、触发类型等信息。它通常与 interrupt-parent 属性配合使用,后者指定中断控制器节点。
- interrupt-parent: 指向中断控制器的 phandle,若子节点未定义,则继承父节点的值。
- interrupts: 一个或多个中断描述符,格式由中断控制器的
#interrupt-cells决定。 - 常见触发类型:
IRQ_TYPE_EDGE_RISING(1) — 上升沿触发IRQ_TYPE_EDGE_FALLING(2) — 下降沿触发IRQ_TYPE_LEVEL_HIGH(4) — 高电平触发IRQ_TYPE_LEVEL_LOW(8) — 低电平触发
// 中断控制器定义
gic: interrupt-controller@10400000 {
compatible = "arm,gic-400";
reg = <0x10400000 0x10000>;
interrupt-controller;
#interrupt-cells = <3>; // GIC 使用 3 个 cell: 中断类型、编号、触发标志
};
// 使用中断的设备节点
ethernet@20000000 {
compatible = "smsc,lan9115";
reg = <0x20000000 0x1000>;
interrupt-parent = <&gic>;
interrupts = <0 33 4>; // SPI 中断,编号 33,高电平触发
};
关键点: 中断号在设备树中通常是硬件中断号,而非 Linux IRQ 号。内核通过 irq_domain 机制完成映射。
3.4 status 属性:设备状态控制
status 属性用于控制设备节点的启用或禁用状态,是设备树覆盖(Overlay)中实现热插拔逻辑的核心属性之一。
| status 值 | 含义 | 典型使用场景 |
|---|---|---|
| okay | 设备已启用,驱动可以正常探测 | 默认使能设备 |
| disabled | 设备被禁用,驱动不会探测 | 硬件未焊接、或需要动态控制 |
| fail | 设备检测失败,驱动不会探测 | 硬件自检失败时由 Bootloader 设置 |
| reserved | 设备保留,不用于当前系统 | 多平台兼容时使用 |
避坑指南: 在 Overlay 中,若父节点
status = "disabled",即使子节点 status = "okay",子设备也不会被使能。必须确保整条设备树路径上的节点均为 okay 状态。
// 基板设备树:默认禁用某个外设
&i2c1 {
status = "okay";
touch: touch@38 {
compatible = "edt,edt-ft5406";
reg = <0x38>;
status = "disabled"; // 默认禁用,等待 Overlay 使能
};
};
// Overlay 文件:使能触摸屏
&touch {
status = "okay"; // 通过 Overlay 动态启用
};
3.5 gpios 属性:GPIO 资源描述
gpios 属性用于描述设备使用的 GPIO 引脚,包括引脚号、标志位等信息。它依赖于 GPIO 控制器节点提供的 #gpio-cells 定义。
- gpio-controller: 标记节点为 GPIO 控制器。
- #gpio-cells: 指定 GPIO 描述符需要的 cell 数量,通常为 2(GPIO 号 + 标志位)。
- 标志位: 常用值包括
GPIO_ACTIVE_HIGH(0) 和GPIO_ACTIVE_LOW(1)。
// GPIO 控制器定义
gpio0: gpio@10001000 {
compatible = "brcm,bcm2835-gpio";
reg = <0x10001000 0x100>;
gpio-controller;
#gpio-cells = <2>;
interrupts = <17>;
};
// 使用 GPIO 的设备
leds {
compatible = "gpio-leds";
led-red {
label = "red-led";
gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>; // GPIO0 的 18 号引脚,高电平有效
linux,default-trigger = "heartbeat";
};
led-green {
label = "green-led";
gpios = <&gpio0 19 GPIO_ACTIVE_LOW>; // GPIO0 的 19 号引脚,低电平有效
default-state = "off";
};
};
驱动对应: 在驱动中通过
of_get_named_gpio() 或 devm_gpiod_get() 函数获取 GPIO 描述符,然后使用标准的 GPIO API 进行控制。
3.6 属性综合对比与实战建议
下表总结了五个核心属性的关键特征,便于在实际开发中快速查阅和对比:
| 属性名 | 数据类型 | 核心作用 | 依赖关系 | Overlay 常用操作 |
|---|---|---|---|---|
| compatible | 字符串列表 | 驱动匹配 | 无 | 通常不修改 |
| reg | u32 数组 | 地址空间定义 | #address-cells, #size-cells | 通常不修改 |
| interrupts | u32 数组 | 中断资源描述 | interrupt-parent, #interrupt-cells | 可能修改中断号 |
| status | 字符串 | 设备使能/禁用 | 无 | 最常修改 |
| gpios | phandle + u32 数组 | GPIO 引脚描述 | gpio-controller, #gpio-cells | 可能修改引脚号 |
实战建议: 在编写 Overlay 时,优先通过修改
status 属性来控制设备的启用与禁用。对于 reg 和 compatible 属性,除非硬件设计变更,否则不建议在 Overlay 中修改。中断和 GPIO 的修改需要确保与硬件实际连接一致。