设备树-1

设备树的主要优势:对于同一SOC的不同主板,只需更换设备树文件.dtb即可实现不同主板的无差异支持,而无需更换内核文件

1.设备树是什么?
由于对于内核而言这些platform设备、resource、i2c_board_info、spi_board_info以及各种硬件的platform_data绝大多数纯属垃圾冗余代码,所以需要一种方式将这些硬件的代码与内核代码隔开。
开源文档对设备树的描述是:
A data structure by which bootloaders pass hardware layout to Linux in a device-independent manner, simplifying hardware probing
①硬件信息通过bootload传递
②设备独立
③数据结构

2.设备树可以传递哪些信息?
CPU的数量和类别、内存基地址和大小、总线和桥、外设连接、中断控制器和中断使用情况、GPIO控制器和GPIO使用情况、Clock控制器和Clock使用情况。

其优势在于,对于使用同一个SOC的不同主板,只需要更换设备树文件 .dtb即可实现不同主板的无差异支持,而无需更换内核文件。

3.设备树怎么将设备信息传给内核?
-dts :是一种ASCII文本,里面放着对对Device Tree的描述,放置在内核的/arch/arm/boot/dts目录。一般而言,一个*.dts文件对应一个ARM的machine。
-dtsi,类似于C语言的头文件。因为不同板子上的设备肯定会有重叠,所以将其放在.dtsi中以供使用。
dtc为编译工具,将.dts编译为.dtb文件,.dtb为二进制文件。.dts可整体编译可单独编译。
Bootloader在引导内核的时候,会预先取.dtb到内存,进而由内核解析。
在ARM中通过bootm或bootz命令来进行传递。

4.设备树的前身
就原版本代码里面有一个device注册有关的函数,其相关模块会包含该设备的中断、内存基地址和大小、外设连接、GPIO等信息。在Linux 3.x后的版本,platform、i2c、spi等设备不再需要在mach-xxx中注册。
不同的设备会对应有一个驱动程序,如何将驱动程序与设备树中的设备对应呢,就是在驱动程序中放一个“tag”之类的标志,只要它与设备树中的对应deviece的"tag"配对,则可以锁定。
原本在device注册相关代码(mach-xxx的device)中有专门的API用来调用和读取设备对应的中断、GPIO等值。这种对属性的获取常常在probe函数中进行。但在获取属性之前,需要确定哪个节点触发了驱动。在驱动程序将直接和设备树里的设备节点进行配对,配对后获取设备树的相关中断、GPIO等信息,即属性的获取。配对借助的是compatible属性值。
即,按步骤来说,分为如下步骤:
①在设备树中配置好相关设备的信息
②每一个设备相关的驱动文件里有一个OF(Open Firmware)匹配表,匹配表中保存着一些compatible的值,通过查找设备树中compatible属性值,如若驱动程序的OF中的compatible与设备树中任一compatible相等,则表示设备可以使用这个驱动
③驱动文件中有特殊的API用于调用对应设备的节点中存放的属性值。只要驱动中的 of_match_table/(我们的是dw_dma_of_id_table)中compatible的值与设备节点中的compatible的值相匹配,probe函数就会被触发。
④probe函数中专门的API去获取设备树中设备对应的属性值与相关信息。

5.probe函数
函数中有专门的API获取设备树中存放的属性值,并赋给device的属性结构体中(这个结构体是什么目前还不知道)

到此,说白了驱动文件和设备树的关系就是,应该是,编译器把.dts编译成.dtb后,bootloader在启动时读取这个二进制文件,会根据设备树的compatible找到对应的驱动文件,一旦该节点被调用,就会征用对应的驱动文件进行驱动。而对应的驱动文件就是一个把设备的硬件信息输入到软件结构体的过程。

6.调用节点
“标号引用”的方式,通过&符号调用/访问该节点。在哪里定义不重要,重要的是在哪调用。

7.设备树语法
DTS基本语法:
它包括一系列节点,以及描述节点的属性。
-根节点 “/”为root节点
一个.dts文件中,只有一个root节点,在root节点下有“node1""node2"子节点,除了root节点外,每个节点有且仅有一个parent节点。
注:如果看过内核/arch/arm/boot/dts目录的读者看到这可能有一个疑问。在每个.dsti和.dts中都会存在一个“/”根节点,那么如果在一个设备树文件中include一个.dtsi文件,那么岂不是存在多个“/”根节点了么。其实不然,编译器DTC在对.dts进行编译生成dtb时,会对node进行合并操作,最终生成的dtb只有一个root node。Dtc会进行合并操作这一点从属性上也可以得到验证。这个稍后做讲解。
-节点属性,属性的值
(1).它可以是字符串string,如①;也可能是字符串数组string-list,如②
(2).它也可以是32 bit unsigned integers,如cell⑧,整形用<>表示
(3).它也可以是binary data,如③,十六进制用[]表示
(4).它也可能是空,如⑦
在这里插入图片描述
8.语法范例
在/arch/arm/boot/dts/目录中有一个文件skeleton.dtsi,该文件为各ARM vendor共用的一些硬件定义信息。以下为skeleton.dtsi的全部内容。

/ {

#address-cells = <1>;

#size-cells = <1>;

chosen { };

aliases { };

memory { device_type = “memory”; reg = <0 0>; };

};

8.1compatible属性
compatible属性也叫做“兼容性”属性,是一个字符串列表,compatible属性用于将设备和驱动绑定起来。字符串列表用于选择设备所要使用的驱动程序,格式如下所示

                                              “manufacturer,model”

其中manufacturrer表示厂商,model一般是模块对应的驱动名字.
该设备首先使用第一个兼容值在Linux内核中查找,看是否能找到与之匹配的驱动文件,如果第一个没找到就用第二个兼容值查。在驱动文件的OF匹配表中找。
static const struct of_device_id imx_wm8960_dt_ids[] = {
	{ .compatible = "fsl,imx-audio-wm8960", },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, imx_wm8960_dt_ids);
 
static struct platform_driver imx_wm8960_driver = {
	.driver = {
		.name = "imx-wm8960",
		.pm = &snd_soc_pm_ops,
		.of_match_table = imx_wm8960_dt_ids,
	},
	.probe = imx_wm8960_probe,
	.remove = imx_wm8960_remove,
};

8.2 #address-cells和#size-cells属性
这两个属性的值都是无符号32位整型的值,故要用<>表示,用于描述子节点的地址信息。#address-cells决定了子节点reg属性中地址信息所占用的字长(32位),#size-cells属性值决定了子节点reg属性中长度信息所占的字长。就一个决定地址的字长,一个决定表示长度的信息的字长。
所以当这两个值为2的时候,应该对应的是用64位表示地址以及用64位表示长度。

8.3reg属性
表示该设备所在基地址以及占据的长度。和地址相关的信息有两种:起始地址和地址长度, reg 属性的格式一为:

reg = <address1 length1 address2 length2 address3 length3……>

8.4

9.配置好设备树后,确认内核配置中包含了你需要的,比如dma
在build/…/linux/路径下
-make help
-make linux_kernel_menuconfig
-选中xxx dma
此即相当于”要把dma.c“文件编译进去。

  1. .dts , .dtsi 区分
    不止是一个头文件的关系,更是一个公共区域的关系,实际上是板级和芯片级的关系。芯片可以放在任意板子上,板子上的设备放在.dts,而芯片级的设备需要放在.dtsi。我需要的dma是芯片级资源。

11.部分节点介绍

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值