1. 设备树基础:从一块砖头说起
我记得刚入行那会儿,做嵌入式Linux移植,最头疼的就是板子换了颗Flash芯片,内核代码得改好几个地方。那时候我就在想——有没有一种办法,把硬件描述和内核源码彻底分开?
后来我遇到了设备树。说白了,它就是一套描述硬件信息的“配置文件”。你换硬件,改这个文件就行,不用动内核代码。
1.1 设备树的起源与作用
设备树的全称是 Device Tree,最早源于PowerPC架构。Linux内核在2.6时代开始引入,到了3.x版本,ARM架构全面拥抱它。
为什么需要它?你想想看,以前每个板子都要在arch/arm/mach-xxx目录下写一堆board-xxx.c文件,里面全是GPIO、中断、时钟的硬编码。内核每支持一个新板子,就得加一堆C代码。这哪受得了?
设备树的作用,就是把这些硬件信息抽出来,放到一个独立的文本文件里。内核启动时解析这个文件,动态构建硬件拓扑。这样一来:
- 内核与硬件解耦:换板子不用重新编译内核
- 同一内核镜像:可以启动不同硬件配置的板子
- 维护成本降低:硬件描述集中管理,不用到处翻C代码
核心思想:设备树 = 硬件拓扑的“数据驱动”描述。内核只负责解析,不负责硬编码。
1.2 设备树语法基础
设备树的源文件后缀是 .dts,编译后的二进制是 .dtb。语法看起来有点像JSON和C的混合体。我刚开始看的时候也觉得别扭,但用多了就习惯了。
先看一个最简单的例子:
/dts-v1/;
/ {
model = "MyBoard V1.0";
compatible = "vendor,myboard-v1", "vendor,myboard";
#address-cells = <1>;
#size-cells = <1>;
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x10000000>;
};
chosen {
bootargs = "console=ttyS0,115200 root=/dev/mmcblk0p2";
};
soc {
#address-cells = <1>;
#size-cells = <1>;
ranges;
serial@10000000 {
compatible = "vendor,uart";
reg = <0x10000000 0x1000>;
interrupts = <0 33 4>;
clock-frequency = <24000000>;
};
};
};
这里有几个关键点,我一个个说:
- 根节点:
/是设备树的根,所有设备都在它下面 - 属性:
compatible、reg、interrupts这些都是属性,描述设备的特征 - 地址编码:
#address-cells和#size-cells决定地址和长度用几个32位整数表示 - reg属性:格式是
<地址 长度>,比如reg = <0x80000000 0x10000000>表示从0x80000000开始,256MB空间
我的习惯:写设备树时,先把根节点的 model 和 compatible 写好。这两个属性是内核匹配板子的关键,写错了板子起不来。
1.3 设备树与ACPI的对比
ACPI(高级配置与电源管理接口)是x86平台的硬件描述标准。设备树和ACPI虽然干的是同一件事——描述硬件,但思路完全不同。
我做过一个项目,需要在同一套硬件上同时支持Linux和Windows。Linux用设备树,Windows用ACPI。那段时间我天天跟这两套东西打交道,感触很深。
| 对比维度 | 设备树 (DT) | ACPI |
|---|---|---|
| 起源 | PowerPC/嵌入式 | x86/PC |
| 文件格式 | 文本(.dts) → 二进制(.dtb) | AML字节码(二进制) |
| 可读性 | 高,文本直接可读 | 低,需要反编译 |
| 运行时修改 | 支持overlay动态加载 | 支持DSDT替换 |
| 电源管理 | 弱,需要额外驱动 | 强,原生支持 |
| 热插拔 | 支持有限 | 原生支持 |
| 适用场景 | 嵌入式、ARM、RISC-V | x86、服务器、笔记本 |
说白了,设备树更“轻”,ACPI更“重”。设备树适合资源受限的嵌入式系统,ACPI适合功能复杂的PC平台。
我曾经踩过的坑:在ARM服务器上尝试用ACPI替代设备树。结果发现ACPI的AML解释器占用的内存比设备树整个都大。后来还是老老实实用回了设备树。选型时一定要考虑硬件资源。
1.4 知识体系总览
下面这张图,是我自己总结的设备树知识体系。你看一眼,心里就有谱了:
嗯,这张图把设备树的三个核心维度串起来了。语法是基础,作用是价值,对比是定位。你把这三点吃透了,后面学设备树集成和固件裁剪就会轻松很多。
1.5 小结
设备树不是什么高深的东西。它就是一套描述硬件的规则,让内核和硬件解耦。我见过很多新手一上来就啃设备树binding文档,结果越看越晕。我的建议是:先写一个最简单的.dts,编译成.dtb,让内核跑起来。然后再慢慢加节点、调属性。
实践出真知,这句话在设备树上特别适用。