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位长度)
示例:64位地址空间的 GPIO 控制器
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 中断示例:
// 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"。
示例:板级覆盖禁用未使用的 UART
// 在 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 中断引用的 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 属性关系总览

设备树核心属性关系图 设备节点 compatible 驱动匹配标识 reg 地址/寄存器空间 interrupts 中断连接描述 status 启用/禁用控制 phandle 节点引用句柄 interrupts-extended phandle + 中断描述 属性协作关系 compatible 确定驱动 → reg 提供硬件地址 → interrupts 连接中断 → status 控制启用 → phandle 实现跨节点引用

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 配置的必备前置知识。掌握它们的格式、语义和常见陷阱,能够有效减少设备树调试中的低级错误。