2. DTS 语法基础:设备树源文件的基本结构与定义

设备树源文件(DTS)是描述硬件拓扑与资源配置的文本文件,采用树形层级结构组织。每个 DTS 文件由节点(node)和属性(property)构成,节点对应硬件设备或总线,属性描述设备的特性与配置参数。

2.1 DTS 文件的基本结构

一个典型的 DTS 文件包含以下部分:

  • 根节点(/):设备树的顶层入口,所有设备节点均挂载在根节点下。
  • 子节点:表示具体的设备或总线,如 CPU、内存、I2C 控制器、GPIO 控制器等。
  • 属性:键值对形式,描述节点的硬件信息,如寄存器地址、中断号、时钟频率等。
  • 包含文件:通过 #include 引入 .dtsi 文件,实现 SoC 级公共定义的复用。
关键概念:DTS 文件采用 C 语言风格的注释(// 和 /* */),支持宏定义和头文件包含,语法上类似 C 语言的结构体定义。
实践提示:实际项目中,SoC 厂商提供 .dtsi 文件定义芯片内部外设,板级开发者只需在 .dts 文件中引用并覆盖或添加板级特有设备。
DTS 文件基本结构 根节点 “/” model = "Board Name" cpus { } memory { } soc { } compatible = "arm,cortex-a9" reg = <0x80000000 0x40000000> #address-cells = <1> 每个节点可包含子节点和属性,属性描述硬件参数 子节点递归嵌套,形成完整的设备树层级

2.2 节点(Node)的定义

节点是设备树的基本组成单元,语法格式如下:

[label:] node-name {
    property1 = value1;
    property2 = value2;
    child-node {
        ...
    };
};

节点定义的关键要素:

要素 说明 示例
节点名称 标识节点类型,通常为通用名称如 uart、i2c serial@101f0000
单元地址 可选,跟在节点名后以 @ 分隔,表示设备基地址 @101f0000
标签(label) 可选,为节点起别名,便于引用或覆盖 uart1: serial@101f0000
属性列表 花括号 { } 内包含多个属性定义 reg = <0x101f0000 0x1000>;
子节点 节点内可嵌套子节点,形成层级结构 clocks { ... };
常见错误:节点名称不能包含空格或特殊字符(除 @、-、_ 外);单元地址必须与 reg 属性中的首地址一致,否则编译报错。

2.3 属性(Property)的定义

属性是节点的数据载体,采用键值对形式。属性值支持多种数据类型:

数据类型 语法格式 示例 说明
空值 property-name; interrupt-controller; 仅表示存在该属性,无值
32 位整数 <value> reg = <0x10000000 0x1000>; 尖括号内可包含多个整数
64 位整数 <high low> reg = <0x0 0x80000000 0x0 0x10000000>; 高 32 位在前,低 32 位在后
字符串 "string" compatible = "arm,cortex-a9"; 双引号包裹
字符串列表 "str1", "str2" compatible = "ti,am335x-uart", "ns16550"; 逗号分隔多个字符串
字节数组 [hex bytes] local-mac-address = [00 11 22 33 44 55]; 方括号内为十六进制字节
混合值 <...> "..." [...] gpios = <&gpio0 15 0>; 可组合不同类型

2.4 标准属性与常用属性

设备树规范定义了一系列标准属性,用于描述设备的核心信息:

属性名 用途 示例值
compatible 设备驱动匹配字符串,格式为 "厂商,型号" "ti,am335x-uart"
reg 设备寄存器地址与长度,格式为 <地址 长度> <0x44e09000 0x2000>
interrupts 中断号与触发类型 <0 56 4>
clocks 时钟源引用 <&clk_uart1_fck>
status 设备状态:okay、disabled、reserved "okay"
#address-cells 子节点 reg 中地址字段的 32 位字数量 <1>
#size-cells 子节点 reg 中长度字段的 32 位字数量 <1>
节点与属性关系 uart0: serial@44e09000 compatible 属性 reg 属性 interrupts 属性 "ti,am335x-uart" 驱动匹配字符串 <0x44e09000 0x2000> 基地址 + 地址范围 <0 56 4> 中断控制器、中断号、触发类型 属性是节点的数据载体,驱动通过读取属性获取硬件配置 标准属性由设备树规范定义,厂商可自定义私有属性

2.5 完整 DTS 示例

以下是一个简化的 UART 设备节点定义,展示节点与属性的实际组合:

/dts-v1/;

/ {
    model = "TI AM335x Board";
    compatible = "ti,am335x-board";

    chosen {
        stdout-path = &uart0;
    };

    uart0: serial@44e09000 {
        compatible = "ti,am335x-uart", "ns16550";
        reg = <0x44e09000 0x2000>;
        interrupts = <0 72 4>;
        clock-frequency = <48000000>;
        status = "okay";

        pinctrl-names = "default";
        pinctrl-0 = &uart0_pins;
    };

    uart0_pins: pinmux_uart0_pins {
        pinctrl-single,pins = <
            0x170 0x30  /* uart0_rxd */
            0x174 0x00  /* uart0_txd */
        >;
    };
};
要点总结:
  • 根节点 / 包含 model 和 compatible 属性,标识板级信息。
  • chosen 节点用于传递内核启动参数,如控制台设备。
  • uart0 节点通过 compatible 属性匹配驱动,reg 描述寄存器地址,interrupts 描述中断资源。
  • pinctrl 属性用于引脚复用配置,属于 SoC 特有的扩展属性。

2.6 节点引用与覆盖

设备树支持通过标签(label)引用节点,实现节点属性的覆盖或扩展:

// 在 .dtsi 文件中定义
uart0: serial@44e09000 {
    compatible = "ti,am335x-uart";
    status = "disabled";
};

// 在 .dts 文件中覆盖
&uart0 {
    status = "okay";
    clock-frequency = <48000000>;
};

引用语法 &label 允许在不重新定义整个节点的情况下,修改或添加属性。这是设备树实现板级差异化的核心机制。

工程实践:SoC 厂商在 .dtsi 中将外设节点 status 设为 disabled,板级 .dts 中仅使能实际使用的设备,避免未用设备占用资源。

2.7 本章小结