3. Overlay语法详解
设备树 Overlay 的语法基于标准 DTS(Device Tree Source)格式,但引入了若干关键语法元素,用于描述“如何将一段设备树片段动态地附加到基础设备树(Base Device Tree)上”。理解 /plugin/、target、__overlay__ 和 fragment 这四个核心元素,是掌握 Overlay 编写的基础。
3.1 语法元素总览
下表列出了 Overlay 语法中的四个核心元素及其作用:
| 语法元素 | 作用 | 使用位置 |
|---|---|---|
/plugin/ |
声明该 DTS 文件是一个 Overlay 插件,而非独立的完整设备树 | 文件头部 |
target |
指定 Overlay 要附加到基础设备树中的哪个节点(通过路径或标签) | 每个 fragment 内部 |
__overlay__ |
包含要附加或修改的设备树内容(属性、子节点) | 每个 fragment 内部,紧跟在 target 之后 |
fragment |
将 target 和 __overlay__ 封装为一个独立的操作单元 | Overlay 根节点下的子节点 |
3.2 /plugin/ —— Overlay 文件标识
/plugin/ 是一个特殊的编译器指令,必须放在 Overlay 源文件的第一行。它告诉 DTC(Device Tree Compiler)该文件是一个插件,需要以 Overlay 模式编译,而不是编译为完整的设备树二进制(.dtb)。
关键点: 没有
/plugin/ 的 DTS 文件会被视为独立设备树,编译时不会生成 Overlay 特有的符号表和 fragment 结构。
// 正确的 Overlay 文件开头
/dts-v1/;
/plugin/;
/ {
fragment@0 {
target = &i2c1;
__overlay__ {
status = "okay";
};
};
};
3.3 target —— 指定附加目标
target 属性用于指定 Overlay 要操作的基础设备树节点。它有两种常用写法:
- 标签引用(推荐): 使用
&label语法,如target = &i2c1;。这种方式可读性好,且编译时会自动解析为正确的路径。 - 绝对路径: 使用字符串路径,如
target = &{/soc/i2c@7e804000};。适用于没有标签的节点。
最佳实践: 优先使用标签引用。在基础设备树中为关键节点(如 I2C、SPI、GPIO 控制器)添加标签,可以大幅提高 Overlay 的可维护性。
3.4 __overlay__ —— 定义附加内容
__overlay__ 节点内部包含要附加到目标节点的具体内容。这些内容可以是:
- 新增属性: 如
status = "okay";、compatible = "my-device"; - 修改属性: 覆盖目标节点中已有的属性值
- 新增子节点: 在目标节点下添加新的设备节点
- 删除节点/属性: 使用
/delete-node/或/delete-property/指令
fragment@1 {
target = &spi0;
__overlay__ {
#address-cells = <1>;
#size-cells = <0>;
sensor@0 {
compatible = "bosch,bme280";
reg = <0>;
spi-max-frequency = <10000000>;
};
};
};
3.5 fragment —— 操作单元封装
fragment 节点将 target 和 __overlay__ 组合成一个完整的操作单元。每个 fragment 对应一次独立的设备树修改操作。fragment 的命名规则为 fragment@N,其中 N 从 0 开始递增。
注意: fragment 的编号顺序不影响加载顺序。加载顺序由 Overlay 的加载顺序决定,而非 fragment 编号。但保持编号连续和有序是良好的编码习惯。
3.6 完整语法结构图
下图展示了 Overlay 文件的完整语法结构及各元素之间的关系:
3.7 多 fragment 示例
实际工程中,一个 Overlay 文件常包含多个 fragment,分别操作不同的目标节点。以下示例同时使能 I2C1 控制器并在 SPI0 总线上添加一个传感器:
/dts-v1/;
/plugin/;
/ {
fragment@0 {
target = &i2c1;
__overlay__ {
status = "okay";
clock-frequency = <400000>;
};
};
fragment@1 {
target = &spi0;
__overlay__ {
#address-cells = <1>;
#size-cells = <0>;
temperature_sensor: sensor@0 {
compatible = "maxim,max31865";
reg = <0>;
spi-max-frequency = <5000000>;
status = "okay";
};
};
};
};
3.8 常见错误与避坑
- 遗漏 /plugin/: 编译时不会报错,但生成的 .dtbo 文件无法被内核正确识别为 Overlay。
- target 路径错误: 如果 target 指向的节点在基础设备树中不存在,加载 Overlay 时会失败。
- __overlay__ 拼写错误: 注意是双下划线 + overlay + 双下划线,容易误写为
_overlay_或__overlay。 - fragment 编号重复: 虽然不影响加载,但会导致编译警告,且不利于调试。
调试技巧: 使用
dtc -@ -I dts -O dtb -o output.dtbo input.dts 编译 Overlay,-@ 选项确保生成符号表。加载失败时,通过 dmesg | grep overlay 查看内核日志定位问题。