zoukankan      html  css  js  c++  java
  • 设备树语法

    [DTS]设备树语法

    原创: 杨永达 嵌入式软件开发交流 3月15日

    前言

            之前分享了一些设备树的基本概念,今天来聊聊设备树的语法。以前阅读设备树文件时发现很多平台的节点的属性名称都不一样,然后就很纠结,就到官方去找,发现都没有该属性或节点,就很郁闷。这其实犯了一个错误,那就是设备树并不是一种编程语言,没有什么绝对的关键字。我们应该把设备树理解成配置文件,如果知道xml文件,就可以把设备树类比成xml文件。

            好,废话不多说了。。。

    语法规则

    一、设备树语法

        (1)设备树节点语法

    [label:] node-name[@unit-address] {    [properties definitions];    [child nodes];};

    解释:

        label: 可选项,节点别名

        node-name: 节点名

        unit-address: 设备地址

        properties definitions:属性定义

        child nodes:子节点

    (2) 属性定义语法

    [label:] property-name = value;[label:] property-name;

    属性分为有属性值和无属性值

    属性值有三种取值:

    • arrays of cells(1个或多个32位数据, 64位数据使用2个32位数据表示),用尖括号表示(< >)

    • string(字符串), 用双引号表示(" ")

    • bytestring(1个或多个字节),用方括号表示([ ])

    举例:

    //Arrays of cells : cell就是一个32位的数据interrupts = <17 0xc>;
    //64bit数据使用2个cell来表示:clock-frequency = <0x00000001 0x00000000>;
    //A null-terminated string (有结束符的字符串):compatible = "simple-bus";
    //A bytestring(字节序列) :local-mac-address = [00 00 12 34 56 78]; // 每个byte使用2个16进制数来表示local-mac-address = [000012345678]; // 每个byte使用2个16进制数来表示
    //可以是各种值的组合, 用逗号隔开:compatible = "ns16550", "ns8250";example = <0xf00f0000 19>, "a strange property format";

    二、特殊属性

        (1)根节点

    #address-cells   // 在子节点的reg属性中, 使用多少个u32整数来描述地址(address)

    #size-cells      // 在子节点的reg属性中, 使用多少个u32整数来描述大小(size)

    compatible // 定义一系列的字符串, 用来指定内核中哪个machine_desc可以支持本设备                 // 即这个板子兼容哪些平台

    model            // 比如有2款板子配置基本一致, 它们的compatible是一样的 // 那么就通过model来分辨这2款板子

    * cell: 一个u32整数

    (2) /memory

    所有设备树文件的必需节点,它定义了系统物理内存的 layout

    device_type = "memory";reg             // 用来指定内存的地址、大小

    (3) /chosen

    传递runtime parameter

    bootargs        // 内核command line参数, 跟u-boot中设置的bootargs作用一样

    (4) /cpus

    /cpus节点下有1个或多个cpu子节点, cpu子节点中用reg属性用来标明自己是哪一个cpu

    所以 /cpus 中有以下2个属性:

    #address-cells   // 在它的子节点的reg属性中, 使用多少个u32整数来描述地址(address)

    #size-cells // 在它的子节点的reg属性中, 使用多少个u32整数来描述大小(size) // 必须设置为0

    (5) aliases

    用来定义别名

    aliases {    ethernet0 = &gmac;    i2c0 = &i2c0;    i2c1 = &i2c1;    i2c2 = &i2c2;    mshc0 = &emmc;    mshc1 = &sdmmc;    mshc2 = &sdio0;    mshc3 = &sdio1;    serial0 = &uart0;    serial1 = &uart1;    spi0 = &spi0;    spi1 = &spi1;  };

    三、引用其他节点

        (1) phandle属性引用

        节点中的phandle属性, 它的取值必须是唯一的(不要跟其他的phandle值一样)

    pic@10000000 {    phandle = <1>;    interrupt-controller;};
    another-device-node { interrupt-parent = <1>; // 使用phandle值为1来引用上述节点};

    (2)使用别名(本质还是phandle)

    PIC: pic@10000000 {    interrupt-controller;};
    another-device-node {    interrupt-parent = <&PIC>;   // 使用label来引用上述节点                       };

    四、包含dtsi文件

    #include "rk3288-firefly.dtsi"

        在每个.dsti和.dts中都会存在一个“/”根节点,那么如果在一个设备树文件中include一个.dtsi文件,那么岂不是存在多个“/”根节点了么。其实不然,编译器DTC在对.dts进行编译生成dtb时,会对node进行合并操作,最终生成的dtb只有一个root node。

    五、使用宏定义

    #include <dt-bindings/gpio/gpio.h>#include <dt-bindings/interrupt-controller/irq.h>#include <dt-bindings/interrupt-controller/arm-gic.h>#include <dt-bindings/pinctrl/rockchip.h>#include <dt-bindings/clock/rk3288-cru.h>#include <dt-bindings/power/rk3288-power.h>#include <dt-bindings/thermal/thermal.h>#include <dt-bindings/power/rk3288-power.h>#include <dt-bindings/soc/rockchip,boot-mode.h>
    arm-pmu { compatible = "arm,cortex-a12-pmu"; interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>; interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; };

    上面的GIC_SPI和IRQ_TYPE_LEVEL_HIGH都是宏定义,定义在头文件中。

    六、属性重写

    //rk3288.dtsihdmi: hdmi@ff980000 {    compatible = "rockchip,rk3288-dw-hdmi";    reg = <0x0 0xff980000 0x0 0x20000>;    reg-io-width = <4>;    #sound-dai-cells = <0>;    rockchip,grf = <&grf>;    interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;    clocks = <&cru  PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_HDCP>, <&cru SCLK_HDMI_CEC>;    clock-names = "iahb", "isfr", "cec";    power-domains = <&power RK3288_PD_VIO>;    status = "disabled";};
    //rk3288-firefly.dtsi&hdmi { ddc-i2c-bus = <&i2c5>; status = "okay";};

    上面的rk3288-firefly.dtsi包含rk3288.dtsi, 然后使用&hdmi引用rk3288.dtsi中的hdmi节点。并在原有的基础上添加ddc-i2c-bus属性,然后将status属性进行重写覆盖。这就体现了dtsi文件的价值,dtsi定义公共的部分,板级差异再进行添加或重写。

        还是提醒大家,设备树不能当成一种编程语言来学哦!否则你有时候会很纠结。

    精彩还在继续,欢迎继续关注!!!!

    欢迎加入QQ群聊

    如果你喜欢就请分享给你的朋友,感谢大家的支持

  • 相关阅读:
    Objective-C 生成器模式 -- 简单实用和说明
    Objective-C 桥接模式 -- 简单实用和说明
    Objective-C 工厂模式(下) -- 抽象工厂模式
    Objective-C 工厂模式(上) -- 简单工厂模式
    Linux篇---Vi的使用
    【Spark篇】---SparkSQL中自定义UDF和UDAF,开窗函数的应用
    【Spark篇】---SparkStreaming算子操作transform和updateStateByKey
    【Spark篇】---SparkStream初始与应用
    【Spark篇】---SparkSQL on Hive的配置和使用
    【Spark篇】---Spark中Shuffle机制,SparkShuffle和SortShuffle
  • 原文地址:https://www.cnblogs.com/idyllcheung/p/11183757.html
Copyright © 2011-2022 走看看