一、概述
Device Tree是一种描述硬件的数据结构,相比于旧架构它起源于 OpenFirmware (OF),在过去的ARM Linux中,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥着大量的冗余代码,相当多数的代码只是在描述板级硬件细节,而这些不同的板级细节描述对于内核来讲是不必要的,如板上的platform设备、resource、i2c_board_info、spi_board_info以及各种硬件的platform_data。
采用Device Tree后,许多硬件的细节可以直接透过DTS传递给Linux,而不再需要在kernel中进行大量的冗余编码。Device Tree由一系列被命名的结点(node)和属性(property)组成,而结点本身可包含子结点。所谓属性,其实就是成对出现的name和value。
1.ARM的核心代码仍然保存在arch/arm目录下
2.ARM SoC core architecture code保存在arch/arm目录下
3.ARM SoC的周边外设模块的驱动保存在drivers目录下
4.ARM SoC的特定代码在arch/arm/mach-xxx目录下
5.ARM SoC board specific的代码被移除,由Device Tree机制来负责硬件拓扑和硬件资源信息
本质上,Device Tree改变了原来用code的方式将硬件信息嵌入到内核代码的方法,改用bootloader传递一个DB的形式。对于嵌入式系统,
在系统启动阶段,bootloader会加载内核并将控制权限交给呢耦合,此外,还需要把上述的三个参数信息传递给kernel,以便有较大的灵活性,
在linux kernel中,Device Tree的设计目标就是如此。
在device tree中,可描述的信息包括:
在Device Tree中,可描述的信息有很多(原先这些信息大多被hard code到kernel中):
它基本就是一棵电路板上的CPU,总线,设备组成的树,Bootloader会将这棵树传递给内核,然后内核来识别这棵树,
这根据它展开出Linux内核中的 platform_device,i2c_client,spi_device等设备,而这些设备用到的内存,IRQ等资源,也被传递给内核,
内核会将这些资源绑定给展开的相应设备。
Linux内核从3.x开始引入设备树的概念,用于实现驱动代码和设备信息相分离。在设备树出现以前,所有关于设备的具体信息都要写在驱动里,一旦外围设备变化,驱动代码就要重写,引入了设备树之后,驱动代码只负责处理驱动的逻辑,而关于设备的具体信息存放到设备树文件中,这样,如果硬件接口信息的变化而没有驱动逻辑的变化,驱动开发者只需要修改设备树文件信息,不需要改驱动代码,
比如ARM Linux内,一个.dts(device tree source)文件对应一个ARM的machine,一般放置在内核的“arch/arm/booot/dts”目录内,
比如stm1a-dk1参考板的板级设备树文件就是“arch/arm/boot/stm32mp157a-dk1.dts”。
这个文件可以通过make ditbs命令编译成二进制的.dtb文件供内核驱动使用。基于同样的的软件分层设计的思想,由于一个SoC可能对应多个machine,如果每个machine的设备树都写成一个完全独立的.dts文件,那么势必相当一些.dts文件有重复的部分,为了解决这个问题,
Linux设备树目录把SoC公用的部分或者多个machine共同部分提炼为了相应的.disi文件。这样每个.dts就只有自己差异的部分,公有的部分只需要“include”相应的.dtsi文件。这样整个设备树的管理更加有序
BootLoader启动,传参给内核后,内核解析查看设备节点信息
一、方法一:进入/sys/firmware/devicetree/base目录查看
二、方法二:进入/proc/device-tress/
所有的节点信息,都可以查到,status打开还是关闭,都可以查,内核启动时,根据status,判断是否加载驱动,因此可以不在confiig来配置启动驱动,如果驱动没有加载,应该查看这个status。
二.设备树在源码的位置
1.设备树的api
drivers/of/base.c
drivers/of/platform.c
2.设备树的板载dts
arch/arm64/boot/dts/
3.设备树文件编译工具dtc
linux-3.10/scripts/dtc/dtc.c
4.用户级的fex配置文件需要转换成dtc文件
转换的方法是:
int dt_update_source(const char *fexname, FILE *f, struct boot_info *bi)
转换所在的源码位置:
scripts/dtc/updatetree.c
三、DTS、DTB、DTC
四、DTS结构,语法,属性
/dts-v1/;
/ {
node1 {
a-string-property = "A string";
a-string-list-property = "first string", "second string";
// hex is implied in byte arrays. no '0x' prefix is required
a-byte-data-property = [01 23 34 56];
child-node1 {
first-child-property;
second-child-property = <1>;
a-string-property = "Hello, world";
};
child-node2 {
........
};
};
node2 {
an-empty-property;
a-cell-property = <1 2 3 4>; /* each number (cell) is a uint32 */
child-node1 {
};
};
........
};
device tree的基本单元是一个node。这些node被组织成树状结构,除了root node,每个node都只有一个parent。一个device tree文件中只能有一个root node。每个node中包含了若干的property/value来描述node的一些特性。每个node用节点名字(node name)标识,节点名字的格式node-name@unit-address。如果该node没有reg属性(后面会描述这个property),
bus上相关。例如对cpu,其unit-address就是寄存器地址。root node的node name是确定的,必须是"/."。
从上面的设备树可以看到
1)一个根节点“/”;
2)根节点下面有可以有多个子节点
3)子节点可以包含自己的子节点如“child-node1”,“child-node2”
4)各个几点都有一系列的属性 (property)
(1)这些属性可能为空,如an-empty-property
(2) 可能为字符 a-string-proerty
(3) 可能为字符串树组 a-string-list-property
(4) 可能为cells(由u32)整型组成,如second-child-property
DTS语法介绍
基本数据类型:
1)text string(以null结束),以双引号括起来,如:string-property=“a string”;
2)cells是无符号32位无符号整型数,以括号括起来,如cell-proerty=<0xbeef 123 0xabcd1234>;
3)binary data 以方括号括起来,如:binary-property = [0x01 0x23 0x45 0x67];
4)不同类型数据可以在同一个属性中存在,以逗号分格,如:mixed-property = “a string”, [0x01 0x23 0x45 0x67],<0x12345678>;
5)多个字符串组成的列表也使用逗号分格,如:string-list = “red fish”,”blue fish”;