设备树基础

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  Warning  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Do not belive this chapter without any doubt, to avoid being hole

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  前方高能  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

请不要绝对相信本文,以免被坑

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  要说三遍  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

重要的事情说3次,请不要绝对相信本文,以免被坑

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

看本文前,请自行打开内核工程的两个文件浏览一遍:

1、 arch/arm/boot/dts 中的随意一个dts文件;

2、 include/linux/of.h

=================================  设备树  ================================

设备树这块,我想说,网上资料基本都是辣鸡,基本都在分析设备树的结构、设备树的内容,但是设备树与内核的关联并没有任何说明,因此总体而言,都是一些没有什么卵用的辣鸡。

所以对于这一块,我也不知道该怎么说才比较好,主要靠的是感觉,你们就信一半试一半吧!

有一篇文章写得非常好,我结合自己的经验,重新编排了一部分,就是下面的文字了。这篇文章网址是:http://blog.csdn.net/21cnbao/article/details/8457546

一、 设备树的文件格式

1、 Dts:板级设备树,编译zImage之后,会自动编译dts文件,生成dtb文件;

2、 Dtsi:设备树模块,可以在其他的dts、dtsi文件中,通过 #include 指令加载;效果类似C++ 的继承,父树有而子树没有的属性合并到子树中,子树中与父树重合的属性会覆盖父树的相应属性;

3、 Dtb:板级设备树输出包,是zImage启动的必要条件之一;

 

二、 设备树的结构(网上基本都是在这一小节上面大做文章,还不完整)

1、 根节点

/ { … };

根节点是一个节点!必须具有根节点!因为所有结构都是从这里开始的!

根节点没有父节点!

2、 Node(节点)和property(属性)

a) 格式

  1. 节点:   node { … };
  2. 属性:   property = … ;

b) 节点可以独立存在,属性必须依赖节点存在;

c) 嵌套:

嵌套是节点间关系,通过嵌套形成树形结构,故称为设备树;

例:

/ {

node1 {

property = “a”;

node3 {

property1 = <1>;

property2;

};

};

node2 {

proprety = <0>;

};

};

3、 标签

标签用于修饰节点,使这个节点能够被“嵌套”到属性中;可以形成跨越树形结构的链接,使完全不同的设备关联起来,如,把设备的管脚配置关联到设备中;

例,将node1赋值给node2的property:

tag: node1 { … };

node2 {

property = <&tag>;

};

4、 命名规则

a) 节点: 设备名@十六进制地址;

b) 属性: 随便;

c) 标签: 设备名+id

5、 赋值

赋值是针对属性的操作,不可以对节点进行赋值。赋值的形式非常多样化,例:

a) 布尔量: property; //有这个属性?or no?

b) 十进制整形值: property = <1234>;

c) 十六进制整型值:property = <0x1234>;

d) 字符串: property = “abcd”;

e) 节点: property = <&tag >;

f) 整形数组: property = <0x1234 1234>;

g) 节点数组: property = <&tag1 &tag2 &tag3>;

h) 结构体: property = <&tag 0x0 123>;

i) 多个字符串: property = ”123”, “456”, “789”;

6、 继承

  1. 源文件:

a) tree1.dtsi:

/ {

node1 {

property1 = 1;

};

};

b) tree2.dtsi:

/ {

node1 {

property2 = 2;

};

 

node2 {

property1 = 1;

};

};

c) tree.dts:

#include “tree1.dtsi”

#include “tree2.dtsi”

/ {

node1 {

property1 = a;

};

};

内核工程make:DTC tree.dts

  1. 等效结果:

/ {

node1 {

property1 = a;

property2 = 2;

};

node2 {

property1 = 1;

};

};

注意node1,tree.dts继承了tree2.dtsi,两者均对node1的proprety1进行了赋值,那么子树tree.dts中的配置将生效,父树中相应的配置失效。

==================================  使用设备树  ===============================

一、 关联简单的驱动程序

1、 compatible和status属性

每个带有compatible属性的节点,都会在linux系统中对应一个设备,不管物理上是否存在这个设备,compatible属性是该节点代表的设备的类型的唯一标识。status控制linux系统是否会创建这个设备,如果为字符串okay,则会创建该设备的匹配关系,若否,则该设备即使存在驱动程序,也不会被匹配。

例:

/ {

test {

compatible = “test”;

status = “okay”;

/* status = “disable”; */

};

};

2、 Driver的compatible属性

static const struct of_device_id test_of_match[] = {

    {

            .compatible = "test",

    },

    { }

};

static struct platform_driver test_driver = {

    .driver = {

        .name = "btn_test",

        .owner = THIS_MODULE,

        .of_match_table = of_match_ptr(test_of_match),

    },

    .probe =    Test_Probe,

    .remove =   Test_Remove,

};

driver的compatible与node的compatible匹配,那么linux就调用driver的probe函数,初始化设备。

二、 在驱动程序中访问设备树

1、 技能需求

我们不需要对设备树的API非常熟悉,因为linux系统已经为我们匹配好了设备树节点,即使需要写全新的驱动程序,也可以参考其他的驱动程序进行仿写。

2、 内核API的of系函数

由于不是太熟练,仅提供函数名,自己体会作用!

a) 与node有关的API:

of_find_node_by_name

of_find_compatible_node

of_get_parent

of_get_next_child

of_get_child_by_name

b) 与property有关的API:

of_find_property

of_get_property

of_property_read_u8

of_property_read_u32

of_property_read_u64

of_property_read_u8_array

of_property_read_u32_array

of_property_read_string

 

三、 设备树中与启动相关的信息

平台信息都放在根节点中,这些信息参与与linux启动,以A5为例:

/{

model = "Atmel SAMA5D36-EK";

compatible = "atmel,sama5d3xmb", "atmel,sama5d3xcm", "atmel,sama5d3", "atmel,sama5";

cpus {

#address-cells = <1>;

#size-cells = <0>;

cpu@0 {

device_type = "cpu";

compatible = "arm,cortex-a5";

reg = <0x0>;

};

};

memory {

reg = <0x20000000 0x8000000>;

};

clocks {

};

};

其中compatible、cpu、memory中的错误,尤其是经常改动的memory,都会导致内核启动死掉。

四、 设备树的影响范围

这是值得注意的一点,设备树只是一个数据结构,保存了设备的地址、配置信息,但事实上并不影响设备本身,操作设备依旧是交给驱动程序去完成,所有驱动程序都需要通过匹配compatible属性方式启动,这一点与过去的board.c文件中直接调取初始化列表的方式是非常不一样的。

原文地址:https://www.cnblogs.com/chencanjian/p/5984007.html