设备树(Device Tree)的结构和语法

详细介绍了设备树(Device Tree)的结构和语法,包括节点的组织方式、属性的类型以及如何使用这些结构和属性来描述硬件设备。以下是对这些知识点的详细分析和介绍,以及相应的代码注释。

 DTS结构

设备树的基本单元是节点(node),这些节点被组织成树状结构。每个节点代表一个设备或总线,并包含描述该节点的属性(properties)。以下是设备树结构的关键要素:

  • 根节点:设备树的根节点使用/表示,它没有父节点。
  • 子节点:根节点和其它节点可以包含子节点,形成层次结构。
  • 属性:节点中的属性用于描述节点的特性,如设备类型、内存地址、中断号等。
代码示例和注释:
/dts-v1/;  // 指定设备树的版本

/ {  // 根节点开始
    node1 {  // 定义一个节点node1
        a-string-property = "A string";  // 定义一个字符串类型的属性
        a-string-list-property = "first string", "second string";  // 定义一个字符串列表属性
        a-byte-data-property = [01 23 34 56];  // 定义一个字节数据属性,常用于存储二进制数据
        child-node1 {  // node1的子节点
            first-child-property;  // 子节点的属性,可以不赋值
            second-child-property = <1>;  // 定义一个单元属性,使用尖括号表示
            a-string-property = "Hello, world";  // 另一个字符串属性
        };
        child-node2 {  // node1的另一个子节点,可以为空
        };
    };
    node2 {  // 定义另一个节点node2
        an-empty-property;  // 一个空属性,表示存在但不赋值
        a-cell-property = <1 2 3 4>;  // 定义一个单元属性列表,每个数字是32位无符号整数
        child-node1 {  // node2的子节点
            // 子节点可以包含更多的属性和子节点
        };
    };
};  // 根节点结束

 DTS语法介绍

DTS语法定义了如何在源文件中表示设备树的结构。以下是DTS语法的关键要素:

  • 节点定义:使用花括号{}定义节点,节点名称可以包含@和单元地址。
  • 属性定义:在节点内部定义属性,属性值可以是字符串、单元列表或其他数据类型。
  • 注释:使用//进行单行注释。
代码示例和注释:
/* 定义一个节点,可能代表一个具体的硬件设备或总线 */
node-name@unit-address {
    /* 定义一个标签,方便在DTS文件中引用 */
    [label:] node-name[@unit-address] {
        /* 属性定义 */
        [properties definitions]
        /* 子节点定义 */
        [child nodes]
    }
};

/* 基本数据类型示例 */
- 文本字符串:以双引号括起来的字符串,如 "a string"。
- 单元(cells):32位无符号整数,以尖括号括起来,如 <0xbeef 123 0xabcd1234>。
- 二进制数据:以方括号括起来的字节序列,如 [0x01 0x23 0x45 0x67]。

/* 属性可以包含多种类型的数据 */
mixed-property = "a string", [0x01 0x23 0x45 0x67], <0x12345678>;

/* 属性列表,由多个字符串组成 */
string-list = "red fish", "blue fish";

dts的组成

        标准属性
        compatible

compatible属性用于指定设备的兼容性字符串,内核通过这些字符串来确定使用哪个驱动程序。

/ {
    compatible = "manufacturer,model", "generic,type";  // 定义设备兼容的字符串
};
         #address-cells和#size-cells

这两个属性定义了在设备树中表示地址和大小所需的单元数(通常是32位或64位)。

soc {
    #address-cells = <1>;  // 地址使用1个单元
    #size-cells = <1>;     // 大小使用1个单元
    /* 其它节点和属性 */
};

        CPU addressing

CPU节点的地址分配通常很简单,每个CPU都有一个唯一的ID。

cpus {
    #address-cells = <1>;  // CPU ID使用1个单元
    #size-cells = <0>;     // CPU没有关联的大小

    cpu@0 {
        compatible = "arm,cortex-a9";
        reg = <0>;  // CPU的ID
    };
    /* 其它CPU节点 */
};
        Memory Mapped Devices

内存映射设备需要同时指定基地址和长度。

/ {
    #address-cells = <1>;
    #size-cells = <1>;
    serial@101f0000 {
        compatible = "arm,pl011";
        reg = <0x101f0000 0x1000>;  // 基地址和长度
    };
    /* 其它内存映射设备 */
};
        Non Memory Mapped Devices

非内存映射设备,如I2C设备,通常只分配一个地址,没有长度。

i2c@1,0 {
    compatible = "acme,a1234-i2c-bus";
    #address-cells = <1>;
    #size-cells = <0>;
    reg = <1 0 0x1000>;  // I2C总线地址
    /* 其它非内存映射设备 */
};
        Ranges (Address Translation)

ranges属性用于地址转换,将子地址空间映射到父地址空间。

external-bus {
    #address-cells = <2>;
    #size-cells = <1>;
    ranges = <0 0 0x10100000 0x10000>;  // 地址转换规则
    /* 子设备 */
};

status属性表示设备的状态,如"okay"表示设备正常工作,"disabled"表示设备被禁用。

device {
    status = "okay";  // 设备状态
};

 中断映射

中断映射定义了设备如何连接到中断控制器,以及如何描述中断。

代码示例和注释:
soc {
    open-pic {
        interrupt-controller;  // 声明一个中断控制器
        #interrupt-cells = <2>;  // 中断控制器需要2个单元来描述一个中断
        /* 中断控制器的其他属性 */
    };
    pci {
        #interrupt-cells = <1>;  // PCI设备的中断使用1个单元描述
        /* PCI设备的其他属性 */
    };
    /* 其他总线或设备的中断映射 */
};

特殊节点

特殊节点,如aliases,用于定义节点的别名,简化对节点的引用。

aliases {
    ethernet0 = &eth0;  // 定义ethernet0的别名为eth0
    serial0 = &serial0;  // 定义serial0的别名为serial0
};

这些知识点构成了设备树的基本语法和结构,允许开发者以一种标准化的方式来描述硬件设备和它们的属性。通过这些描述,Linux内核可以在启动时识别和配置硬件设备。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值