3. 设备树编译器:dtc工具的使用,编译与反编译,dtb文件的生成与加载
设备树写好了,怎么变成机器能读懂的东西?
这就得靠dtc——设备树编译器。说白了,dtc就是把我们写的.dts文本文件,转成二进制的.dtb文件。反过来,也能把.dtb反编译回.dts,方便调试。
我刚开始接触设备树时,总觉得这步很简单。直到有一次,一个逗号写错了位置,折腾了我整整一个下午。嗯,从那以后,我对dtc的每个警告都不敢轻视了。
3.1 dtc工具是什么?
dtc全称是Device Tree Compiler。它是设备树生态的核心工具。你想想看,没有它,我们写的那些花里胡哨的节点、属性,都只是一堆文本而已。
dtc主要做三件事:
- 编译:.dts → .dtb
- 反编译:.dtb → .dts
- 检查:验证设备树语法是否正确
我个人习惯,每次修改完设备树后,先用dtc编译一下,看看有没有报错。这比直接烧到板子上再调试,效率高太多了。
3.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:指定输出文件名- 最后一个参数是输入文件
我在项目中遇到过,有些新手喜欢省略-I和-O参数。dtc确实能自动识别,但万一识别错了呢?还是显式指定更靠谱。
-@选项,可以生成带符号表的dtb。这对后续动态加载overlay很有用。
3.3 反编译:从.dtb回到.dts
调试时经常需要反编译。比如从内核或bootloader里拿到的dtb,想看看里面到底写了什么。
dtc -I dtb -O dts -o decompiled.dts my_board.dtb
反编译出来的dts,和原始dts可能不完全一样。为什么?因为编译过程中,一些注释会被丢掉,属性顺序也可能变化。但逻辑上是等价的。
我曾经反编译过一个别人的dtb,发现里面有个GPIO的pinmux配置写错了。要不是能反编译回来看看,这bug还真不好找。
3.4 常用选项与实战技巧
dtc的选项不少,但常用的就这几个:
| 选项 | 作用 | 我的建议 |
|---|---|---|
-@ |
生成符号表 | 建议默认加上 |
-H |
指定phandle格式 | 一般用默认即可 |
-W |
启用特定警告 | 调试时很有用 |
-E |
启用特定错误检查 | 建议全开 |
-v |
显示版本信息 | 确认工具版本 |
举个例子,我想检查设备树里有没有重复的节点名:
dtc -I dts -O dtb -o test.dtb -W duplicate_node_names test.dts
3.5 dtb文件的生成流程
在实际项目中,dtb的生成通常不是手动敲命令,而是集成在构建系统里。比如Linux内核的编译系统,或者Yocto、Buildroot等。
但不管用哪种构建系统,核心流程都一样:
- 编写或修改.dts/.dtsi源文件
- 调用dtc进行编译
- 生成.dtb文件
- 将.dtb打包到镜像中,或单独烧录
我见过一个项目,他们把dtb生成写成了一个独立的Makefile。每次修改设备树后,只需要make dtbs,所有板型的dtb就都重新生成了。这个做法值得借鉴。
3.6 dtb的加载过程
dtb怎么被加载到内核的?不同平台略有差异,但大体流程是:
- U-Boot:从存储介质(如eMMC、SD卡、SPI Flash)读取dtb到内存,然后通过寄存器或参数传递给内核
- UEFI:通过ACPI或设备树协议传递
- 裸机:直接烧录到固定地址,由启动代码加载
以U-Boot为例,常见的加载命令:
load mmc 0:1 ${fdt_addr_r} my_board.dtb
bootz ${kernel_addr_r} - ${fdt_addr_r}
这里${fdt_addr_r}是dtb在内存中的地址。内核启动时,会从这个地址解析设备树。
我曾经踩过一个坑:U-Boot加载dtb的地址,和内核期望的地址不一致。结果内核启动到一半就崩了。后来查了半天,才发现是地址没对齐。嗯,这种低级错误,犯过一次就记住了。
3.7 知识体系:dtc工具的核心逻辑
下面这张图,帮你理清dtc工具在整个设备树生态中的位置和作用:
3.8 避坑指南
最后,分享几个我踩过的坑:
- 路径问题:dtc默认在当前目录找include文件。如果.dts里引用了其他目录的.dtsi,记得用
-i指定搜索路径。 - 版本兼容:不同版本的dtc,对语法的检查严格程度不一样。我建议用和内核版本匹配的dtc。
- 大小写敏感:设备树是大小写敏感的。NodeName和nodename是两个不同的节点。我曾经因为这个,浪费了半天时间。
- 不要手动编辑dtb:dtb是二进制文件,别用文本编辑器打开。想修改,就反编译成dts,改完再编译回去。
好了,dtc工具的使用就讲到这里。记住,工具是死的,思路是活的。多动手编译几次,自然就熟练了。
可可精品资料库