第四节:设备树编译器——dtc工具的使用、编译与反编译、常用选项

设备树写好了,怎么变成机器能懂的东西?

答案就是——dtc,设备树编译器。全称 Device Tree Compiler。

说实话,这工具看着不起眼,但它是整个设备树生态的基石。我刚开始接触设备树时,觉得不就是个编译器嘛,跟gcc差不多。后来踩了几个坑才发现,dtc的细节远比想象中多。

4.1 dtc是什么?

dtc负责把人类可读的.dts文件,转成二进制.dtb文件。反过来也能把.dtb还原成.dts,这叫反编译。

你想想看,uboot、内核、TF-A这些组件,最终读的都是.dtb。所以dtc就是那个“翻译官”。

核心流程:

.dts(文本) → dtc编译 → .dtb(二进制) → 内核解析

我个人习惯在开发阶段频繁使用dtc的-W和-E选项,能提前发现很多问题。后面会细说。

4.2 编译:从.dts到.dtb

最基本的用法,一行命令搞定:

dtc -I dts -O dtb -o my_board.dtb my_board.dts

参数解释:

  • -I dts:输入格式是dts
  • -O dtb:输出格式是dtb
  • -o my_board.dtb:指定输出文件名

实际项目中,我更喜欢加几个选项:

dtc -I dts -O dtb -o my_board.dtb -W no-unit_address_vs_reg -@ my_board.dts

-@这个选项很重要。它允许生成符号节点,方便后续overlay。我在做模块化设计时,几乎必加这个选项。

4.3 反编译:从.dtb回到.dts

有时候拿到一个二进制的.dtb,想看看里面写了什么。反编译就派上用场了。

dtc -I dtb -O dts -o my_board_reverse.dts my_board.dtb

嗯,这里要注意:反编译出来的.dts,跟原始.dts不完全一样。注释会丢失,节点顺序也可能变化。但关键信息都在。

我曾经在调试一个第三方提供的固件时,对方只给了.dtb。我反编译后才发现,某个GPIO的配置跟原理图对不上。这种问题,不反编译根本发现不了。

4.4 常用选项详解

dtc的选项不少,但常用的就那几个。我整理了一张表:

选项 作用 我的建议
-I 指定输入格式(dts/dtb/fs) 默认是dts,但显式指定更安全
-O 指定输出格式(dts/dtb) 编译用dtb,反编译用dts
-o 输出文件名 建议跟板子名一致,方便管理
-W 启用特定警告 开发阶段建议全开
-E 启用特定错误检查 我习惯加 -E no_property_type
-@ 生成符号节点 做overlay时必须加
-H 指定phandle格式 默认epapr,一般不用改
-V 指定dtb版本 默认17,兼容性最好

小技巧:调试阶段可以用 dtc -I dts -O dts -o output.dts input.dts 来格式化dts文件。dtc会自动帮你整理缩进和对齐,比手动排版快多了。

4.5 编译过程中的常见错误

我见过太多人在dtc上栽跟头了。总结几个高频问题:

  • 语法错误:少了个分号,或者花括号不匹配。dtc的错误信息还算友好,会告诉你哪一行出问题。
  • 引用错误:用&引用节点时,节点不存在。检查一下标签名是否拼写正确。
  • 类型不匹配:比如reg属性应该用,结果写成了字符串。dtc会报warning,但不会阻止编译。

避坑指南:我曾经在项目中遇到一个诡异的问题——dtc编译通过,但内核启动时设备树解析失败。查了两天才发现,是某个节点的#address-cells写错了。dtc不会检查这种逻辑错误,它只负责语法层面。所以编译通过不代表设备树没问题。

4.6 实战:一个完整的编译流程

假设我们有一个项目,包含主设备树和两个overlay:

# 编译主设备树
dtc -I dts -O dtb -@ -o main.dtb main.dts

# 编译overlay
dtc -I dts -O dtb -@ -o overlay1.dtbo overlay1.dts
dtc -I dts -O dtb -@ -o overlay2.dtbo overlay2.dts

# 检查生成的dtb
dtc -I dtb -O dts -o main_check.dts main.dtb

注意overlay文件的扩展名是.dtbo,这是惯例。虽然dtc不强制,但uboot和内核都认这个命名规则。

4.7 知识体系图

下面这张图,是我对dtc工具知识点的梳理:

dtc工具知识体系 dtc 编译器 编译 .dts → .dtb 反编译 .dtb → .dts 语法检查 / 格式化 常用选项 -I / -O -o 输出文件 -W 警告 -E 错误检查 -@ 符号节点 常见错误 语法错误(少分号等) 引用错误(标签不存在) 类型不匹配(reg等) 编译通过 ≠ 设备树正确 逻辑错误需要结合硬件手册排查

4.8 一些实用技巧

最后分享几个我积累的小经验:

  • 批量编译:写个Makefile,用wildcard收集所有.dts文件,一行命令编译整个项目。
  • 版本控制:我习惯把.dts和生成的.dtb都提交到git。虽然.dtb是二进制文件,但方便其他人直接使用。
  • 调试技巧:用dtc -V 16可以生成旧版本的dtb,有时候兼容老内核会用到。

个人习惯:我每次修改设备树后,都会先做一次反编译,对比修改前后的差异。这能帮我快速发现手误。比如少写了一个逗号,或者把0x写成了0X,反编译结果一眼就能看出来。

dtc工具本身不复杂,但用好它需要积累经验。多编译、多反编译、多对比,慢慢就熟练了。


可可精品资料库