3. 设备树常用属性:compatible、reg、interrupts、status、phandle
设备树中的属性(Property)是描述硬件节点特征的关键载体。对于 LED 驱动配置而言,掌握以下五个核心属性是正确编写设备树节点的前提。每个属性都有其固定的语法、语义和使用场景,下面逐一展开。
3.1 属性总览
| 属性名 | 作用 | 值类型 | 是否必需 |
|---|---|---|---|
compatible |
指定设备与驱动的匹配名称 | 字符串 / 字符串列表 | 是 |
reg |
描述设备地址空间或寄存器偏移 | 数值对(地址,长度) | 视总线类型而定 |
interrupts |
描述设备的中断号与触发类型 | 数值列表 | 中断设备必需 |
status |
控制设备节点的启用状态 | 字符串 | 否(默认 okay) |
phandle |
提供节点引用句柄,供其他节点引用 | 数值(自动生成) | 被引用时必需 |
讲师提示: 在
gpio-leds 节点中,compatible 和 status 是最常用的两个属性;reg 和 interrupts 在简单 GPIO LED 中通常不出现,但在复杂外设(如 I2C/SPI 扩展 GPIO 芯片)中必须使用。
3.2 compatible —— 驱动匹配的“身份证”
compatible 是设备树中最关键的属性。内核通过该属性的值在驱动列表中查找匹配的 of_device_id 表。其格式为 "厂商,设备型号",推荐使用倒置域名风格。
// 标准写法
compatible = "ti,omap3-gpio", "linux,gpio";
// 内核匹配顺序:先精确匹配 "ti,omap3-gpio",失败后尝试 "linux,gpio"
匹配规则: 字符串列表从左到右优先级递减。第一个字符串最精确,后续字符串为兼容回退。驱动编写时,
of_match_table 中的条目顺序应与设备树中的列表顺序逻辑一致。
3.3 reg —— 地址与寄存器描述
reg 属性用于描述设备在总线上的地址范围。其基本语法为 reg = <address1 length1 [address2 length2 ...]>。每个 address 和 length 的位数由父节点的 #address-cells 和 #size-cells 决定。
// 32位地址系统,address-cells=1, size-cells=1
reg = <0x48002000 0x1000>;
// 64位地址系统,address-cells=2, size-cells=2
reg = <0x00 0x4A000000 0x00 0x1000>;
| 场景 | address-cells | size-cells | reg 示例 |
|---|---|---|---|
| 简单内存映射外设 | 1 | 1 | <0x48002000 0x1000> |
| I2C 设备(无地址长度) | 1 | 0 | <0x50> |
| PCI 设备(多地址空间) | 3 | 2 | <0x02000000 0x00000000 0x10000000 0x00000000 0x00100000> |
3.4 interrupts —— 中断资源描述
interrupts 属性描述设备使用的中断号、中断触发类型等信息。其解析依赖于父节点的 #interrupt-cells 和 interrupt-parent。
// 中断控制器定义 #interrupt-cells = <2>(中断号 + 触发类型)
interrupt-parent = <&gpio1>;
interrupts = <15 IRQ_TYPE_EDGE_RISING>;
常见错误: 忘记指定
interrupt-parent,或 interrupts 中的 cell 数量与中断控制器定义的 #interrupt-cells 不匹配。对于 GPIO 按键/中断型 LED,必须正确配置中断属性,否则驱动无法响应硬件事件。
3.5 status —— 设备启用开关
status 属性控制节点是否被内核枚举。常用值如下:
- okay —— 设备正常启用(默认值,可省略)
- disabled —— 设备禁用,内核不扫描该节点
- fail —— 设备检测失败,但节点保留
- fail-sss —— 带具体错误码的失败状态
// 在 .dtsi 中默认禁用
&led_red {
status = "disabled";
};
// 在板级 .dts 中启用
&led_red {
status = "okay";
};
3.6 phandle —— 节点引用句柄
phandle(pointer handle)是设备树编译器(DTC)自动为每个节点生成的唯一数值标识符。开发者通常不直接写 phandle,而是使用 &label 语法引用节点,编译器会自动解析为对应的 phandle 值。
// 定义带标签的节点
gpio1: gpio@48002000 {
compatible = "ti,omap3-gpio";
reg = <0x48002000 0x1000>;
#gpio-cells = <2>;
phandle = <0x00000001>; // 编译器自动生成,无需手动填写
};
// 引用节点
led-red {
gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; // &gpio1 被编译为 phandle 值
};
实战要点: 在
gpio-leds 节点中,gpios 属性内部就使用了 phandle 引用 GPIO 控制器节点。理解 phandle 的机制,有助于排查“GPIO 引用无效”或“中断找不到父节点”等常见问题。
3.7 属性关系与数据流
下图展示了五个核心属性在设备树节点中的组织关系,以及它们如何被内核驱动解析使用:
3.8 属性使用避坑清单
- compatible 拼写错误: 驱动中的
of_match_table字符串必须与设备树完全一致,包括大小写和标点。 - reg 的 address-cells/size-cells 不匹配: 子节点的
reg格式必须遵循父节点定义,否则内核解析出的地址会错位。 - interrupts 缺少 interrupt-parent: 如果节点没有显式指定
interrupt-parent,内核会向上查找父节点,但建议显式声明以避免歧义。 - status 误写为 disable 或 ok: 内核只识别
okay和disabled等标准值,拼写错误会导致节点被忽略。 - phandle 手动赋值冲突: 永远不要手动为节点写
phandle,由 DTC 编译器自动生成即可。