3、设备树编译器(DTC):安装、编译、反编译与输出格式
设备树编译器(Device Tree Compiler,DTC)是设备树工具链的核心组件,负责将人类可读的 .dts 源文件转换为内核可解析的二进制 .dtb 文件,也支持反向操作。掌握 DTC 的安装、编译、反编译及输出格式,是进行设备树调试与内核故障定位的基础。
3.1 DTC 的安装
DTC 通常作为独立工具包或内核源码的一部分提供。推荐使用以下方式安装:
| 安装方式 | 命令/步骤 | 适用场景 |
|---|---|---|
| 包管理器安装(推荐) | sudo apt-get install device-tree-compiler (Debian/Ubuntu)sudo yum install dtc (CentOS/RHEL) |
快速搭建开发环境,版本稳定 |
| 从内核源码编译 | make scripts 或 make dtc (在内核根目录) |
需要与内核版本严格对齐时 |
| 从 GitHub 源码编译 | git clone https://git.kernel.org/pub/scm/utils/dtc/dtc.gitcd dtc && make && sudo make install |
需要最新特性或修复补丁时 |
验证安装: 执行
dtc --version,若输出类似 Version: DTC 1.7.0 的信息,则安装成功。
3.2 编译:从 DTS 到 DTB
编译是将 .dts 源文件转换为内核可加载的二进制 .dtb 文件的过程。基本命令格式如下:
dtc -I dts -O dtb -o <输出文件.dtb> <输入文件.dts>
常用编译选项:
-I dts:指定输入格式为 DTS 源文件。-O dtb:指定输出格式为 DTB 二进制文件。-o <file>:指定输出文件名。-@:生成可叠加的 DTB(支持__symbols__节点,用于设备树叠加)。-H epapr:指定生成的 DTB 使用 ePAPR 标准(默认)。-W no-unit_address_vs_reg:关闭特定警告,用于兼容老旧 DTS。
实战示例:
# 将 myboard.dts 编译为 myboard.dtb,并启用叠加支持
dtc -I dts -O dtb -@ -o myboard.dtb myboard.dts
3.3 反编译:从 DTB 到 DTS
反编译用于将二进制 DTB 还原为可读的 DTS 源文件,是调试内核启动时实际加载的设备树配置的关键手段。
dtc -I dtb -O dts -o <输出文件.dts> <输入文件.dtb>
常用反编译选项:
-I dtb:指定输入格式为 DTB 二进制文件。-O dts:指定输出格式为 DTS 源文件。-s:在输出中保留原始偏移量信息,便于对比分析。-f:强制覆盖输出文件。
注意: 反编译得到的 DTS 文件会丢失原始 DTS 中的注释和宏定义(如
#include 展开后的内容),但保留了完整的节点结构和属性值,足以用于故障定位。
3.4 输出格式详解
DTC 支持三种核心输出格式,理解其差异对调试至关重要:
| 格式 | 扩展名 | 类型 | 用途 | 可读性 |
|---|---|---|---|---|
| DTS | .dts |
文本源文件 | 人类编辑、版本管理、代码审查 | 高 |
| DTB | .dtb |
二进制文件 | 内核引导加载、Bootloader 传递、生产烧录 | 低 |
| DTBO | .dtbo |
二进制叠加文件 | 运行时动态修改设备树(如外设模块热插拔) | 低 |
3.5 设备树叠加(DTBO)编译
设备树叠加允许在不修改主 DTB 的情况下,动态添加或修改节点。编译叠加文件需使用 -@ 选项生成带符号的主 DTB,然后编译叠加 DTS:
# 1. 编译主 DTB(必须带 -@ 符号)
dtc -I dts -O dtb -@ -o main.dtb main.dts
# 2. 编译叠加 DTS 为 DTBO
dtc -I dts -O dtb -@ -o overlay.dtbo overlay.dts
加载 DTBO 通常由 Bootloader(如 U-Boot)或内核的 configfs 接口完成。
3.6 DTC 工作流程与数据流
下图展示了 DTC 在设备树开发与调试中的核心位置,以及三种输出格式之间的转换关系:
3.7 常用选项速查表
| 选项 | 功能 | 典型用法 |
|---|---|---|
-I <格式> |
指定输入格式(dts/dtb/fs) | -I dts |
-O <格式> |
指定输出格式(dts/dtb/asm) | -O dtb |
-o <文件> |
指定输出文件路径 | -o output.dtb |
-@ |
生成符号节点(支持叠加) | -@ -o main.dtb |
-s |
反编译时保留偏移信息 | -s -O dts |
-W <警告> |
启用特定警告 | -W no-unit_address_vs_reg |
-E <错误> |
将警告视为错误 | -E unit_address_vs_reg |
-v |
显示详细编译信息 | -v -O dtb |
-H <格式> |
指定 DTB 头部格式 | -H epapr |
3.8 调试故障定位中的典型用法
案例:内核启动时外设未识别
- 提取实际加载的 DTB: 从
/sys/firmware/devicetree/base复制或使用dtc -I fs -O dtb -o captured.dtb /sys/firmware/devicetree/base。 - 反编译分析:
dtc -I dtb -O dts -o captured.dts captured.dtb。 - 对比预期 DTS: 使用
diff比较captured.dts与原始.dts文件,定位缺失或错误的节点/属性。 - 验证修复: 修改 DTS 后重新编译
dtc -I dts -O dtb -o fixed.dtb fixed.dts,替换内核使用的 DTB 并重启测试。
提示: 使用
dtc -O dts -I dtb -s 反编译时,-s 选项会输出每个节点在 DTB 中的偏移地址,有助于分析 DTB 结构是否被 Bootloader 修改过。