1、设备树基础概念:什么是设备树、为什么需要设备树、设备树在Linux内核中的角色

各位同学好,我是老李。今天咱们来聊聊设备树——这个在嵌入式Linux开发中绕不开的话题。说实话,我刚入行那会儿,设备树还是个新鲜玩意儿,那时候大家还在用老式的板级文件。嗯,现在想想,变化真快。

1.1 什么是设备树?

设备树,英文叫 Device Tree,简称 DT。说白了,它就是一个描述硬件信息的数据结构。你想想看,一块开发板上有什么CPU、什么内存、什么外设,这些信息怎么告诉内核?设备树就是干这个的。

设备树用文本文件(.dts)来描述硬件,然后通过编译器(dtc)编译成二进制文件(.dtb)。内核启动时,bootloader会把.dtb传给内核,内核解析后就知道自己跑在什么硬件上了。

核心要点:设备树 = 硬件描述语言 + 数据传递机制

我举个例子。假设你有一块板子,上面有个UART串口,地址在0x10000000,中断号是33。在设备树里,你会这么写:

/ {
    uart@10000000 {
        compatible = "ns16550";
        reg = <0x10000000 0x1000>;
        interrupts = <33>;
    };
};

你看,compatible告诉内核这是哪种驱动,reg描述地址和大小,interrupts描述中断号。内核拿到这个信息,就知道怎么初始化这个串口了。

1.2 为什么需要设备树?

这个问题,我得从历史讲起。在设备树出现之前,Linux内核是怎么处理硬件的?

  • 板级文件时代:每个板子都有一个 board-xxx.c 文件,里面写满了硬件信息。比如 arch/arm/mach-omap2/ 下面,有几十个这样的文件。
  • 问题来了:每次换个板子,就得改内核代码,重新编译。维护成本越来越高,尤其是ARM架构,碎片化严重。

我记得有一次,客户换了个Flash芯片,我改了三天代码。为什么?因为板级文件里硬编码了Flash的时序参数,得重新适配。那时候我就想,要是能把硬件信息抽出来,不就不用改内核了吗?

设备树就是来解决这个问题的。它把硬件描述从内核代码中剥离出来,变成独立的数据文件。好处很明显:

  1. 解耦:硬件变了,改.dts文件就行,不用动内核源码
  2. 统一:所有架构都用同一套描述方式,不再各自为政
  3. 可维护:一个.dtb文件对应一个板子,清晰明了

我的经验:刚开始接触设备树时,我总觉得它复杂。但用久了你会发现,它其实是个很优雅的设计。尤其是做产品迭代时,换个Flash、改个GPIO,改改.dts就搞定,不用重新编译整个内核。

1.3 设备树在Linux内核中的角色

设备树在内核里扮演什么角色?我把它总结为三个关键词:桥梁、配置器、适配器

先看一张图,帮你理解设备树在内核启动过程中的位置:

设备树在Linux内核启动中的角色 Bootloader 加载.dtb到内存 设备树(.dtb) 硬件描述数据 Linux内核 解析设备树,初始化硬件 内核内部处理流程 1. 解析设备树 2. 匹配驱动 3. 初始化硬件 设备树是Bootloader与内核之间的硬件信息桥梁 内核通过设备树实现硬件无关性 桥梁 配置器 适配器

从这张图你能看到,设备树处在Bootloader和内核之间,是个典型的桥梁角色。具体来说:

1.3.1 桥梁角色

Bootloader把设备树传给内核,内核通过设备树了解硬件。没有这个桥梁,内核就得自己去猜硬件配置,或者靠板级文件硬编码。我见过一些老项目,换个Flash就得改内核,就是因为没有设备树这个桥梁。

1.3.2 配置器角色

设备树不仅描述硬件,还能配置硬件参数。比如你可以通过设备树设置GPIO的默认电平、时钟频率、DMA通道等。这有点像BIOS里的设置,但更灵活。

举个例子:同一个驱动,在不同板子上可能用不同的中断号。设备树里配一下就行,驱动代码不用改。这就是配置器的威力。

1.3.3 适配器角色

设备树让内核能够适配不同的硬件平台。你想想看,一个Linux内核镜像,可以跑在几百种ARM板子上,靠的就是设备树。启动时,内核根据设备树信息,动态初始化对应的硬件。

注意:设备树不是万能的。它只描述硬件,不包含驱动逻辑。驱动代码还是要写的。设备树只是让驱动和硬件解耦,让驱动更通用。

1.4 设备树的核心文件类型

做设备树开发,你主要会接触这几类文件:

文件类型 扩展名 说明
设备树源文件 .dts 文本格式,人类可读,描述硬件
设备树头文件 .dtsi 类似C语言的.h,公共定义放这里
设备树二进制 .dtb 编译后的二进制,内核直接使用
设备树覆盖 .dtbo 运行时动态加载的设备树片段

我个人习惯把.dtsi当作公共库来用。比如SoC厂商会提供一个通用的.dtsi,板卡厂商再基于它写自己的.dts。这样复用性很好。

避坑指南:我曾经犯过一个错误,在.dts里直接修改了.dtsi定义的节点,结果导致其他板子也受影响。后来我学会了用 &node 的方式引用节点,在.dts里做覆盖,这样就不会污染公共文件了。

1.5 小结

设备树不是什么高深的东西,它就是一套硬件描述规范。你把它想象成硬件的「身份证」就行。内核拿到这个身份证,就知道怎么跟硬件打交道。

嗯,这一章就到这里。记住三个关键词:桥梁、配置器、适配器。后面我们会深入设备树的语法、编译、调试,一步步带你成为设备树高手。


公众号:蓝海资料掘金营,微信deep3321