编写设备树DTS

第一步就是要为这个模型机构建一个基本结构,这是一个有效的设备树最基本的结构。在这个阶段你需要唯一的标识该机器。

/{

  compatible= " Marvell ,armada38x"

};compatible 指定了系统的名称。它包含了一个“<制造商>,<型号>”形式的字符串。重要的是要指定一个确切的设备,并且包括制造商的名子,以避免命名空间冲突。由于操作系统会使用 compatible 的值来决定如何在机器上运行,所以正确的设置这个属性变得非常重要。



接下来就应该描述每个 CPU 了。先添加一个名为“cpus”的容器节点,然后为每个 CPU 分别添加子节点。具体到我们的情况是一个 ARM 的 双核 Cortex A9 系统

/{

  compatible= " Marvell ,armada38x";

  cpus{

     [email protected]{

          compatible = "arm,cortex-a9";

        };

       [email protected]{

          compatible = "arm,cortex-a9";

        };

      };

};每个 cpu 节点的 compatible 属性是一个“<制造商>,<型号>”形式的字符串,并指定了确切的 cpu,就像顶层的 compatible 属性一样



节点名称:现在应该花点时间来讨论命名约定了。每个节点必须有一个“<名称>[@<设备地址>]”形式的名字。

  1).名称> 就是一个不超过31位的简单 ascii 字符串。通常,节点的命名应该根据它所体现的是什么样的设备。比如一个 3com 以太网适配器的节点就应该命名为 ethernet,而不应该是 3com509。

  2).如果该节点描述的设备有一个地址的话就还应该加上设备地址(unit-address)。通常,设备地址就是用来访问该设备的主地址,并且该地址也在节点的 reg 属性中列出

  3).同级节点命名必须是唯一的,但只要地址不同,多个节点也可以使用一样的通用名称(例如 [email protected] 和 [email protected])

 

设备:系统中每个设备都表示为一个设备树节点。所以接下来就应该为这个设备树填充设备节点。现在,知道我们讨论如何进行寻址和中断请求如何处理之前这些新节点将一直为空。 

/ {
    compatible = "acme,coyotes-revenge";

cpus {
        [email protected] {
            compatible = "arm,cortex-a9";
        };
        [email protected] {
            compatible = "arm,cortex-a9";
        };
    };

[email protected] {
        compatible = "arm,pl011";
    };

[email protected] {
        compatible = "arm,pl011";
    };

[email protected] {
        compatible = "arm,pl061";
    };

[email protected] {
        compatible = "arm,pl190";
    };

[email protected] {
        compatible = "arm,pl022";
    };

external-bus {
        [email protected],0 {
            compatible = "smc,smc91c111";
        };

[email protected],0 {
            compatible = "acme,a1234-i2c-bus";
            [email protected] {
                compatible = "maxim,ds1338";
            };
        };

[email protected],0 {
            compatible = "samsung,k8f1315ebm", "cfi-flash";
        };
    };
};在此树中,已经为系统中的每个设备添加了节点,而且这个·层次结构也反映了设备与系统的连接方式。例如,外部总线上的设备就是外部总线节点的子节点,i2c 设备就是 i2c 总线节点的子节点。通常,这个层次结构表现的是 CPU 视角的系统视图。现在这棵树还是无效的,因为它缺少关于设备之间互联的信息。稍后将添加这些信息。

在这颗树中,应该注意这些事情:

              每个设备节点都拥有一个 compatible 属性,

              闪存(flash)节点的 compatible 属性由两个字符串构成。欲知为何,请阅读下一节

 

理解 compatible 属性:

             1).树中每个表示一个设备的节点都需要一个 compatible 属性。compatible 属性是操作系统用来决定使用哪个设备驱动来绑定到一个设备上的关键因素。

             2).compatible 是一个字符串列表,之中第一个字符串指定了这个节点所表示的确切的设备,该字符串的格式为:"<制造商>,<型号>"。剩下的字符串的则表示其它与之相兼容的设备。

                   3).Freescale MPC8349 片上系统(SoC)拥有一个实现了美国国家半导体 ns16550 的寄存器接口的串行设备,那么 MPC8349 的串行设备的 compatible 属性就应该是:compatible = "fsl,mpc8349-uart", "ns16550"。在这里,mpc8349-uart 指定了确切的设备,而 ns16550 则说明这是与美国国家半导体 ns16550 UART 的寄存器级兼容

             4).不要使用带通配符的 compatible 值,比如“fsl,mpc83xx-uart”或类似情况。芯片提供商无不会做出一些能够轻易打破你通配符猜想的变化,这时候在修改已经为时已晚了。相反,应该选择一个特定的芯片然后是所有后续芯片都与之兼容。

如何编址:

1>可编址设备使用以下属性将地址信息编码进设备树

       ■ reg

      ■ #address-cells
       ■ #size-cells

    2>每个可编址设备都有一个元组列表的 reg,元组的形式为:reg = <地址1 长度1 [地址2 长度2] [地址3 长度3] ... >。每个元组都表示一个该设备使用的地址范围。每个地址值是一个或多个 32 位整型数列表,称为 cell。同样,长度值也可以是一个 cell 列表或者为空。

    3>由于地址和长度字段都是可变大小的变量,那么父节点的 #address-cells 和 #size-cells 属性就用来声明各个字段的 cell 的数量。换句话说,正确解释一个 reg 属性需要用到父节点的 #address-cells 和 #size-cells 的值。要知道这一切是如何运作的,我们将给模型机添加编址属性,就从 CPU 开始。

      CPU 编址:

            

CPU 节点表示了一个关于编址的最简单的例子。每个 CPU 都分配了一个唯一的 ID,并且没有 CPU id 相关的大小信息。
    cpus {
        #address-cells = <1>;
        #size-cells = <0>;
        [email protected] {
            compatible = "arm,cortex-a9";
            reg = <0>;
        };
        [email protected] {
            compatible = "arm,cortex-a9";
            reg = <1>;
        };
    };在 cpu 节点中,#address-cells 设置为 1,#size-cells 设置为 0。这意味着子节点的 reg 值是一个单一的 uint32,这是一个不包含大小字段的地址,为这两个 cpu 分配的地址是 0 和 1。cpu 节点的 #size-cells 为 0 是因为只为每个 cpu 分配一个单独的地址。你可能还会注意到 reg 的值和节点名字是相同的。按照惯例,如果一个节点有 reg 属性,那么该节点的名字就必须包含设备地址,这个设备地址就是 reg 属性里第一个地址值

    内存映射设备:   

与 cpu 节点里单一地址值不同,应该分配给内存映射设备一个地址范围。#size-cells 声明每个子节点的 reg 元组中长度字段的大小。在接下来的例子中,每个地址值是 1 cell(32 位),每个长度值也是 1 cell,这是典型的 32 位系统。64 位的机器则可以使用值为 2 的 #address-cells 和 #size-cells 来获得在设备树中的 64 位编址。
/ {
    #address-cells = <1>;
    #size-cells = <1>;

...

[email protected] {
        compatible = "arm,pl011";
        reg = <0x101f0000 0x1000 >;
    };

[email protected] {
        compatible = "arm,pl011";
        reg = <0x101f2000 0x1000 >;
    };

[email protected] {
        compatible = "arm,pl061";
        reg = <0x101f3000 0x1000
               0x101f4000 0x0010>;
    };

[email protected] {
        compatible = "arm,pl190";
        reg = <0x10140000 0x1000 >;
    };

[email protected] {
        compatible = "arm,pl022";
        reg = <0x10115000 0x1000 >;
    };

...
};每个设备都被分配了一个基址以及该区域的大小。这个例子中为 GPIO 分配了两个地址范围:0x101f3000...0x101f3fff 和 0x101f4000..0x101f400f。

一些挂在总线上的设备有不同的编址方案。例如一个带独立片选线的设备也可以连接至外部总线。由于父节点会为其子节点定义地址域,所以可以选择不同的地址映射来最恰当的描述该系统。下面的代码展示了设备连接至外部总线并将其片选号编码进地址的地址分配

external-bus {
        #address-cells = <2>
        #size-cells = <1>;

[email protected],0 {
            compatible = "smc,smc91c111";
            reg = <0 0 0x1000>;
        };

[email protected],0 {
            compatible = "acme,a1234-i2c-bus";
            reg = <1 0 0x1000>;
            [email protected] {
                compatible = "maxim,ds1338";
            };
        };

[email protected],0 {
            compatible = "samsung,k8f1315ebm", "cfi-flash";
            reg = <2 0 0x4000000>;
        };
    };外部总线的地址值使用了两个 cell,一个用于片选号;另一个则用于片选基址的偏移量。而长度字段则还是单个 cell,这是因为只有地址的偏移部分才需要一个范围量。所以,在这个例子中,每个 reg 项都有三个 cell:片选号、偏移量和长度。

由于地址域是包含于一个节点及其子节点的,所以父节点可以自由的定义任何对于该总线来说有意义的编址方案。那些在直接父节点和子节点以外的节点通常不关心本地地址域,而地址应该从一个域映射到另一个域

chosen 节点:

chosen 节点并不代表一个真正的设备,只是作为一个为固件和操作系统之间传递数据的地方,比如引导参数。chosen 节点里的数据也不代表硬件。通常,chosen 节点在 .dts 源文件中为空,并在启动时填充。

chosen {
        bootargs = "root=/dev/nfs rw nfsroot=192.168.1.1 console=ttyS0,115200";
    };

 ...................

.................... 

时间: 2024-10-11 01:43:21

编写设备树DTS的相关文章

设备树DTS使用

参考:<设备树DTS使用总结 - 基于MT76X8> .<linux内核设备树及编译> 一.Linux设备树的起源 在Linux 2.6中,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥着大量的垃圾代码,相当多数的代码只是在描述板级细节,而这些板级细节对于内核来讲,不过是垃圾,如板上的platform设备.resource.i2c_board_info.spi_board_info以及各种硬件platform_data. 在Linux3.x版本后,ar

从零开始写设备树DTS【转】

转自:https://blog.csdn.net/woshidahuaidan2011/article/details/52948732 7.从零开始写设备树 设备树就是有一些属性和节点组成的一种数据结构,属性一般会赋予一些属性值,而节点则可能是是由属性跟其下的子节点构成.下面是一个简单的例子: /dts-v1/; / { node1 { a-string-property = "A string"; a-string-list-property = "first strin

Linux设备树(2)——设备树格式和使用

一.设备树dts文件的语法规范 1. DTS文件布局(layout) /dts-v1/; [memory reservations] // 格式为: /memreserve/ <address> <length>; / { [property definitions] [child nodes] }; (1) 特殊的.默认的属性 a. 根节点的: #address-cells // 在它的子节点的reg属性中, 使用多少个u32整数来描述地址(address) #size-cell

基于设备树的led驱动程序

1 #include <linux/module.h> 2 #include <linux/kernel.h> 3 #include <linux/fs.h> 4 #include <linux/init.h> 5 #include <linux/delay.h> 6 #include <asm/io.h> 7 #include <linux/cdev.h> 8 #include <linux/device.h>

Linux 获取设备树源文件(DTS)里描述的资源【转】

转自:http://www.linuxidc.com/Linux/2013-07/86839.htm 转自:http://blog.sina.com.cn/s/blog_636a55070101mced.html 在linux使用platform_driver_register() 注册  platform_driver 时, 需要在 platform_driver 的probe() 里面知道设备的中断号, 内存地址等资源. 这些资源的描述信息存放在 resource 数据结构中, 相同的资源存

设备树的规范(dts)

如何看下面这张图: 1)从根节点开始看起,即 / 2)在根节点中有属性以及设备节点名称 3)属性的格式有两种形式,当property-name = value时,value的取值有三种形式 4)设备节点(child nodes)的格式 总结: (1) 语法:Devicetree node格式:[label:] node-name[@unit-address] { [properties definitions] [child nodes]}; Property格式1:[label:] prope

Linux设备树语法详解

Linux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离.在设备树出现以前,所有关于设备的具体信息都要写在驱动里,一旦外围设备变化,驱动代码就要重写.引入了设备树之后,驱动代码只负责处理驱动的逻辑,而关于设备的具体信息存放到设备树文件中,这样,如果只是硬件接口信息的变化而没有驱动逻辑的变化,驱动开发者只需要修改设备树文件信息,不需要改写驱动代码.比如在ARM Linux内,一个.dts(device tree source)文件对应一个ARM的machine,一般放置在内核的

Linux设备树语法详解【转】

本文转载自:http://www.cnblogs.com/xiaojiang1025/p/6131381.html 概念 Linux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离.在设备树出现以前,所有关于设备的具体信息都要写在驱动里,一旦外围设备变化,驱动代码就要重写.引入了设备树之后,驱动代码只负责处理驱动的逻辑,而关于设备的具体信息存放到设备树文件中,这样,如果只是硬件接口信息的变化而没有驱动逻辑的变化,驱动开发者只需要修改设备树文件信息,不需要改写驱动代码.比如在AR

Linux设备树使用(二)

一.设备树与驱动的匹配1.设备树会被/scripts中的dtc可执行程序编译成二进制.dtb文件,之前设备树中的节点信息会以单链表的形式存储在这个.dtb文件中:驱动与设备树中compatible属性匹配上后, 驱动中的相应的node节点就映射在这个设备树节点上了,然后以这个node为参数调用of函数来解析这个设备树块上的信息为驱动所用.设备树中的信息是逐条进行获取的(?) 2.例如设备树中有如下定义: flash_SY7803:flashlight { compatible = "qcom,l