• 设备树基础


    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  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文件中直接调取初始化列表的方式是非常不一样的。

  • 相关阅读:
    2010.10.10 第九课 函数(二)(递归)(汉诺塔)
    2020.10.8第八课函数(一)(4种函数)
    2020.9.29 第七课 字符串函数与字符数组
    2020.9.26第六节课数组
    2020.9.22 第四课 运算符表达式和语句
    2020.9.19 第三课 字符串格式化输出与输入
    2020.9.17 第二课 C语言中数据类型 2,8,10进制转换 计算机内存数值存储方式(补码转换)
    2020.9.15 第一课,概念
    spring架构解析--入门(一)
    JAVA对象实例化方式总结
  • 原文地址:https://www.cnblogs.com/chencanjian/p/5984007.html
Copyright © 2020-2023  润新知