一、设备树基础概念
什么是设备树?
设备树,英文叫 Device Tree,是一套描述硬件资源的数据结构。说白了,它就是一份「硬件配置清单」。
我刚开始接触嵌入式 Linux 时,总觉得这玩意儿有点玄乎。后来做项目多了才明白——设备树其实就是告诉内核:你的板子上有哪些外设、它们挂在哪里、用哪个中断、GPIO 怎么配。
设备树的文件后缀通常是 .dts(Device Tree Source),编译后会生成 .dtb(Device Tree Blob),内核启动时直接读取这个二进制文件。
核心要点:设备树 = 硬件描述语言,专门给 Linux 内核用的。
为什么需要设备树?
在早期 Linux 内核中,硬件信息是直接写在 C 代码里的。比如 arch/arm/mach-xxx 目录下,每个板子都有对应的 board 文件。你想想看,换一个 GPIO 就要改源码、重新编译内核,多麻烦。
我遇到过最头疼的一次:客户临时换了颗传感器,中断引脚从 GPIO1_3 改到了 GPIO2_7。当时我改完 board 文件,编译内核花了 20 分钟,烧录又花了 10 分钟。后来换成设备树,改两行 dts,重新编译 dtb 几秒钟搞定。
设备树解决了三个核心问题:
- 硬件与驱动解耦——同一份内核镜像可以跑在不同板子上
- 减少内核编译次数——改硬件配置不用重编内核
- 统一描述格式——ARM、RISC-V、x86 都用同一套规则
我的经验:做产品开发时,设备树文件比内核源码改得更频繁。建议把 dts 文件纳入版本管理,跟硬件原理图一一对应。
设备树在 Linux 内核中的角色
内核启动时,设备树扮演了「硬件导游」的角色。它告诉内核:
- CPU 是什么架构、几个核、频率多少
- 内存起始地址和大小
- 每个外设的寄存器基地址
- 中断控制器是 GIC 还是老式的
- GPIO 控制器挂在哪个总线下面
我画了一张图,帮你理解设备树在内核中的位置:
内核启动时,Bootloader(比如 U-Boot)会把 dtb 文件加载到内存,然后传给内核。内核的 OF(Open Firmware)子系统负责解析这个二进制文件,把硬件信息提取出来,供各个驱动使用。
设备树的基本语法
来看一个最简单的设备树节点:
/dts-v1/;
/ {
model = "MyBoard v1.0";
compatible = "vendor,myboard";
uart0: serial@10000000 {
compatible = "ns16550";
reg = <0x10000000 0x1000>;
interrupts = <0 33 4>;
clock-frequency = <1843200>;
};
};
这里我解释几个关键字段:
| 字段 | 含义 | 我的理解 |
|---|---|---|
compatible |
兼容性字符串,驱动匹配的依据 | 相当于硬件的「身份证号」 |
reg |
寄存器基地址和范围 | 告诉驱动去哪里操作硬件 |
interrupts |
中断号、触发类型 | 这个我踩过坑,后面细说 |
#address-cells |
地址字段占几个 32 位 | 32位系统通常是1,64位是2 |
注意:我曾经遇到一个坑——设备树里 reg 的地址写错了,导致驱动 probe 失败。排查了半天才发现是地址多了一个 0。所以写设备树时,一定要对照原理图和数据手册,一个字都不能错。
设备树与中断、GPIO 的关系
中断和 GPIO 是设备树里最常用的两个资源。为什么把它们放在一起讲?因为在实际项目中,它们经常是绑定的。
比如一个按键,它既是一个 GPIO 输入,又会产生中断。设备树里是这样描述的:
gpio-keys {
compatible = "gpio-keys";
button@0 {
label = "Power";
gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
interrupts = <&gpio1 3 IRQ_TYPE_EDGE_FALLING>;
};
};
这里 gpios 指定了 GPIO 控制器、引脚号和有效电平。interrupts 指定了中断控制器、中断号和触发方式。两者配合,才能实现按键检测。
我个人的习惯是:先确认硬件原理图上的 GPIO 编号,再查芯片手册找到对应的中断号,最后写到设备树里。顺序不能乱,否则驱动拿到的资源就是错的。
设备树的编译与使用
写好的 .dts 文件需要编译成 .dtb:
# 编译设备树
dtc -I dts -O dtb -o myboard.dtb myboard.dts
# 反编译(调试用)
dtc -I dtb -O dts -o myboard.dts myboard.dtb
我建议你在开发阶段,每次改完设备树都反编译验证一下。有时候语法错误不会报错,但生成的 dtb 可能不完整。
小技巧:用 fdtdump 工具可以查看 dtb 的原始内容,适合快速确认设备树是否被正确加载。
总结一下
设备树不是什么高深的技术,它就是一份硬件配置清单。把硬件信息从内核源码里抽出来,放到一个独立文件里,方便修改和维护。
做嵌入式 Linux 开发,设备树是绕不开的一关。尤其是中断和 GPIO 的配置,稍不注意就会出问题。后面的章节,我会结合具体项目案例,带你一步步搞定这些配置。
记住一句话:设备树写对了,驱动开发就成功了一半。