为什么会有设备树:
在linux2.6之前,Linux采用硬编码的方式,把支持的厂商的测试板的信息全部写在内核中。来实现Linux的兼容,这使得内核硬件信息的代码占比越来越大。而对用户来说我只要我的板子的硬件信息。这就导致有很多的代码的冗余
我们引入设备树之后,用户可以根据自己的板子,去填写和修改设备硬件信息,做到硬件信息和驱动的分离。
我驱动过程中,我们的设备树文件,会被挂载到u_boot的一个内存区域,比如我们之前系统移植的过程中。我们把U-Image 放到41000000
把exynos4412-fs4412.dtb 放到了420000000的位置,这样内核在运行的时候就可以去读取设备树二进制文件中的数据。
根据,我驱动要的设备信息进行匹配,根据设备节点和属性等信息进行匹配。
设备树文件,是以树形结构编写设备,有根节点,下面有节点设备,节点设备下面又有子设备,子设备下面还一子子设备…
比如,我电脑,是一个设备,那么我电脑里面所有的设备组成的设备,那么我电脑设备就是一个根设备/dev 那我电脑里面有网卡上面的,那我网卡组成一个设备节点/dev/网卡 网卡里面有分很多设备 什么dm9000。。。。。
语法格式
/ {
node1 {
a-string-property = "A string";
a-string-list-property = "first string", "second string";
a-byte-data-property = [0x01 0x23 0x34 0x56];
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 {
};
};
};


双引号:文本字符串
尖括号:32位无符号位整数
不同数据类型:用逗号,连接
——————————————————————————————————————————————
常见的属性:
1、compatible:兼容的,可用的
指定了系统的名称,是一个字符串的列表,实际在代码中可以用于进行匹配,当前你选择的是
哪个机器,它包含了一个“<制造商>,<型号>”形式的字符串。重要的是要指定一个确切的设备,
并且包括制造商的名子,以避免命名空间冲突,
不要使用带通配符的 compatible 值,比如“fsl,mpc83xx-uart”或类似情况
/ {
compatible = “acme,coyotes-revenge”;
};
通常compatible 是 的第一个字符串为,设备名称 第二个参数为型号
compatible:有时会用于做匹配,比如在我们的i2c子系统下面,DRV与适配层匹配就是用的compatible。
2、#address-cells
#size-cells
这表示我们的address 地址的字段长度
和 size length 的字段长度
eg:
external-bus {
#address-cells = <2>
#size-cells = <1>;
ethernet@0,0 {
compatible = "smc,smc91c111";
reg = <0 0 0x1000>; // 地址站两个cells, 长度站1个cells
nterrupts = < 5 2 >;
};
}
3、reg 地址信息
reg的组织形式为reg = <address1 length1 [address2 length2] [address3 length3] … >
其中的每一组address length表明了设备使用的一个地址范围 其字段长度由 cell决定
5、中断信息
interrupt-controller:一个空的属性定义该节点作为一个接收中断信号的设备
表示,我这个设备有中断。
#interrupt-cells:这是一个中断控制器节点的属性。它声明了该中断控制器的
中断指示符中 cell 的个数(类似于 #address-cells 和 #size-cells)
interrupt-parent:一个设备节点的属性,包含一个指向该设备连接的中断控制
器的 phandle(指向或者可以引用&)那些没有 interrupt-parent 的节点则从它们
的 父节点中继承该属性。
interrupts - 一个设备节点属性,包含一个中断指示符的列表,对应于该设备上的每个
中断输出信号
EG:
interrupt-paren = <&gpx1>; 表示继承gpx1的中断信息
interrupts = <1 2>; 1表示该设备是gpx1_1的中断 2表示触发方式
——————————————————————————————————————————————————————
我们在设备树上填写了信息之后(还可以写自己的自定义信息);
那我们的这驱动过程中怎么去拿到这些信息呢?
我们编写设备树的目的就是通过设备树来实现,信息传递到驱动中。
那么:我们要怎么才能在驱动程序中调用到我们想要的我们写的设备树信息呢?
我们利用文件接口 :of :Open Firmware

通过of获取设备信息:
1、获取节点
of_find_node_by_path;
of_find_node_by_name;
of_find_node_by_cpuid;
of_find_node_by_phandle
of_find_node_by_type;
可以通过以上接口获取到节点信息,最常用的还是通过path 路径
2、获取属性 property
of_find_property(parameter 1;parameter 2,parameter 3)
parameter 1:找到的节点结构体指针
parameter 2:要找的属性名称 :/“compaible”…
parameter 3:属性长度:一般我们也不知道,拿到的数据类型或者是数据大小,所以用NULL
我们需要用一个property 结构体来保存我们的数据,of里面已经有了,直接实例化一个
3、获取属性中特殊的数据。
3.1:获取整数数组:
of_property_read_u32_array(const struct device_node * np, const char * propname, u32 * out_values, size_t sz)
parameter 1:设备节点指针
parameter 2:要找的属性名称 :“reg”…
parameter 3:数据放的地方
parameter 4:数据个数 里面有多少个值就写多少个

3.2获取属性里面的字符串数组
of_property_read_string(struct device_node * np, const char * propname, const char * * out_string)

设备树在Linux系统中用于解决内核硬件信息的代码冗余问题,实现了硬件信息和驱动的分离。本文介绍了设备树的基本概念、组织结构、常见属性如compatible、#address-cells、#size-cells、reg、中断信息等,并讲解了如何在驱动程序中通过Open Firmware接口获取设备树信息。
630

被折叠的 条评论
为什么被折叠?



