100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 【嵌入式环境下linux内核及驱动学习笔记-(11-设备树)】

【嵌入式环境下linux内核及驱动学习笔记-(11-设备树)】

时间:2022-09-13 07:32:21

相关推荐

【嵌入式环境下linux内核及驱动学习笔记-(11-设备树)】

目录

1、设备树体系1.1 DTS /DTSI / DTC / DTB 2、基础语法2.1 节点语法2.1.1 通用名称建议 2.2 属性语法2.2.1 属性值 2.3 关于label2.4 节点的[@unit-address] 与reg属性2.5 根节点 /2.6 标准属性compatible2.6.1 of_machine_is_compatible函数 2.7 地址编码2.7.1 标准属性#address-cells 与 #size-cells2.7.2 标准属性reg2.7.3 标准属性ranges (地址转换)2.7.3.1 转载个实例: 2.7.4 dma-ranges2.7.5 2.3.10. dma-coherent2.7.6 name (deprecated)2.7.7 device_type (deprecated) 2.8 中断连接2.8.1 属性phandle 与linux,phandle2.8.2中断产生设备的 属性interrupts2.8.3 中断产生设备的属性interrupt-parent2.8.4 中断产生设备的属性interrupts-extended2.8.5 中断控制器属性#interrupt-cells2.8.6 中断控制器属性 interrupt-controller2.8.7 中断关系属性 interrupt-map2.8.4 中断关系属性 interrupt-map-mask2.8.5 中断关系属性 #interrupt-cells2.8.6 中断映射示例 2.9 Nexus节点和说明符映射2.9.1 <specifier>-map2.9.2 <specifier>-map-mask2.9.3 <specifier>-map-pass-thru2.9.4. #<specifier>-cells2.9.4 指定符映射示例 2.10 通用属性GPIO2.10.1 GPIO控制器属性2.10.1.1 gpio-controller2.10.1.2 GPIO控制器属性 #gpio-cells 2.10.2 GPIO使用者属性2.10.2.1 GPIO使用者节点xxx-gpio 2.11 status 3、通过一个样机进行实操4、设备特殊数据4.1 特殊节点4.1.1 aliases 节点4.1.2 chosen 节点 4.2 Advanced Topics 高级主题4.2.1 Advanced Sample Machine 先进的样品机4.2.2 PCI Host Bridge(PCI主机桥)4.2.2.1 PCI总线编号4.2.2.2 PCI地址转换4.2.2.3 PCI DMA地址转换4.2.3 高级中断映射

本章内容参考:/Device_Tree_Usage

设备树是一种描述硬件的数据结构。

Bootloader会在运行最后,将这棵传递给内核,然后内核再将树里所刻画的资源绑定给展开的相应的设备。

1、设备树体系

设备树体系包括描述硬件信息的数据文件和对其进行编译的工具。

1.1 DTS /DTSI / DTC / DTB

.dts (device tree source): 是一个ASCII文本格式的设备树描述。在ARM平台对应的dts文件存放在arch/arm/boot/dts目录中。

.dtsi (device tree source include ):对于一些相同的dts配置可以抽象到dtsi文件中,然后类似于C语言的方式可以include到dts文件中,对于同一个节点的设置情况,dts中的配置会覆盖dtsi中的配置。

.dtb (device tree blob):文件.dtb是.dts被DTC编译后的二进制格式的设备树描述,可由Linux内核解析。

DTC(Devcie Tree Compiler):DTC是将.dts编译为.dtb的工具。DTC源代码位于内核的scripts/dtc目录中,编译内核时一并被编译出来

在Linux下,我们可以单独编译设备树文件。命令是在Linux内核目录内运行make dtbs。

可以在Ubuntu系统上通过指令apt-get install device-tree-compiler安装dtc工具

DTC还可以“反汇编”.dtb文件为.dts文件,指令为:

注意:可以到内核 的Documentation/devicetree/bindings目录下,找到对设备树中的节点和属性进行讲解的文本文档,以.txt为后缀名。

用以下的图来说明这些文件之间的关系:

2、基础语法

先展示一个.dts设备树的例子:

设备树.dts文件和.dtsi文件是由一系列被命名的节点(Node)属性(Property)组成,节点本身还可包含子节点。

而属性,就是成对出现的名称和值。

在设备树中,可描述的信息包括:

CPU的数量和类别内存基地址和大小总线和桥外设连接中断控制器和中断使用情况GPIO控制器和GPIO使用情况时钟控制器和时钟使用情况

因此接下来,就分别说明节点的语法和属性的语法。

2.1 节点语法

[label:] node-name[@unit-address] {

[properties definitions]

[child nodes]

}

“[]”表示option(可选项的意思),因此可以定义一个只有node name的空节点,label相当于node-name的别名,方便在dts文件中引用每个节点必须有一个“<名称>[@<设备地址>]”形式的名字。如果该节点描述的设备有一个地址的话就还应该加上设备地址(unit-address)。通常,设备地址就是用来访问该设备的主地址,并且该地址也在节点的 reg 属性中列出。多个相同类型设备节点的name可以一样,只要unit-address不同即可。

2.1.1 通用名称建议

节点的名称应该有点通用,反映设备的功能,而不是其精确的编程模型。如果合适,名称应为以下选项之一:

2.2 属性语法

[label:] property-name = value;

[label:] property-name;

属性可以无值有值的属性

具体属性可以如下格式:“

补充:

如果是64位的值 0x1122334455667788 则需要拆分成两个32位的值来表示: <0x11223344 0x55667788>

2.2.1 属性值

2.3 关于label

如上2.1的节点语法,我们可以给一个设备节点添加label,之后就可以通过 &label的形式访问这个label。

如在linux 3.14内核中的/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi中有如下代码:

在同一个目录下的exynos4412-origen.dts有对该label的引用。

2.4 节点的[@unit-address] 与reg属性

1、对于挂 在内存空间的设备而言,@字符后跟的一般就是该设备在内存空间的基地址,如arch/arm/boot/dts/exynos4210.dtsi

在该节点的reg属性的起始地址(例中为0x0000)与@后面的地址是一样的。

2、对于挂在IIC总线上的外设而言,@后面一般跟的是IIC从设轩的IIC地址,譬如arch/arm/boot/dts/exynos4210-trats.dts中的:

2.5 根节点 /

根节点”/“ 表示整个开发板的信息。所有其它设备节点都是它的后代,即它的子节点。

基下包含了一些直接属性:

2.6 标准属性compatible

Linux内核通过根节点“/”的兼容属性即可判断它启动的是什么设备。一般包括两个或者两个以上的兼容性字符串,首个兼容性字符串是板子级别的名字,后面一个兼容性是芯片极别的名字。

内核编程时一般使用of_machine_is_compatible()函数来比较某个设备的兼容性。

2.6.1 of_machine_is_compatible函数

声明在:include/linux/of.h

定义在:drivers/of/base.c

int of_machine_is_compatible(const char *compat)

它的工作是:

获取根设备节点(根路径为"/")检查根设备节点的兼容性属性与传入的 compat 字符串是否匹配如果匹配则返回 1,否则返回 0

那么它与某个具体的设备树文件是如何关联的呢?这是通过内核的编译和启动过程实现的。

具体来说:

4. 当编译一个内核时,需要指定一个设备树文件(通过DEVICE_TREE Makefile 变量),这个设备树文件会被编译到内核的二进制镜像中。

5. 当内核启动时,它会从二进制镜像中提取此设备树文件,并根据设备树文件初始化内核的设备树数据结构。

6. 此后,每当内核的任何部分需要访问设备树信息时,它都会从这棵已经初始化的内核设备树中获取信息。

7. of_machine_is_compatible() 函数就是通过检查内核已初始化的设备树与传入的兼容字符串是否匹配来实现其功能的。

8. 所以实际上,在内核编译和启动的整个过程中,隐式地将一个具体的设备树文件与内核相关联了。这个设备树文件就是内核要管理和访问的硬件设备信息的来源。

2.7 地址编码

2.7.1 标准属性#address-cells 与 #size-cells

父节点的#address-cells和#size-cells分别决定了子节点reg属性的address和length字段的长度,这个长度单位是uint32。

比如:根节点的#address-cells=<1>; #size-cells=<1>,则其下的serial、gpio、spi等节点的address和length字段的长库就分别是1.

如下:

2.7.2 标准属性reg

其中的每一组address length表明了设备使用的一个地址范围。address为1个或多个32位的整型,而length的意义则意味着从address到address+length-1的地址范围都属于该节点。若#size-cells=0 ,则length字段为空。

address和length字段是可变长的,父节点的#address-cells和#size-cells分别决定了子节点reg属性的address和length的长度。

特别的是如果是IIC节点,假设它的address字段为0x58,这是是该设备的I2C地址。

2.7.3 标准属性ranges (地址转换)

https://devicetree-specification.readthedocs.io

ranges的值可以是: <空值> 或者可以是如下的 三元组。

ranges <(child-bus-address parent-bus-address length) >

即:ranges<子总线地址、父总线地址、长度>

说明:

ranges属性提供了一种定义总线的地址空间(子地址空间)和总线节点的父地址空间(父地址空间)之间的映射或转换的方法。

ranges属性的值的格式是任意数量的三元组(子总线地址、父总线地址、长度)

"子总线地址"是子总线地址空间中的一个物理地址。表示地址的cell个数取决于总线,可以根据该节点(出现ranges属性的节点)的#address-cells 来确定。

"父总线地址"是父总线地址空间中的一个物理地址。表示父地址的cell个数取决于总线,可以根据定义父地址空间的节点的#address-cells属性来确定。

“长度”指定子级地址空间中范围的大小。表示大小的cell个数可以根据该节点(出现range属性的节点)的#size-cells来确定。

注意:

如果属性是用<空>值定义的,则它指定父地址空间和子地址空间相同,并且不需要地址转换。如果总线节点中不存在该属性,则假定节点的子节点和父地址空间之间不存在映射。

soc节点指定的范围属性为 <0x0 0xe0000000 0x00100000>;

此属性值指定,对于1024 KB范围的地址空间,位于物理0x0的子节点映射到物理0xe000000的父地址。通过这种映射,serial 设备节点可以被加载或存储在位于0xe0004600的地址,偏移量为0x4600(在reg中指定)加上ranges中指定的0xe000000映射。

2.7.3.1 转载个实例:

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。