2、DTS、DTB、DTC 关系详解:源文件、编译产物与编译器工作流程
设备树从可读的文本描述到内核可解析的二进制数据,需要经过一个明确的编译流程。理解 DTS(源文件)、DTB(二进制) 与 DTC(编译器) 三者之间的关系,是调试设备树编译报错的基础。
2.1 核心概念定义
在深入工作流程之前,先明确三个核心组件的定义与角色:
| 组件 | 全称 | 文件格式 | 核心作用 |
|---|---|---|---|
| DTS | Device Tree Source | 纯文本(.dts / .dtsi) | 开发者编写的设备树源文件,描述硬件拓扑、寄存器地址、中断、时钟等节点信息。 |
| DTC | Device Tree Compiler | 可执行程序 | 将 DTS 源文件编译为 DTB 二进制文件的工具,同时负责语法检查与错误报告。 |
| DTB | Device Tree Blob | 二进制(.dtb) | Bootloader 传递给内核的最终设备树数据,内核通过解析 DTB 来枚举和配置硬件。 |
关键区分:
.dtsi 文件是“包含头文件”,通常用于存放 SoC 公共定义(如 CPU 核、中断控制器、时钟控制器),而 .dts 文件是板级文件,通过 #include 引用 .dtsi 并添加或覆盖板级特有的外设节点。
2.2 完整工作流程:从源文件到二进制
DTC 的编译过程并非简单的文本到二进制转换,它包含预处理、语法解析、节点合并、符号生成和二进制打包等多个阶段。下图展示了从 .dts 源文件到 .dtb 二进制文件的完整流水线:
2.3 编译命令与典型输出
在实际开发中,最常用的 DTC 编译命令格式如下:
# 基本编译:将 .dts 编译为 .dtb
dtc -I dts -O dtb -o output.dtb input.dts
# 反编译:将 .dtb 反编译为 .dts(调试利器)
dtc -I dtb -O dts -o output.dts input.dtb
# 生成符号表(用于设备树叠加层)
dtc -@ -I dts -O dtb -o output.dtb input.dts
参数说明:
-I:指定输入格式(dts 或 dtb)。-O:指定输出格式(dtb 或 dts)。-o:指定输出文件名。-@:生成符号表,支持设备树叠加层(DTO)功能。-Wno-unit_address_vs_reg:忽略某些非致命警告,常用于清理编译输出。
2.4 编译过程中的常见报错类型
DTC 在编译过程中会执行严格的语法和语义检查。理解报错类型有助于快速定位问题:
| 错误类型 | 典型报错信息 | 常见原因 |
|---|---|---|
| 语法错误 | syntax error before '...' token |
缺少分号、花括号不匹配、属性值格式错误。 |
| 节点重复 | Duplicate node name 'xxx' |
同一层级下出现两个相同名称的节点,且未使用 label: node 区分。 |
| 属性类型错误 | Expected integer value for property 'reg' |
reg 属性需要 <u32> 或 <u64> 格式,却写成了字符串。 |
| 引用未定义 | Reference to non-existent node or label '&xxx' |
使用 &xxx 引用标签,但该标签未在任何地方定义。 |
| 地址格式错误 | Bad cell value for 'reg' |
reg 属性中的地址或长度值不是合法的十六进制数。 |
2.5 反编译验证:调试的“照妖镜”
当 DTC 编译成功但内核行为异常时,反编译验证 是最有效的调试手段之一。通过将编译后的 .dtb 反编译回 .dts,可以检查 DTC 是否按照预期合并了节点、覆盖了属性。
反编译验证的典型场景:
- 节点覆盖检查: 确认
.dtsi中的默认值是否被板级.dts正确覆盖。 - 标签解析验证: 检查
&xxx引用是否被正确展开为完整节点路径。 - 属性值精度确认: 验证
reg、interrupts等数值属性是否按预期编码。 - 删除操作确认: 检查
/delete-node/或/delete-property/是否生效。
反编译命令示例:
# 将编译后的 DTB 反编译为可读的 DTS
dtc -I dtb -O dts -o decompiled.dts compiled.dtb
# 对比原始 DTS 与反编译 DTS 的差异
diff -u original.dts decompiled.dts
2.6 工作流程中的关键注意事项
- 预处理顺序: DTC 内部调用 C 预处理器(cpp)处理
#include、#define和#ifdef,因此可以在.dts中使用 C 风格的宏定义。 - 节点合并规则: 同名节点在合并时,后出现的属性值会覆盖先出现的属性值,但子节点会递归合并而非覆盖。
- 标签作用域: 标签(label)在整个设备树中必须是唯一的,否则 DTC 会报重复标签错误。
- 二进制对齐: DTB 文件内部结构要求 4 字节对齐,DTC 会自动填充对齐字节,开发者无需手动处理。