文章目录
- 四、/proc/device-tree目录
- **`/proc/device-tree` 目录解析**
- **1. 设备树如何加载到 `/proc/device-tree`**
- **2. `/proc/device-tree` 目录结构解析**
- **(1) 根目录 `/proc/device-tree/`**
- **(2) CPU 相关信息 `/proc/device-tree/cpus/`**
- **(3) 内存信息 `/proc/device-tree/memory/`**
- **(4) 片上系统(SoC)信息 `/proc/device-tree/soc/`**
- **3. `/proc/device-tree` 与 `dtb` 设备树二进制文件的关系**
- **4. 设备树在驱动中的应用**
- **5. 总结**
一、什么是设备树(Device Tree)
设备树(Device Tree, DT) 是一种用于描述 硬件 的数据结构,主要用于 ARM、PowerPC 及其他嵌入式系统中,以 独立于内核代码 的方式提供硬件信息。它的作用是让内核在启动时能够动态解析硬件配置,而无需对内核代码进行修改。
在 ARM 体系中,设备树广泛用于 Linux 内核、Bootloader(如 U-Boot),它解决了传统的“板级文件”模式(即在内核中硬编码硬件信息)的问题,使得同一份内核可以适用于不同的硬件平台。
二、设备树基础语法
设备树的源文件采用 DTS(Device Tree Source) 语法,类似于 C 语言结构体,主要包括 节点(node) 和 属性(property)。
1. 设备树基本结构
/ {compatible = "myboard,example"; // 兼容性信息,通常用于匹配驱动cpus {#address-cells = <1>;#size-cells = <0>;cpu@0 {compatible = "arm,cortex-a53";reg = <0>;};};memory {device_type = "memory";reg = <0x80000000 0x20000000>; // 表示内存起始地址和大小};soc {uart@10000000 { // 串口compatible = "ns16550";reg = <0x10000000 0x100>;clock-frequency = <24000000>;};gpio@20000000 { // GPIOcompatible = "myvendor,gpio";reg = <0x20000000 0x1000>;interrupts = <5 1>; // 中断号及触发方式};};
};
2. 语法解析
-
节点(node)
- 以
{}
包围,表示设备或总线,通常带有地址,如cpu@0
、uart@10000000
。 soc
是一个 SoC 设备的总线节点,里面包含 UART、GPIO 等子节点。
- 以
-
属性(property)
- 以
key = value;
形式出现,例如compatible = "ns16550";
。 reg = <地址 大小>;
表示设备的寄存器地址和大小。
- 以
-
特殊属性
compatible
:用于驱动匹配,表示设备支持的驱动类型。reg
:表示设备的寄存器基地址和大小。interrupts
:中断信息。
三、dtb 文件、dtsi 文件、dts 文件的区别
文件类型 | 作用 | 说明 |
---|---|---|
.dts | 设备树源文件 | 描述特定硬件的设备信息,最终转换为 .dtb |
.dtsi | 设备树包含文件 | 供多个 .dts 复用,类似 C 语言 #include |
.dtb | 设备树二进制文件 | .dts 编译后生成的二进制文件,供内核加载 |
1. DTS 文件(设备树源文件)
DTS 是设备树的主要源文件,定义特定开发板的硬件信息,最终需要被编译为 dtb
才能被 Linux 内核识别。
示例(myboard.dts
)
#include "common.dtsi" // 引入 dtsi 文件/ {model = "My Custom Board";compatible = "myvendor,myboard";memory {reg = <0x80000000 0x40000000>; // 1GB 内存};
};
2. DTSI 文件(设备树包含文件)
DTSI(Device Tree Source Include)文件是设备树的“公共部分”,通常用于存放通用硬件配置,多个 DTS 文件可以引用它,类似 C 语言中的 #include
。
示例(common.dtsi
)
/soc {uart@10000000 {compatible = "ns16550";reg = <0x10000000 0x100>;clock-frequency = <24000000>;};
};
这里的
common.dtsi
可以被多个不同的开发板.dts
复用。
3. DTB 文件(设备树二进制文件)
DTB(Device Tree Blob)是 DTS
文件经过编译后生成的二进制文件,Linux 内核或 Bootloader 直接加载这个文件,而不是解析 DTS 源文件。
DTS 编译生成 DTB
dtc -I dts -O dtb -o myboard.dtb myboard.dts
dtc
(Device Tree Compiler)是设备树编译工具,能将.dts
编译成.dtb
,也能反编译.dtb
为.dts
。
DTB 反编译回 DTS
dtc -I dtb -O dts -o myboard.dts myboard.dtb
总结:
.dts
:设备树源文件,定义具体开发板的硬件信息。.dtsi
:设备树包含文件,用于公共配置,被多个.dts
复用。.dtb
:设备树二进制文件,Linux 内核或 Bootloader 直接使用的文件,由.dts
编译而成。
设备树的引入使得 Linux 内核适配不同硬件变得更简单,无需修改内核代码,只需修改设备树即可支持新的硬件平台。
四、/proc/device-tree目录
/proc/device-tree
目录解析
在 Linux 内核 中,/proc/device-tree
是 设备树(Device Tree) 在系统中的一个虚拟文件系统(procfs),它提供了一个内核解析设备树后的视图,允许用户直接查看设备树信息,而无需解析 dtb
文件。
1. 设备树如何加载到 /proc/device-tree
设备树(DT, Device Tree)在系统启动时由 Bootloader(如 U-Boot) 加载,并传递给 Linux 内核,内核解析设备树 dtb
文件,并在 /proc/device-tree
下以目录树的方式映射出来,方便用户查看。
示例:
ls /proc/device-tree
可能输出:
#address-cells
#size-cells
model
compatible
memory
cpus
soc
这些文件和目录对应于 DTS(设备树源文件) 中的节点和属性。
2. /proc/device-tree
目录结构解析
设备树是层级化的结构,/proc/device-tree
也是如此,通常包含如下关键子目录:
(1) 根目录 /proc/device-tree/
文件 / 目录 | 作用 |
---|---|
model | 存放设备的型号,如 Raspberry Pi 4 Model B |
compatible | 硬件的兼容性信息,通常用于驱动匹配 |
memory | 设备的内存信息 |
cpus/ | CPU 信息,包含各个 CPU 核心的详细参数 |
soc/ | 片上系统(SoC)信息,包含串口、GPIO 等外设 |
示例:
cat /proc/device-tree/model
输出:
Raspberry Pi 4 Model B
这表明该设备是 树莓派 4B。
(2) CPU 相关信息 /proc/device-tree/cpus/
ls /proc/device-tree/cpus/
可能输出:
#address-cells
#size-cells
cpu@0
cpu@1
cpu@2
cpu@3
每个 cpu@X
目录表示一个 CPU 核心。
查看某个 CPU 的信息:
cat /proc/device-tree/cpus/cpu@0/compatible
可能输出:
arm,cortex-a72
这表明 CPU 是 Cortex-A72 架构。
(3) 内存信息 /proc/device-tree/memory/
ls /proc/device-tree/memory/
可能输出:
device_type
reg
查看 reg
(表示内存基地址和大小):
xxd /proc/device-tree/memory/reg
可能输出:
00000000: 00 00 00 00 08 00 00 00 00 40 00 00 00 00 00 00
这里:
0x80000000
表示内存起始地址。0x40000000
表示内存大小(1GB)。
(4) 片上系统(SoC)信息 /proc/device-tree/soc/
ls /proc/device-tree/soc/
可能输出:
gpio@3f200000
uart@3f215000
gpio@3f200000
:表示 GPIO 控制器,地址0x3F200000
。uart@3f215000
:表示串口设备,地址0x3F215000
。
查看串口信息:
cat /proc/device-tree/soc/uart@3f215000/compatible
可能输出:
brcm,bcm2835-uart
表明串口是 Broadcom BCM2835 UART。
3. /proc/device-tree
与 dtb
设备树二进制文件的关系
/proc/device-tree
的内容是从 dtb
设备树二进制文件解析出来的,可以通过 dtc
(设备树编译器)导出原始 DTS 设备树:
将 /proc/device-tree
转换回 DTS:
dtc -I fs -O dts -o extracted.dts /proc/device-tree
这样就可以获取系统当前使用的设备树。
4. 设备树在驱动中的应用
在 Linux 设备驱动开发中,驱动程序通常会通过 /proc/device-tree
解析设备信息,加载相应的驱动。
示例:在驱动中读取 compatible
属性
struct device_node *np;
np = of_find_node_by_path("/soc/uart@3f215000");
if (np) {const char *compat;if (of_property_read_string(np, "compatible", &compat) == 0) {printk("UART Compatible: %s\n", compat);}
}
of_find_node_by_path()
:根据路径查找设备树节点。of_property_read_string()
:读取compatible
属性,用于驱动匹配。
5. 总结
/proc/device-tree
是 Linux 内核解析 设备树(DTB) 后的视图。- 目录结构与 DTS 设备树源码类似,允许用户直接访问设备信息。
- 通过
/proc/device-tree
可以查询 CPU、内存、GPIO、串口等硬件信息,有助于调试嵌入式设备。 - 可以使用
dtc
反编译/proc/device-tree
为 DTS 设备树源码,便于分析系统当前加载的设备树配置。
设备树极大地简化了 Linux 内核对不同硬件的适配,/proc/device-tree
使开发者可以轻松获取设备信息,无需深入 Linux 内核代码。