3. DTC 编译器介绍
DTC(Device Tree Compiler)是设备树源文件(.dts / .dtsi)到二进制设备树(.dtb)的核心转换工具,也是反向反编译(.dtb → .dts)的唯一官方工具。理解 DTC 的作用、安装与命令行选项,是掌握设备树编译流程的第一步。
3.1 DTC 工具的作用
DTC 在嵌入式 Linux 开发中承担三项关键职责:
| 功能 | 输入 → 输出 | 典型场景 |
|---|---|---|
| 编译 | .dts / .dtsi → .dtb |
将人类可读的设备树源文件转换为内核可解析的二进制 Blob |
| 反编译 | .dtb → .dts |
调试现有 DTB、验证编译结果、提取厂商固件中的设备树 |
| 预处理 | .dts + C 预处理器 → .dts.pre |
展开 #include、宏定义、条件编译(#ifdef) |
关键认知: DTC 本身不执行 C 预处理。当
.dts 中包含 #include 或宏时,必须通过 -E 选项或外部调用 cpp 先完成预处理,再送入 DTC 编译。
3.2 DTC 的安装方法
DTC 的安装方式取决于开发环境。以下列出三种主流途径:
- 发行版包管理器(推荐)
# Debian / Ubuntu sudo apt-get install device-tree-compiler # Fedora / RHEL sudo dnf install dtc # Arch Linux sudo pacman -S dtc - 从内核源码编译
# 进入内核源码树的 scripts/dtc 目录 cd linux/scripts/dtc make sudo make install此方式保证 DTC 版本与当前内核完全匹配,适合内核开发场景。
- 从 GitHub 仓库编译最新版
git clone https://git.kernel.org/pub/scm/utils/dtc/dtc.git cd dtc make sudo make install适用于需要最新特性(如
YAML输出、新绑定检查)的开发者。
版本兼容提醒: 低版本 DTC(v1.4.x)可能不支持
#include 语法或 /omit-if-no-ref/ 标签。建议使用 v1.6.0 及以上版本。可通过 dtc --version 检查当前版本。
3.3 基本命令行选项
DTC 的命令行结构为:
dtc [选项] [输入文件]
下表列出最常用的选项及其用途:
| 选项 | 全称 | 说明 |
|---|---|---|
-I |
输入格式 | dts(源文件)、dtb(二进制)、fs(文件系统目录) |
-O |
输出格式 | dtb(二进制)、dts(源文件)、yaml(YAML 描述) |
-o |
输出文件 | 指定输出路径,如 -o output.dtb |
-E |
仅预处理 | 执行 C 预处理后输出,不编译 |
-@ |
生成插件节点 | 允许生成 __symbols__ 节点,用于设备树叠加层(DTO) |
-H |
phandle 格式 | epapr(默认)、legacy、both |
-W |
启用警告 | 如 -W unit_address_vs_reg、-W graph_child_address |
-E |
启用错误 | 将指定警告升级为错误,如 -E graph_child_address |
-v |
版本信息 | 显示 DTC 版本号并退出 |
3.4 典型编译流程示例
以下 SVG 展示了从 .dts 源文件到 .dtb 二进制文件的完整编译链路,包含预处理、编译和反编译三种路径:
3.5 常用命令速查
# 1. 基本编译:dts → dtb
dtc -I dts -O dtb -o output.dtb input.dts
# 2. 反编译:dtb → dts
dtc -I dtb -O dts -o output.dts input.dtb
# 3. 仅预处理(展开 #include 和宏)
dtc -E -I dts -o preprocessed.dts input.dts
# 4. 编译时启用所有警告
dtc -I dts -O dtb -o output.dtb -W all input.dts
# 5. 生成支持叠加层的 DTB(含 __symbols__)
dtc -I dts -O dtb -o output.dtb -@ input.dts
# 6. 从 /proc/device-tree 目录重建 DTB(嵌入式调试)
dtc -I fs -O dtb -o recovered.dtb /proc/device-tree
调试技巧: 当编译报错“syntax error”或“bad character literal”时,先用
dtc -E 检查预处理后的文件,确认宏展开是否正确。多数语法错误源于 #define 宏展开后产生非法字符。
3.6 常见编译错误与排查方向
| 错误信息 | 可能原因 | 排查方向 |
|---|---|---|
FATAL ERROR: Unable to parse input tree |
输入文件格式错误或包含非法字符 | 检查文件编码(必须为 UTF-8)、确认 -I 参数与文件类型匹配 |
ERROR: Input tree has errors |
节点属性值类型不匹配或缺少必要属性 | 使用 -W all 查看具体警告,检查 reg、compatible 等关键属性 |
WARNING: unit_address_vs_reg |
节点名称中的地址与 reg 属性不匹配 |
确保 node@address 中的地址与 reg = <address> 一致 |
WARNING: graph_child_address |
图形绑定中端口节点地址不连续 | 检查 ports 下 port@ 节点的编号是否从 0 开始递增 |