4. 设备树基础:设备树语法入门

设备树(Device Tree)是 Linux 内核中用于描述硬件平台非可枚举设备的一种数据结构。在音频驱动开发中,I2S 接口、Codec、DMA 通道、时钟和 GPIO 等硬件资源都通过设备树节点进行描述和传递。掌握设备树语法是配置音频接口的前提。

核心概念:设备树将硬件描述与内核驱动代码分离。同一份内核镜像可以通过不同的设备树文件(.dtb)适配不同的硬件板卡,无需重新编译内核。

4.1 节点(Node)与属性(Property)

设备树的基本组成单元是节点,每个节点代表一个硬件设备或总线。节点内包含若干属性,用于描述设备的配置参数、寄存器地址、中断号、时钟频率等。

  • 节点名称:格式为 node-name@unit-address,其中 unit-address 通常为设备基地址。
  • 属性:键值对形式,值可以是字符串、32 位整数数组、64 位整数数组、字节串等。
  • 根节点:/,所有设备节点都挂载在根节点下。
/dts-v1/;

/ {
    model = "MyAudioBoard";
    compatible = "vendor,myboard-v1";

    sound {
        compatible = "simple-audio-card";
        simple-audio-card,name = "My Audio Card";
        simple-audio-card,format = "i2s";
        simple-audio-card,bitclock-master = &cpu_dai;
        simple-audio-card,frame-master = &cpu_dai;
    };

    i2s@ff890000 {
        compatible = "vendor,i2s-controller";
        reg = <0xff890000 0x1000>;
        interrupts = <0 45 4>;
        clocks = <&clk_i2s>;
        #sound-dai-cells = <0>;
    };
};
语法要点:
  • 每个节点以分号 ; 结束。
  • 属性值用尖括号 <> 包裹 32 位整数数组,用双引号 "" 包裹字符串。
  • compatible 属性是驱动匹配的关键,格式为 "厂商,设备型号"。

4.2 标签(Label)与引用(Reference)

标签为节点提供一个别名,方便在其他节点中引用。引用使用 &label 语法,在编译时会被替换为对应节点的路径。

语法元素 示例 说明
标签定义 cpu_dai: i2s@ff890000 { ... }; 为 i2s 节点定义标签 cpu_dai
标签引用 sound { ... bitclock-master = &cpu_dai; }; 引用标签指向的节点路径
路径引用 &{/soc/i2s@ff890000} 直接使用完整路径引用
// 定义标签
cpu_dai: i2s@ff890000 {
    compatible = "vendor,i2s-controller";
    #sound-dai-cells = <0>;
};

// 引用标签
&cpu_dai {
    status = "okay";
};
常见错误:标签引用时不要忘记 & 符号。如果直接写 cpu_dai 而不加 &,编译器会将其视为字符串,而不是节点引用。

4.3 包含文件(Include)与 dts/dtsi 结构

设备树源文件分为 .dts(板级描述文件)和 .dtsi(芯片级描述文件)。.dtsi 文件通过 #include 指令被包含到 .dts 中,实现代码复用。

dts/dtsi 文件包含结构 myboard.dts #include "soc.dtsi" #include "audio-codec.dtsi" myboard.dtb(编译输出) 文件层级说明 .dtsi:芯片级通用描述 .dts:板级特定描述 .dtb:二进制设备树
// soc.dtsi — 芯片级描述
/ {
    cpu: cpu@0 {
        compatible = "arm,cortex-a7";
    };

    i2s0: i2s@ff890000 {
        compatible = "vendor,i2s-controller";
        reg = <0xff890000 0x1000>;
        status = "disabled";
    };
};

// myboard.dts — 板级描述
/dts-v1/;
#include "soc.dtsi"
#include "audio-codec.dtsi"

/ {
    model = "MyAudioBoard";
};

&i2s0 {
    status = "okay";
    pinctrl-0 = <&i2s0_pins>;
};
最佳实践:
  • 芯片厂商提供 .dtsi 文件,板卡厂商提供 .dts 文件。
  • 在 .dts 中通过 &label 方式覆盖 .dtsi 中的属性,如使能设备、配置引脚。
  • 不要修改 .dtsi 文件,通过 .dts 进行板级定制。

4.4 绑定文档(Binding Documentation)的重要性

绑定文档是设备树属性与内核驱动之间的“契约”。它定义了哪些属性是必需的、哪些是可选的、属性值的格式和含义。没有绑定文档,设备树配置将变成“猜谜游戏”。

绑定文档要素 说明 音频示例
compatible 字符串 驱动匹配的唯一标识 "simple-audio-card"
必需属性列表 驱动正常工作必须提供的属性 simple-audio-card,format
可选属性列表 提供额外功能配置的属性 simple-audio-card,bitclock-master
属性值格式 字符串、整数、phandle 等类型定义 <&cpu_dai> 为 phandle 引用
节点层级关系 子节点、父节点的约束 codec 节点必须挂在 sound 节点下
绑定文档在驱动开发中的角色 设备树 (.dts) 描述硬件配置 绑定文档 定义属性契约 内核驱动 解析属性并初始化 绑定文档的作用 1. 确保设备树属性名称、格式与驱动期望一致 2. 提供属性值的合法取值范围说明 3. 作为硬件工程师与驱动工程师之间的接口规范
实践建议:在编写音频设备树节点之前,务必先阅读对应驱动的绑定文档。Linux 内核源码中的 Documentation/devicetree/bindings/sound/ 目录下包含了所有音频相关绑定文档。例如 simple-audio-card.txt 定义了 simple-audio-card 驱动的所有可用属性。

4.5 本章小结

设备树语法是音频驱动开发的基石。通过节点描述硬件、属性传递参数、标签实现跨节点引用、包含文件实现代码复用,开发者可以灵活地配置 I2S 接口、Codec 和音频通路。绑定文档则是确保配置正确的“说明书”,必须养成查阅绑定文档的习惯。

关键记忆点:
  • 节点 = 硬件设备,属性 = 设备参数
  • 标签 + 引用 = 跨节点连接
  • .dtsi 通用 + .dts 定制 = 高效复用
  • 绑定文档 = 设备树与驱动的契约