2、设备树基础概念:DTS、DTC、DTB、DTBO文件格式与关系
好,咱们今天来聊聊设备树里最基础、也最容易搞混的几个概念——DTS、DTC、DTB、DTBO。说实话,我刚入行那会儿,看着这几个缩写也是一头雾水。后来在项目里被坑过几次,才真正搞明白它们之间的关系。
你想想看,设备树本质上就是一个描述硬件信息的“数据文件”。但硬件描述不能直接给内核用,得经过编译、转换。这中间就涉及到了四种文件格式。咱们一个一个说。
2.1 DTS:设备树源文件
DTS 全称 Device Tree Source,就是设备树的源代码。它用文本形式描述硬件信息,比如 CPU 数量、内存地址、外设寄存器、中断号等等。
我个人习惯把 DTS 文件比作“硬件的身份证”。里面写的都是板上钉钉的东西——哪个 GPIO 接了 LED,哪个 I2C 总线上挂了传感器,清清楚楚。
一个典型的 DTS 文件长这样:
/dts-v1/;
/ {
compatible = "vendor,board-name";
#address-cells = <1>;
#size-cells = <1>;
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x10000000>;
};
chosen {
bootargs = "console=ttyS0,115200";
};
};
嗯,这里要注意:DTS 文件里可以包含 #include 预处理指令,就像 C 语言一样。所以实际项目中,我们通常不会把整个板子的描述写在一个文件里,而是拆成多个 .dtsi 文件(设备树包含文件),然后通过 #include 组合起来。
2.2 DTC:设备树编译器
DTC 就是 Device Tree Compiler,负责把 DTS 编译成 DTB。它就像 C 语言里的 gcc,是连接源码和二进制文件的桥梁。
DTC 的用法很简单:
dtc -I dts -O dtb -o output.dtb input.dts
反过来,你也可以把 DTB 反编译成 DTS:
dtc -I dtb -O dts -o output.dts input.dtb
我曾经在调试一个启动问题的时候,手头只有别人给的 DTB 文件,没有源码。就是用这个反编译命令,把 DTB 转成 DTS,才找到了问题所在。所以这个技能你一定要掌握。
2.3 DTB:设备树二进制文件
DTB 是 Device Tree Blob 的缩写,就是编译后的设备树二进制文件。Bootloader(比如 U-Boot)在启动内核时,会把 DTB 加载到内存中,然后把它的地址传给内核。
说白了,内核启动时看到的硬件信息,就是从这个 DTB 里读出来的。它包含了所有硬件节点的地址、大小、中断号、时钟频率等关键数据。
DTB 文件的结构是扁平的,由一个个节点(node)和属性(property)组成。每个节点都有一个偏移量,内核通过遍历这些节点来获取硬件信息。
| 文件类型 | 格式 | 用途 |
|---|---|---|
| DTS | 文本 | 人类可读的硬件描述源码 |
| DTB | 二进制 | 内核直接使用的硬件描述数据 |
| DTBO | 二进制 | 可叠加的设备树片段 |
2.4 DTBO:设备树叠加文件
DTBO 是 Device Tree Blob Overlay 的缩写。它是个相对较新的概念,我接触它是在做 FPGA 动态加载项目的时候。
为什么需要 DTBO?你想想看,如果一块板子上有多个可插拔的模块,每个模块都有自己的设备树描述。总不能为每一种组合都编译一个完整的 DTB 吧?那太麻烦了。
DTBO 就是解决这个问题的。它只描述“增量”部分,然后通过叠加(overlay)的方式,合并到基础 DTB 上。
举个例子,基础 DTB 描述了一个 I2C 控制器,而 DTBO 描述了这个 I2C 总线上挂载的一个温度传感器。加载 DTBO 后,内核就能识别到这个传感器了。
编译 DTBO 的命令:
dtc -I dts -O dtb -@ -o overlay.dtbo overlay.dts
注意这里的 -@ 选项,它会在 DTB 中生成符号表,这样叠加时才能找到对应的节点。
- DTS 是源码,DTC 是编译器,DTB 是编译产物
- DTBO 是 DTB 的“补丁”,用于动态添加硬件
- 内核启动时只认 DTB,不认 DTS
- 调试时可以用 DTC 在 DTS 和 DTB 之间来回转换
2.5 它们之间的流转关系
咱们捋一下整个流程:
- 工程师编写 .dts 和 .dtsi 文件
- 构建系统调用 DTC 编译器,生成 .dtb 文件
- Bootloader 加载 .dtb 到内存,传给内核
- 内核解析 DTB,初始化硬件驱动
- 如果支持设备树叠加,可以在运行时加载 .dtbo 文件
我曾经遇到过一个坑:某次升级内核后,板子死活起不来。后来发现是 DTB 没更新,新内核里某个驱动改了设备树节点的命名规则,旧的 DTB 匹配不上。从那以后,我每次升级内核都会同步编译新的 DTB,再也不敢偷懒了。
好了,关于 DTS、DTC、DTB、DTBO 的基本概念和关系,咱们就聊到这里。下一节我会深入讲解 DTS 的语法细节,包括节点、属性、标签、引用这些内容。到时候咱们再细聊。