1.设备树
设备树(Device Tree)是一种描述硬件的数据结构。
作用:提供设备信息。
时间:在操作系统引导阶段进行设备初始化的时候,数据结构中的硬件信息被检测并传递给操作系统。
设备树源文件(xxxx.dts) DTC编译 设备树二进制文件(xxxx.dtb)
2.设备树基本语法
设备树的基本单元是节点(node),这些node被组织成树状结构,除了root node,每个node都只有一个parent node,一个device tree文件中只能有一个root node。每个node中包含了若干的键值对(property/value)来描述该node的一些特性。每个node用节点名字标识。(类似于linux文件系统)
/{ //根节点
Property = value; //描述信息
<name>[@<unit-address>]{ //子节点
Property = value //描述信息
};
……
};
3.节点名命名规范
节点名字的格式是[@]。如果该node没有reg属性,那么该节点名字中不能包括@unit-address。unit-address的具体格式是和设备挂在哪个bus上相关。例如对于CPU,其unit-address就是从0开始编址,以此加1,而具体的设备,例如以太网控制器,其unit-address就是寄存器地址。根节点的节点名是确定的,必须是“/”。
reg = <0x10001000 0x24 0x20001000 0x24>;
4.节点别名
一个设备可能会使用到别的节点的内容,可以通过节点的别名来引用到其内容。引用的目的可能是合并两个节点的内容、 替换部分内容、或是使用部分内容。
/{ //根节点
demo:demo0@0x48000000{
compatible = “xxx”;
};
……
};
节点名 : demo0@0x48000000
节点路径: /demo0@0x48000000
节点别名: demo
demo == /demo0@80000000
引用方式:
1.&demo{
Reg = <0x10001000 4 0x20001000 4>
……
};
2./{
reference-node{
property = <&demo>;
……
};
};
5.合并节点内容
一个硬件设备的部分信息不会变化,但是另一部分信息是有可能会变化的,就出现了节点内容合并。即:先编写好节点,仅仅描述部分属性值;使用者后加一部分属性值。在同级路径下,节点名相同的“两个”节点实际会自动合并成一个节点。(类似于c++中的命名空间)
6.设备树键值对相关语法
[1]. 字符串信息
compatible = "随风,飘落";
[2]. 32位无符号整形数组
word-array = <32 45 67 89>;
reg = <0x10001000 0x24 0x20001000 0x24>;
[3]. 二进制数组
bi-array = [0c 20 11 24];
mac = [FE 02 11 CB 40 58];
[4]. 字符数组
string-list = "aaa" , "bbb" , "ccc";
7.默认意义的属性
[1]. 设备树语法中已经定义好的,具有通用规范意义的属性如果是设备信息和驱动分离框架的设备节点,则能够在内核初始化找到节点时候,自动解析生成相应的设备信息。
常见属性的有: compatible、地址address、中断interrupt
简单举例:
compatible属性:用于匹配设备节点和设备驱动的属性,规则是驱动设备ID表中的compatible域的值(字符串),和设备树中设备节点中的compatible属性值完全一致。 compatible=“厂商名,设备名” ;
struct platform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
struct device_driver driver;
const struct platform_device_id *id_table;
};
struct device_driver {
const char *name;
struct bus_type *bus;
struct module *owner;
const struct of_device_id *of_match_table;
};
struct of_device_id
{
char compatible[128]; //用来和设备树中的compatible属性进行匹配
};
[2]. ARM Linux内核定义好的,一类设备通用的有默认意义的属性不能被内核自动解析生成相应的设备信息,但是内核已经编写了相应的解析提取函数。
常见属性的有: MAC地址、 GPIO、 clock …
GPIO属性:
gpio-controller:说明该节点描述的是一个gpio控制器
#gpio-cells:描述gpio使用节点的属性一个cell的内容
属性名=<&引用GPIO节点别名 GPIO标号 工作模式>;
eg: gpios = <&gpx0 1 1> ;
补充
描述设备节点相关信息的结构体
struct device_node {
const char *name; //名字
const char *type; //类型
char *full_name; //节点全名
};