文章目录
概述
为什么要引入总线设备架构?为了更好扩展和减少内核的臃肿
使用总线设备架构会导致linux内核臃肿,在linux内核之外,利用设备树dtb(配置文件)去定义不同单板平台的引脚资源信息,可以保持linux内核的干净,且替换设备树可以不用去编译内核文件,便于开发
开发板中设备树文件目录结构
输入:ls /sys/firmware
输出:/devicetree fdt
-
devicetree文件夹目录下是以目录结构呈现的 dtb 文件, 根节点对应 base 目录,每一个节点对应一个目录, 每一个属性对应一个文件。
- 这些属性的值如果是字符串,可以使用
cat 命令把它打印出来;对于数值,可以用hexdump把它打印出来。
- 这些属性的值如果是字符串,可以使用
-
fdt文件就是dtb文件,可以反编译为dts文件
./scripts/dtc/dtc -I dtb -O dts -o tmp.dts arch/arm/boot/dts/xxx.dtb // 反编译 dtb 为dts
一个单板启动时,U-boot 先运行,它的作用是启动内核。U-boot 会把内核和设备树文件都读入内存,然后启动内核。在启动内核时会把设备树在内存中的地址告诉内核。在内核的打印信息中, ftdfile的属性值会指定设备树挂载哪个文件
设备树文件语法
设备树文件dts,使用时需要编译为dtb文件
设备树文件参考实例:
例如:dts 文件如下

它对应的 dtb 文件如下:

Devicetree 格式
DTS 文件的格式
DTS 文件布局(layout):
/dts-v1/; // 表示版本
[memory reservations] // 格式为: /memreserve/ <address> <length>;
/ {
[property definitions]
[child nodes]
};
node 的格式
设备树中的基本单元,被称为“node”,其格式为:
[label:] node-name[@unit-address] {
[properties definitions]
[child nodes]
};
label 是标号,可以省略。label 的作用是为了方便地引用 node,比如:
/dts-v1/;
/ {
uart0: uart@fe001000 {
compatible="ns16550";
reg=<0xfe001000 0x100>;
};
};
可以使用下面 2 种方法来修改 uart@fe001000 这个 node:
// 在根节点之外使用 label 引用 node :
&uart0 {
status = “disabled”;
};
//或在根节点之外使用全路径:
&{
/uart@fe001000} {
status = “disabled”;
};
properties 的格式
简单地说,properties 就是“name=value”,value 有多种取值方式。
有多种格式:
- Property 格式 1:
[label:] property-name = value;
- Property 格式 2(没有值):
[label:] property-name;
- Property 取值只有 3 种:
1. arrays of cells(1 个或多个 32 位数据, 64 位数据使用 2 个 个 32 位数据表示),
2. string( 字符串),
3. bytestring(1 个或多个字节)
示例:
interrupts = <17 0xc>;//Arrays of cells : cell 就是一个 32 位的数据,用尖括号包围起来
clock-frequency = <0x00000001 0x00000000>;//64bit 数据使用 2 个 cell 来表示,用尖括号包围起来:
compatible = "simple-bus";//A null-terminated string (有结束符的字符串),用双引号包围起来:
local-mac-address = [00 00 12 34 56 78]; //A bytestring(字节序列) ,用中括号包围起来;每个 byte 使用 2 个 16进制数来表示
compatible = "ns16550", "ns8250";//可以是各种值的组合, 用逗号隔开:
example = <0xf00f0000 19>, "a strange property format";//可以是各种值的组合, 用逗号隔开:
dts 文件包含 dtsi 文件
设备树文件不需要我们从零写出来,内核支持了某款芯片比如 imx6ull,
在内核的 arch/arm64/boot/dts (或arch/arm32/boot/dts)目录下就有了能用的设备树模板,一般命名为xxxx.dtsi。“i”表示“include”,被别的文件引用的。根据某款芯片制作出了自己的单板,所用资源跟 xxxx.dtsi 是大部分相同,小部分不同,所以需要引脚 xxxx.dtsi 并修改。dtsi 文件跟 dts 文件的语法是完全一样的。dts 中可以包含.h 头文件,也可以包含 dtsi 文件,在.h 头文件中可以定义一些宏。
格式:
/dts-v1/;
#include <dt-bindings/input/input.h>
#include "stm32mp15xx-100ask.dtsi"
/ {
……
};
常用的属性
#address-cells 、#size-cells
- cell 指一个 32 位的数值,
- address-cells:address 要用多少个 32 位数来表示;
- size-cells:size 要用多少个 32 位数来表示。
示例:比如一段内存,怎么描述它的起始地址和大小?
/ {
#address-cells = <1>;//address-cells 为 1,所以 reg 中用 1 个数来表示地址,即用0x80000000 来表示地址
#size-cells = <1>;//size-cells 为 1,所以 reg 中用 1 个数来表示大小,即用 0x20000000 表示大小:
memory {
reg = <0x80000000 0x20000000>;
};
};
compatible
“compatible”表示“兼容”,对于某个 LED,内核中可能有 A、B、C 三个
驱动都支持它,那可以这样写:
led {
compatible = “A”, “B”, “C”;
}

本文详细介绍了Linux设备树的概念、目录结构、文件格式以及设备树节点的语法。设备树用于定义不同单板平台的硬件资源,通过dts文件描述,编译成dtb文件供内核使用。内容涵盖了设备树节点的属性、常见节点类型如根节点、CPU节点和memory节点,以及如何通过设备树获取设备资源。此外,还讨论了设备树与内核、驱动程序的匹配机制和资源分配。
2203

被折叠的 条评论
为什么被折叠?



