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 属性关系与数据流

下图展示了五个核心属性在设备树节点中的组织关系,以及它们如何被内核驱动解析使用:

设备树节点核心属性关系图 设备树节点 compatible reg interrupts status phandle 各属性在内核驱动中的使用路径 • compatible → 驱动 .of_match_table 匹配,决定 probe 哪个驱动 • reg → of_iomap() / platform_get_resource() 获取寄存器基址 • interrupts → request_irq() / devm_request_irq() 注册中断处理函数 • status → of_device_is_available() 判断节点是否启用 • phandle → of_parse_phandle() 获取引用节点的 device_node 指针

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 编译器自动生成即可。