当前位置:网站首页>图解Kernel Device Tree(设备树)的使用
图解Kernel Device Tree(设备树)的使用
2022-08-03 07:47:00 【内核笔记】
活动地址:CSDN21天学习挑战赛
文章目录
平台 | 内核版本 | 安卓版本 |
---|---|---|
RK3399 | Linux4.4 | Android7.1 |
本质上,Device Tree
改变了原来用hardcode
方式将HW
配置信息嵌入到内核代码的方法,改用bootloader
传递一个DB
的形式。对于基于ARM CPU
的嵌入式系统,我们习惯于针对每一个platform
进行内核的编译。但是随着ARM
在消费类电子上的广泛应用(甚至桌面系统、服务器系统),我们期望ARM
能够象X86
那样用一个kernel image
来支持多个platform
。在这种情况下,如果我们认为kernel
是一个black box
,那么其输入参数应该包括:
- 识别
platform
的信息 runtime
的配置参数- 设备的拓扑结构以及特性
对于嵌入式系统,在系统启动阶段,bootloader
会加载内核并将控制权转交给内核,此外,还需要把上述的三个参数信息传递给kernel
如上图,以便kernel
可以有较大的灵活性。在linux kernel
中,Device Tree
的设计目标就是如此。
一、device Tree包含的硬件信息有哪些?(海纳百川?)
Device Tree
是否可以描述所有的硬件信息?
答案是不行的,因为基本上,那些可以动态探测到的设备是不需要描述的,例如USB device
。不过对于SOC
上的usb host controller
,它是无法动态识别的,需要在device tree
中描述。同样的道理,在computer system
中,PCI device
可以被动态探测到,不需要在device tree
中描述,但是PCI bridge
如果不能被探测,那么就需要描述之。 需要描述的内容一般包括:
CPUs
Memory
Buses
Peripheral connections
Interrupt Controllers
GPIO controllers
Clock controllers
二、Device Tree示例 (线头)
为了了解Device Tree
的结构,我们首先给出一个Device Tree
的示例:
最重要的属性 compatible
, reg
, clocks
, interrupts
, and status
。
下面我们一起对其解析:
三、Device Tree语法解析(药引子)
其实DeviceTree
的结构非常简单,由两种元素组成:Node
(节点)、Property
(属性)。
从上图中可以看出,device tree
的基本单元是node
。系统中的每个设备用一个node
来描述,这些node
被组织成树状结构,除了root node
,每个node
都只有一个parent
。一个device tree
文件中只能有一个root node
。每个node
中包含了若干的property/value
来描述该node
的一些特性。每个node
用节点名字(node name
)标识,节点名字的格式是:
node-name
说明了何种设备,必须使用字符开头unit-address
访问此设备的主地址,必须唯一,必须和此节点的reg
属性的开始地址一致
[label:] node-name[@unit-address] {
[properties definitions]
[child nodes]
}
“[]”
表示option
,因此可以定义一个只有node name
的空节点。labe
l方便在dts
文件中引用。child node
的格式和node
是完全一样的,因此,一个dts
文件中就是若干嵌套组成的node
,property
以及child note
、child note property
描述。
注意:
如果该node
没有reg
属性,那么该节点名字中必须不能包括@
和unit-address
,例如上图spi0
总线下的device
child node
。unit-address
的具体格式是和设备挂在那个bus
上相关。例如对于cpu
,其unit-address
就是从0
开始编址,以此加一。而具体的设备,例如以太网控制器,其unit-address
就是寄存器地址。root node
的node name
是确定的,必须是“/”
。
四、特殊节点的介绍
4.1、根节点root node
只能有一个root node
,它用来描述从CPU
端看到的地址空间,至少需要用cpu
和memory
节点组成,如下:
/ {
compatible = "rockchip,rk3399";
interrupt-parent = <&gic>;
#address-cells = <2>;
#size-cells = <2>;
cpus {
......
}
4.2、别名节点
aliases
节点定义了一些别名。为何要定义这个node
呢?因为Device tree
是树状结构,当要引用一个node
的时候要指明相对于root node
的full path
,例如/node1/child-node1
。如果多次引用,每次都要写这么复杂的字符串多少是有些麻烦,因此可以在aliases
节点定义一些设备节点full path
的缩写。
4.3、CPU节点
对于根节点,必须有一个cpus
的child node
来描述系统中的CPU
信息。
cpus {
#address-cells = <2>;
#size-cells = <0>;
cpu_l0: [email protected]0 {
device_type = "cpu";
compatible = "arm,cortex-a53", "arm,armv8";
reg = <0x0 0x0>;
enable-method = "psci";
#cooling-cells = <2>; /* min followed by max */
clocks = <&cru ARMCLKL>;
dynamic-power-coefficient = <100>;
};
4.4、Memory节点
memory device node
是所有设备树文件的必备节点,它定义了系统物理内存的layout
。device_type
属性定义了该node
的设备类型,例如cpu
、serial
等。对于memory node
,其device_type
必须等于memory
。reg
属性定义了访问该device node
的地址信息,该属性的值被解析成任意长度的(address
,size
)数组,具体用多长的数据来表示address
和size
是在其parent node
中定义(#address-cells
和#size-cells
)。对于device node
,reg
描述了memory-mapped IO register
的offset
和length
。对于memory node
,定义了该memory
的起始地址和长度。
4.5、可选节点
chosen node
主要用来描述由系统firmware
指定的runtime parameter
。如果存在chosen
这个node
,其parent node
必须是名字是“/”
的根节点。原来通过tag list
传递的一些linux kernel
的运行时参数可以通过Device Tree
传递。例如command line
可以通过bootargs
这个property
这个属性传递;initrd
的开始地址也可以通过linux,initrd-start
这个property
这个属性传递。在实际中,建议增加一个bootargs
的属性,例如:
chosen {
bootargs = "console=ttymxc0,115200"; };
我们知道,device tree
用于HW platform
识别,runtime parameter
传递以及硬件设备描述。chosen
节点并没有描述任何硬件设备节点的信息,它只是传递了runtime parameter
。
五、属性
5.1、Compatible属性和model属性
“compatible”
属性通常用来device
和driver
的适配,推荐的格式为”manufacturer,model”
demo:
compatible = "fsl,imx6ul-evk-wm8960","fsl,imx-audio-wm8960";
fsl表示厂商,“imx6ul-evk-wm8960
” 和 “imx-audio-wm8960
“表示驱动模块名字。 该设备在linux
内核先查找第一个兼容值"imx6ul-evk-wm8960
”,找不到再找第二兼容值"imx-audio-wm8960
”
一般驱动程序文件.c
都会有一个 OF
匹配表,此 OF
匹配表保存着一些 compatible
值,如果设备节点的 compatible
属性值和 OF
匹配表中的任何一个值相等,那么就表示设备可以使用这个驱动,
demo
static const struct of_device_id imx_wm8960_dt_ids[] =
{
{
.compatible = "fsl,imx-audio-wm8960", } ,
{
.compatible = "fsl,imx6ul-evk-wm8960", } ,
};
如果在设备树中有哪个节点的 compatible 属性值与此相等,那么这个节点就会使用此驱动.c文件
“model”
属性只是简单的表示型号,root
节点用其来传递值给machine_desc_str
属性值也是一个字符串,一般 model 属性描述设备模块信息,比如名字什么的。
model = "wm8960-audio";
5.2、属性标签
5.3、寻址属性
如果一个device node
中包含了有寻址需求(要定义reg property
)的sub node
(后文也许会用child node
,和sub node
是一样的意思),那么就必须要定义这两个属性。
#address-cells
defines the number of cells used to encode the address field in a child node’s reg property#size-cells
property defines the number of cells used to encode the size field in a child node’s reg property.
其中“#”
是number
的意思,#address-cells
这个属性是用来描述sub node
中的reg
属性的地址域特性的,也就是说需要用多少个u32
的cell
来描述该地址域。
reg = <address1 length1 [address2 length2] [address3 length3] ... >
在 spi
节点中,#address-cells
设置为 1
,#size-cells
设置为 0
。
5.4、中断
属性 | 含义 |
---|---|
interrupt-controller | a property of the interrupt controller node. It states how many cells are in an interrupt specifier for this interrupt controller (Similar to #address-cells and #size-cells). |
#interrupt-cells | a property of the interrupt controller node. It states how many cells are in an interrupt specifier for this interrupt controller (Similar to #address-cells and #size-cells). |
interrupt-parent | A property of a device node containing a list of interrupt specifiers, one for each interrupt output signal on the device. |
interrupts | A property of a device node containing a list of interrupt specifiers, one for each interrupt output signal on the device. |
具体各个HW block 的interrupt source 是如何物理的连接到interruptcontroller 的呢?在dts 文件中是用interrupt-parent 这个属性来标识的。且慢,这里定义interrupt-parent 属性的是root node ,难道root node 会产生中断到interrupt controller 吗?当然不会,只不过如果一个能够产生中断的device node 没有定义interrupt-parent 的话,其interrupt-parent 属性就是跟随parent node 。因此,与其在所有的下游设备中定义interrupt-parent ,不如统一在root node 中定义了。 | |
intc 是一个lable ,标识了一个device node (在本例中是标识了intc : [email protected] 这个device node )。实际上,interrupt-parent 属性值应该是是一个u32 的整数值(这个整数值在Device Tree 的范围内唯一识别了一个device node ,也就是phandle ),不过,在dts 文件中中,可以使用类似c 语言的Labels and References 机制。定义一个lable ,唯一标识一个node 或者propert y,后续可以使用& 来引用这个lable 。DTC 会将lable 转换成u32 的整数值放入到DTB 中,用户层面就不再关心具体转换的整数值了。 | |
关于interrupt ,我们值得进一步描述。在Device Tree 中,有一个概念叫做interrupt tree ,也就是说interrupt 也是一个树状结构。我们以下图为例(该图来自Power_ePAPR_APPROVED_v1.1 ): | |
5.5、节点状态
可以使用okay
和disabled
来打开和注掉某一个驱动的设备注册。
设备状态有关的, status 属性值也是 字符串 ,字符串是设备的状态信息
值 | 描述 |
---|---|
“okay” | 设备是可操作 |
“disable” | 设备当前是不可操作 |
“fail” | 备不可操作,设备检测到了一系列的错误,而且设备也不大可能变得可操作 |
“fail-sss” | 含义和“fail”相同 |
边栏推荐
猜你喜欢
解决移动端有纵向滚动条但是不能滚动的问题
2022年 SQL 优化大全总结详解
Windows安装MySQL(MIS)
Nanny level explains Transformer
面试介绍项目经验(转)
《剑指Offer》刷题之打印从1到最大的n位数
【第1天】SQL快速入门-基础查询(SQL 小虚竹)
【图像去雾】基于matlab暗通道和非均值滤波图像去雾【含Matlab源码 2011期】
AI mid-stage sequence labeling task: three data set construction process records
Golang协程goroutine的调度与状态变迁分析
随机推荐
Postman will return to the interface to generate a json file to the local
ArcEngine (six) use the tool tool to realize the zoom in, zoom out and translation of the pull box
ArcEngine(一)加载矢量数据
推荐系统-排序层-特征工程:用户特征、物品特征
ArcEngine (1) Loading vector data
工控机防勒索病毒浅析
面试介绍项目经验(转)
How to choose a reliable and formal training institution for the exam in September?
计算机网络常见面试题总结
酷雷曼上新6大功能,全景营销持续加码
ceph简介
9月考,如何选择靠谱正规的培训机构?
sqlite 日期字段加一天
pyspark @udf loop using variable problem
ArcEngine(六)用tool工具实现拉框放大缩小和平移
Daily practice of PMP | Do not get lost in the exam-8.2 (including agility + multiple choice)
依赖注入(DI),自动配置,集合注入
用云机器/虚拟机架设方舟游戏?
postman将接口返回结果生成csv文件到本地
HCIP笔记整理 2022/7/18