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 的安装方式取决于开发环境。以下列出三种主流途径:

  1. 发行版包管理器(推荐)
    # Debian / Ubuntu
    sudo apt-get install device-tree-compiler
    
    # Fedora / RHEL
    sudo dnf install dtc
    
    # Arch Linux
    sudo pacman -S dtc
  2. 从内核源码编译
    # 进入内核源码树的 scripts/dtc 目录
    cd linux/scripts/dtc
    make
    sudo make install

    此方式保证 DTC 版本与当前内核完全匹配,适合内核开发场景。

  3. 从 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 二进制文件的完整编译链路,包含预处理、编译和反编译三种路径:

DTC 编译 / 反编译流程 .dts / .dtsi .dtb (二进制) cpp 预处理 DTC 编译器 -I dts -O dtb .dtb (二进制) .dts (反编译) 💡 实线 = 编译路径(dts → dtb);虚线 = 反编译路径(dtb → dts)。 预处理步骤仅在 .dts 包含 #include 或宏定义时必需,可通过 -E 选项单独执行。

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 开始递增