3. 设备树常用属性
设备树中的属性(Property)是描述硬件节点特征的关键载体。每个节点通过一组属性向内核传递硬件资源信息、驱动匹配标识、地址映射关系、中断连接以及状态控制等。本章将深入解析五个最核心的通用属性,并结合 GPIO 与 pinctrl 场景说明其实际用法。
3.1 compatible —— 驱动匹配的“身份证”
compatible 属性是设备树中最关键的字符串属性,用于将设备节点与对应的 Linux 驱动进行绑定。内核通过设备树匹配机制,遍历节点的 compatible 值,与驱动中 of_device_id 表进行比对。
3.1.1 属性格式与匹配规则
- 格式:
"厂商,型号"或"通用型号",推荐使用厂商前缀以避免命名冲突。 - 匹配顺序:内核优先匹配列表中的第一个字符串;若失败,则依次尝试后续字符串。
- 通配符:不支持通配符,必须精确匹配字符串。
// i2c 设备节点
eeprom@50 {
compatible = "atmel,24c02", "microchip,24c02";
reg = <0x50>;
};
// GPIO 控制器节点
gpio0: gpio@ff730000 {
compatible = "snps,dw-apb-gpio";
reg = <0x0 0xff730000 0x0 0x1000>;
interrupts = <0 93 4>;
#gpio-cells = <2>;
gpio-controller;
};
3.1.2 匹配优先级与回退机制
| 匹配顺序 | compatible 值 | 说明 |
|---|---|---|
| 1 | "atmel,24c02" |
精确厂商型号,优先匹配 |
| 2 | "microchip,24c02" |
兼容型号,作为回退 |
| 3 | "atmel,24c0x" |
❌ 不支持通配符,无法匹配 |
cat /sys/firmware/devicetree/base/.../compatible 可查看实际生效的 compatible 字符串。驱动加载失败时,优先检查该值与驱动中的 of_device_id 是否完全一致。
3.2 reg —— 地址与寄存器空间描述
reg 属性用于描述设备在总线上的地址范围,通常包含一个或多个地址/长度对。对于内存映射设备,它定义了寄存器基地址和映射大小;对于 I2C/SPI 设备,则定义从设备地址。
3.2.1 地址编码与 #address-cells / #size-cells
reg 的解析依赖于父节点的 #address-cells 和 #size-cells 属性,它们决定了地址和长度字段的 32 位字数量。
| 父节点属性 | 含义 | 常见值 |
|---|---|---|
#address-cells |
地址字段占用的 32 位单元数 | 1(32位地址)、2(64位地址) |
#size-cells |
长度字段占用的 32 位单元数 | 0(无长度)、1(32位长度) |
soc {
#address-cells = <2>; // 64位地址
#size-cells = <2>; // 64位长度
gpio1: gpio@ff740000 {
compatible = "snps,dw-apb-gpio";
reg = <0x0 0xff740000 0x0 0x1000>;
// 地址: 0xff740000, 长度: 0x1000 (4KB)
};
};
3.2.2 多段 reg 与索引访问
一个设备可以拥有多个不连续的地址段,内核通过索引(0、1、2...)分别访问。
// 双段 reg 示例:控制寄存器 + 数据缓冲区
dma@ff200000 {
compatible = "my,dma-controller";
reg = <0x0 0xff200000 0x0 0x100>, // 索引0: 控制寄存器
<0x0 0xff201000 0x0 0x400>; // 索引1: 数据缓冲区
};
3.3 interrupts —— 中断连接描述
interrupts 属性将设备的中断请求线连接到中断控制器,是外设与 CPU 交互的重要通道。其格式由父中断控制器的 #interrupt-cells 决定。
3.3.1 中断属性格式
| 中断控制器类型 | #interrupt-cells | interrupts 格式 |
|---|---|---|
| GIC(通用中断控制器) | 3 | <中断类型 中断号 触发方式> |
| 简单中断控制器 | 1 | <中断号> |
| GPIO 作为中断控制器 | 2 | <GPIO号 触发方式> |
// GIC v2 中断控制器
gic: interrupt-controller@ffc01000 {
compatible = "arm,gic-400";
#interrupt-cells = <3>;
interrupt-controller;
};
// 使用 GIC 中断的外设
uart0: serial@ff010000 {
compatible = "snps,dw-apb-uart";
reg = <0x0 0xff010000 0x0 0x1000>;
interrupts = <0 33 4>; // 类型:SPI, 中断号:33, 触发:高电平
};
3.3.2 中断触发类型编码
| 触发类型 | 编码值 | 说明 |
|---|---|---|
| IRQ_TYPE_NONE | 0 | 未指定 |
| IRQ_TYPE_EDGE_RISING | 1 | 上升沿触发 |
| IRQ_TYPE_EDGE_FALLING | 2 | 下降沿触发 |
| IRQ_TYPE_EDGE_BOTH | 3 | 双边沿触发 |
| IRQ_TYPE_LEVEL_HIGH | 4 | 高电平触发 |
| IRQ_TYPE_LEVEL_LOW | 8 | 低电平触发 |
3.4 status —— 设备状态控制
status 属性用于控制设备节点的启用或禁用状态,是设备树中实现“硬件裁剪”和“运行时配置”的常用手段。
3.4.1 可选值及含义
| status 值 | 含义 | 内核行为 |
|---|---|---|
"okay" |
设备启用 | 正常探测并初始化 |
"disabled" |
设备禁用 | 跳过探测,不注册设备 |
"reserved" |
保留状态 | 通常由固件使用,内核视为禁用 |
"fail" |
设备故障 | 探测失败,不注册 |
| 缺失 | 默认启用 | 视为 "okay" |
3.4.2 典型应用场景
- 硬件变体管理:同一款 SoC 的不同板级,通过
status启用/禁用不同外设。 - 调试与隔离:临时禁用某个有问题的外设,避免系统崩溃。
- 电源管理:在休眠状态下将不必要的外设标记为
"disabled"。
// 在 SoC 基础 dtsi 中定义
uart2: serial@ff030000 {
compatible = "snps,dw-apb-uart";
reg = <0x0 0xff030000 0x0 0x1000>;
interrupts = <0 35 4>;
status = "disabled"; // 默认禁用
};
// 在板级 dts 中启用
&uart2 {
status = "okay";
pinctrl-0 = <&uart2_pins>;
pinctrl-names = "default";
};
3.5 phandle —— 节点引用与连接
phandle(指针句柄)是设备树中实现节点间引用的数字标识符。每个节点可以拥有一个唯一的 phandle 值,其他节点通过 <&label> 语法引用该节点。
3.5.1 phandle 的生成与使用
在 DTS 源文件中,开发者通常使用标签(label)来引用节点,编译器自动生成 phandle 值。
// 定义 GPIO 控制器,带标签
gpio2: gpio@ff750000 {
compatible = "snps,dw-apb-gpio";
reg = <0x0 0xff750000 0x0 0x1000>;
#gpio-cells = <2>;
gpio-controller;
#interrupt-cells = <2>;
interrupt-controller;
};
// 按键设备通过 phandle 引用 gpio2
button@0 {
compatible = "gpio-keys";
gpios = <&gpio2 15 0>; // &gpio2 展开为 phandle 值
interrupts-extended = <&gpio2 15 2>; // 下降沿触发
};
3.5.2 phandle 与 interrupts-extended
当设备需要连接到多个中断控制器时,interrupts-extended 属性允许为每个中断显式指定 phandle,而 interrupts 则隐式使用父节点的中断控制器。
| 属性 | 适用场景 | 格式 |
|---|---|---|
interrupts |
单一中断控制器 | <中断描述> |
interrupts-extended |
多中断控制器混合 | <&phandle 中断描述> ... |
dtc -I dtb -O dts 反编译 DTB 文件,可以查看编译器自动生成的 phandle 数值(如 phandle = <0x3e>),有助于验证引用关系是否正确。
3.6 属性关系总览
3.7 属性使用避坑指南
- compatible 拼写错误:厂商前缀或型号名称大小写不一致,导致驱动无法匹配。使用
dtc -I dtb -O dts反编译确认实际值。 - reg 地址越界:寄存器长度超出实际硬件映射范围,导致内核访问异常。检查
#address-cells和#size-cells是否与父节点一致。 - interrupts 触发类型不匹配:硬件实际触发方式与设备树描述不一致,导致中断丢失或误触发。使用
cat /proc/interrupts观察中断计数。 - status 覆盖失效:在 dts 中通过
&node引用修改 status 时,确保引用路径正确,且没有被其他包含文件再次覆盖。 - phandle 循环引用:设备树编译器会检测循环引用并报错,避免节点之间形成 A→B→A 的依赖环。
3.8 本章小结
本章详细解析了设备树中五个最常用的属性:compatible 负责驱动匹配,reg 描述硬件地址空间,interrupts 连接中断信号,status 控制设备启用状态,phandle 实现节点间引用。这些属性是构建任何设备树节点的基础,也是后续学习 GPIO 和 pinctrl 配置的必备前置知识。掌握它们的格式、语义和常见陷阱,能够有效减少设备树调试中的低级错误。