1、设备树入门:什么是设备树?为什么需要设备树?设备树在Linux系统中的角色

各位同学,咱们今天聊聊设备树。

说实话,我刚入行那会儿,Linux内核里还没有设备树这东西。那时候写驱动,板级信息全写在 arch/arm/mach-xxx 下面,一个板子一个文件,改个GPIO都得重新编译内核。后来我接手一个项目,要同时支持三块不同配置的开发板,那叫一个痛苦。嗯,设备树就是来解决这个问题的。

什么是设备树?

设备树(Device Tree),说白了就是一个描述硬件信息的文本文件。

它用树形结构来描述:

  • CPU 有几个核
  • 内存地址范围
  • 外设挂在哪个总线上
  • 中断号、GPIO号、时钟频率
  • 等等等等

你想想看,以前这些信息是硬编码在C代码里的。换一块板子,就得改代码、重新编译。有了设备树,硬件描述和内核代码就分开了。内核只需要解析设备树,就能知道当前跑在什么硬件上。

核心思想:设备树 = 硬件配置的「说明书」。内核读说明书,不猜硬件。

设备树的文件后缀是 .dts(Device Tree Source),编译后变成 .dtb(Device Tree Blob),内核启动时加载它。

为什么需要设备树?

我总结三个最直接的原因:

  1. 解耦硬件与驱动 —— 驱动代码不再关心板级差异。同一个驱动,换个设备树就能适配不同板子。
  2. 减少内核分支 —— 以前每个开发板都要维护一个 board-xxx.c,内核里塞了几百个这样的文件。设备树一出,这些文件全砍了。
  3. 启动时动态适配 —— bootloader 可以修改设备树,比如调整内存大小、关闭某个外设。内核不用重新编译。

我记得有一次,客户临时要求换一颗Flash芯片,引脚完全兼容,但容量不同。我改了一下设备树里的 reg 属性,重新打包 .dtb,十分钟搞定。要是以前,得改 board-xxx.c,重新编译内核,再烧录,至少半天。

小提示:设备树不是Linux独有的。U-Boot、FreeBSD、甚至一些RTOS也支持设备树。学会它,一通百通。

设备树在Linux系统中的角色

咱们来看一张图,你就明白了。

设备树在Linux系统中的角色 硬件层(CPU、内存、外设、总线) 设备树(.dtb)—— 硬件描述 Linux内核(解析设备树,匹配驱动) 设备驱动(读取设备树属性,初始化硬件) 硬件 → 设备树描述 → 内核解析 → 驱动匹配 → 设备正常工作

流程其实很简单:

  • 硬件是客观存在的,设备树是它的「翻译官」。
  • 内核启动时,读取设备树,知道有哪些设备、怎么访问。
  • 驱动根据设备树里的信息,去初始化对应的硬件。

举个例子。你写一个LED驱动,以前你得知道LED接在哪个GPIO上,写死在代码里。现在呢?设备树里写:

leds {
    compatible = "mycompany,myled";
    led-gpios = &gpio1 3 GPIO_ACTIVE_HIGH;
};

驱动里只需要读 led-gpios 这个属性,就能拿到GPIO号。板子变了,改设备树就行,驱动代码不用动。

注意:设备树不是万能的。它只描述硬件「有什么」、「在哪」,不描述「怎么用」。怎么用,还是驱动的事。

设备树的核心概念(快速扫一眼)

概念 说明 我的一点经验
节点(node) 一个硬件设备或总线 每个节点就是一个「设备对象」
属性(property) 描述节点的信息 比如地址、中断号、时钟频率
compatible 驱动匹配的关键字 驱动靠它找到对应的设备
reg 寄存器地址和长度 告诉驱动「去哪读写」
interrupts 中断号 中断控制器和中断号配对

你可能会问:「这么多概念,怎么记?」

我的建议是:先别死记。后面几章我们会手把手写一个完整的设备树,从零到一。你跟着写一遍,自然就记住了。

避坑指南:我曾经犯过一个低级错误——设备树里写错了 reg 的地址范围,结果驱动读写时访问了非法内存,系统直接死机。排查了半天才发现是设备树的问题。所以,写设备树一定要仔细核对硬件手册的地址。

小结

设备树不是什么高深的东西。它就是一份硬件配置清单,让内核知道「我在什么板子上跑」。

你想想看,没有设备树的时候,每换一块板子就要改内核代码、重新编译。有了设备树,改个文本文件就行。这就是它的价值。

嗯,这一章先讲到这里。下一章我们开始动手写第一个 .dts 文件,到时候你就知道设备树到底长什么样了。

可可精品资料库