3. 设备树编译器(DTC):从DTS到DTB的编译过程
设备树编译器,简称DTC,是Linux内核中一个不起眼但极其重要的工具。说白了,它的工作就是把我们人类能读懂的DTS文件,转换成机器能高效解析的DTB二进制文件。我在做嵌入式开发的头两年,几乎每天都在跟它打交道。
3.1 DTC工具的基本使用方法
DTC工具通常随内核源码一起发布,路径在 scripts/dtc/ 目录下。我个人习惯直接使用内核编译系统来调用它,但有时候也需要手动操作。
先看看最基本的用法:
# 编译DTS到DTB
dtc -I dts -O dtb -o output.dtb input.dts
# 反编译DTB到DTS
dtc -I dtb -O dts -o output.dts input.dtb
这里有几个关键参数:
- -I:指定输入文件格式,dts或dtb
- -O:指定输出文件格式,dts或dtb
- -o:指定输出文件名
小技巧:我建议你编译时加上 -@ 选项。这个选项会保留符号信息,方便后续调试。我在调试一个i.MX6的板子时,就因为没加这个选项,浪费了半天时间定位问题。
3.2 从DTS到DTB的编译过程
编译过程其实不复杂,但背后有几个关键步骤。我把它拆解成三个阶段:
- 预处理阶段:处理
#include和/include/指令,展开宏定义 - 解析阶段:将DTS文本解析成抽象语法树
- 生成阶段:将语法树序列化成二进制DTB格式
来看一个实际例子。假设我们有这样一个简单的DTS文件:
/dts-v1/;
/ {
compatible = "myboard,imx6ul";
#address-cells = <1>;
#size-cells = <1>;
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x20000000>;
};
chosen {
bootargs = "console=ttymxc0,115200";
};
};
编译命令很简单:
dtc -I dts -O dtb -o myboard.dtb myboard.dts
编译完成后,可以用 hexdump 或 fdtdump 查看生成的DTB文件结构。DTB文件头部有一个固定格式的header,包含了魔数、总大小、各区域偏移等信息。
核心要点:DTB文件采用大端字节序。这一点在跨平台开发时特别容易踩坑。我曾经在x86主机上编译DTB,然后放到ARM板子上用,结果因为字节序问题折腾了一整天。
3.3 反编译技巧
反编译DTB到DTS,是调试时最常用的操作。很多时候,我们拿到的只有DTB文件,或者想看看内核实际解析出来的设备树是什么样子。
基本反编译命令:
dtc -I dtb -O dts -o decompiled.dts board.dtb
但这里有个坑——反编译出来的DTS可能和原始DTS不完全一样。为什么?因为编译过程中,一些注释、空行、格式信息会丢失。另外,属性值的表示方式也可能变化。
举个例子,原始DTS中可能有这样的写法:
reg = <0x80000000 0x20000000>;
反编译后可能变成:
reg = <0x80000000 0x20000000>;
看起来一样?嗯,但如果你原始文件里用了 #include 包含的头文件,反编译后这些头文件会被展开成具体的内容。我曾经遇到过这样的情况:反编译后得到一个巨大的DTS文件,完全找不到原来的结构层次。
注意:反编译时加上 -s 选项可以输出更简洁的格式,去掉一些冗余信息。但如果你需要保留所有细节,就别加这个选项。
3.4 高级用法与调试技巧
除了基本的编译和反编译,DTC还有一些高级功能。我个人最常用的是 -H 选项,它可以指定输出格式的版本:
# 生成旧版本格式的DTB
dtc -I dts -O dtb -H epapr -o old.dtb input.dts
另外,-V 选项可以查看DTC的版本信息。不同版本的DTC对语法的检查严格程度不同。我记得有一次,一个同事的DTS文件在旧版本DTC上编译通过,但换到新版本就报错了。原因是新版本对属性值的类型检查更严格。
还有一个很实用的功能是 -W 和 -E 选项,用于控制警告和错误:
# 关闭所有警告
dtc -W no-* -I dts -O dtb -o output.dtb input.dts
# 将警告视为错误
dtc -E -I dts -O dtb -o output.dtb input.dts
3.5 知识体系图
下面这张图展示了DTC工具的核心工作流程和关键知识点:
3.6 实战经验总结
最后,分享几个我在项目中积累的经验:
- 版本匹配很重要:内核版本和DTC版本要匹配。不同版本对设备树语法的支持程度不同。
- 善用make dtbs:在内核源码根目录下执行
make dtbs,会自动编译所有设备树文件。 - 检查DTB有效性:用
dtc -I dtb -O dts /dev/null可以快速检查DTB文件是否损坏。 - 保留原始DTS:反编译只是辅助手段,不要完全依赖它来还原原始文件。
嗯,说到检查DTB有效性,我想起一个案例。有次客户反馈板子启动到一半就卡住了。我远程一看,发现是DTB文件在传输过程中被截断了。用fdtdump一查,文件大小不对,头部校验失败。从那以后,我每次烧录前都会先校验DTB的完整性。
DTC工具虽然简单,但用好它能让你的设备树开发效率提升不少。记住,工具是死的,经验是活的。多动手、多踩坑,自然就熟练了。
公众号:蓝海资料掘金营,微信deep3321