2. 设备树基础:DTS语法、节点、属性与核心概念

设备树(Device Tree,DT)是一种描述硬件资源的数据结构,用于将非可枚举的硬件信息从内核源码中剥离,传递给操作系统。在骁龙平台上,Sensor Hub(如SLPI)的上电时序、GPIO分配、中断路由等关键配置,均通过设备树节点完成。理解DTS语法是调试Sensor上电时序的前提。

核心认知: 设备树不是编程语言,而是一种键值对描述的硬件拓扑树。每个硬件外设对应一个节点(node),节点内包含若干属性(property),属性描述该外设的寄存器地址、中断号、GPIO引脚、电源域等。

2.1 DTS文件结构与语法

DTS(Device Tree Source)采用树形层次结构,以/dts-v1/;开头,根节点为/。每个节点以节点名@地址的形式定义,节点内可嵌套子节点。

/dts-v1/;

/ {
    model = "Qualcomm SM8550 Platform";
    compatible = "qcom,sm8550";

    soc: soc@0 {
        #address-cells = <2>;
        #size-cells = <2>;
        ranges;

        i2c@9800000 {
            compatible = "qcom,i2c-geni";
            reg = <0x0 0x09800000 0x0 0x4000>;
            interrupts = <GIC_SPI 601 IRQ_TYPE_LEVEL_HIGH>;
            #address-cells = <1>;
            #size-cells = <0>;

            sensor@48 {
                compatible = "bosch,bmi270";
                reg = <0x48>;
                vdd-supply = <&pm8550_l5>;
                vio-supply = <&pm8550_l6>;
                interrupt-parent = <&tlmm>;
                interrupts = <92 IRQ_TYPE_EDGE_RISING>;
                pinctrl-names = "default";
                pinctrl-0 = <&sensor_irq_default>;
            };
        };
    };
};
语法要点:
  • 分号结尾:每个属性定义必须以;结束。
  • 尖括号:<>内为32位整型数组,用于地址、中断号等。
  • 双引号:字符串属性用""包裹,如"qcom,i2c-geni"。
  • &引用:&tlmm表示引用其他节点(如TLMM中断控制器)。

2.2 节点(Node)与节点名

节点是设备树的基本组成单元,每个节点代表一个硬件设备或总线。节点名格式为:

节点名[@单元地址]
  • 节点名:通用名称,如i2c、sensor、gpio。
  • 单元地址:可选,用于区分同一总线下的多个同类型设备,如sensor@48中的48为I2C从设备地址。
节点类型 示例 说明
根节点 / 设备树的顶层容器,包含所有硬件节点
总线节点 soc@0 代表SoC内部总线,包含地址映射信息
外设节点 i2c@9800000 I2C控制器,包含寄存器基地址和中断
设备节点 sensor@48 挂载在总线上的具体传感器,包含电源、GPIO等
设备树节点层次结构(Sensor上电相关) / (根节点) soc@0 (SoC总线) i2c@9800000 (I2C控制器) sensor@48 (BMI270传感器) 节点属性示例: compatible = "bosch,bmi270"; reg = <0x48>; vdd-supply = <&pm8550_l5>; interrupts = <92 IRQ_TYPE_EDGE_RISING>; pinctrl-0 = <&sensor_irq_default>; // GPIO引脚复用配置

2.3 属性(Property)详解

属性是节点的具体配置项,每个属性由名称和值组成。以下是Sensor上电时序调试中最关键的属性:

2.3.1 compatible —— 驱动匹配标识

compatible = "bosch,bmi270";

内核通过该属性查找对应的驱动程序。格式为"厂商,设备型号",驱动中需在of_match_table中声明相同的字符串。

2.3.2 reg —— 地址资源

reg = <0x0 0x09800000 0x0 0x4000>;  // I2C控制器寄存器基地址+长度
reg = <0x48>;                         // 传感器I2C从设备地址

reg的值由父节点的#address-cells和#size-cells决定。对于I2C设备,reg通常只包含从设备地址(7位或10位)。

2.3.3 interrupts —— 中断配置

interrupt-parent = <&tlmm>;
interrupts = <92 IRQ_TYPE_EDGE_RISING>;
  • interrupt-parent:指定中断控制器(如TLMM、GIC)。
  • interrupts:中断号(92)和触发类型(上升沿触发)。
中断触发类型宏 值 适用场景
IRQ_TYPE_EDGE_RISING 1 传感器数据就绪中断(DRDY)
IRQ_TYPE_EDGE_FALLING 2 唤醒中断(低功耗模式)
IRQ_TYPE_LEVEL_HIGH 4 GPIO电平触发(如复位完成)
IRQ_TYPE_LEVEL_LOW 8 电源状态指示

2.3.4 pinctrl —— GPIO引脚复用控制

pinctrl-names = "default", "sleep";
pinctrl-0 = <&sensor_irq_default>;
pinctrl-1 = <&sensor_irq_sleep>;

在Sensor上电时序中,GPIO引脚必须在正确的时刻切换到正确的功能模式:

  • default:正常工作模式,GPIO配置为中断输入或I2C功能。
  • sleep:休眠模式,GPIO可配置为下拉或悬空以降低漏电。
调试陷阱: 如果Sensor上电后中断GPIO未正确配置为pinctrl-0状态,可能导致中断无法触发,Sensor驱动认为设备未就绪,进而影响上电时序中的等待中断阶段。务必检查pinctrl-0中的引脚复用、上拉/下拉配置是否与硬件设计一致。

2.4 电源与上电时序相关属性

在骁龙平台上,Sensor的上电时序通常涉及以下电源属性:

属性名 示例 作用
vdd-supply &pm8550_l5 主电源(1.8V或3.3V),驱动中通过regulator_enable()控制
vio-supply &pm8550_l6 IO电源(通常1.8V),先于vdd上电
vddio-supply &pm8550_l7 数字IO电源,部分Sensor需要独立供电
reset-gpios <&tlmm 45 GPIO_ACTIVE_LOW> 复位引脚,上电时序中用于释放复位
powerdown-gpios <&tlmm 46 GPIO_ACTIVE_HIGH> 掉电控制引脚,用于低功耗模式
Sensor上电时序与设备树属性映射 Step 1: IO电源使能 vio-supply Step 2: 主电源使能 vdd-supply Step 3: 释放复位 reset-gpios Step 4: 等待中断 interrupts 设备树属性与驱动时序的对应关系 1. vio-supply (IO电源) 驱动调用 regulator_enable(vio) → 等待 regulator_is_enabled 返回 true 2. vdd-supply (主电源) 驱动调用 regulator_enable(vdd) → 延时 t1 (通常1-5ms) 等待电源稳定 3. reset-gpios (复位释放) 驱动调用 gpiod_set_value(reset, 1) → 延时 t2 (Sensor内部初始化时间) 4. interrupts (中断等待) 驱动注册中断处理函数 → 等待 Sensor 发出 DRDY 中断 → 上电完成

2.5 特殊属性:status与phandle

status

status = "okay";   // 启用设备
status = "disabled"; // 禁用设备

在调试过程中,可通过修改status属性临时禁用某个Sensor节点,以隔离上电时序问题。

phandle(句柄)

pm8550_l5: pm8550_l5 {
    regulator-min-microvolt = <1800000>;
    regulator-max-microvolt = <1800000>;
};

pm8550_l5: 是标签(label),编译后生成phandle(唯一数字ID)。其他节点通过&pm8550_l5引用该节点,实现跨节点关联。

调试技巧: 在编译后的DTB文件中,可以使用dtc -I dtb -O dts反编译查看phandle值。如果Sensor上电时序异常,检查vdd-supply引用的phandle是否指向正确的regulator节点,以及该regulator的电压配置是否匹配硬件设计。

2.6 包含文件与宏定义

实际项目中,DTS文件通常通过#include引入头文件,使用宏定义提高可读性:

#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/gpio/gpio.h>
#include "sm8550-pinctrl.dtsi"

&i2c_1 {
    status = "okay";

    sensor@48 {
        compatible = "bosch,bmi270";
        reg = <0x48>;
        interrupt-parent = <&tlmm>;
        interrupts = <92 IRQ_TYPE_EDGE_RISING>;
        reset-gpios = <&tlmm 45 GPIO_ACTIVE_LOW>;
        vdd-supply = <&pm8550_l5>;
        vio-supply = <&pm8550_l6>;
        pinctrl-names = "default";
        pinctrl-0 = <&sensor_irq_default>;
    };
};
  • 头文件:arm-gic.h定义GIC中断类型,gpio.h定义GPIO_ACTIVE_HIGH/LOW。
  • dtsi文件:sm8550-pinctrl.dtsi包含SoC引脚复用配置,通过&sensor_irq_default引用。
  • &引用:&i2c_1表示向已存在的I2C节点追加子节点或修改属性。
本章小结: 设备树通过节点描述硬件拓扑,通过属性传递寄存器地址、中断、电源、GPIO等关键信息。在Sensor上电时序调试中,重点关注vdd-supply、vio-supply、reset-gpios、interrupts和pinctrl属性。这些属性的配置直接影响电源使能顺序、复位释放时机和中断响应,是定位上电时序问题的第一切入点。