设备树语法

设备树由节点属性构成,节点可以包含属性子节点,树型结构。

属性为 name=value。

其中 value 有多种取值方式:

  • 一个32位的数据,用尖括号包围起来,如
interrupts = <17 0xc>;   
  • 一个64位数据(使用2个32位数据表示),用尖括号包围起来,如:
clock-frequency = <0x00000001 0x00000000>;   
  • 有结束符的字符串,用双引号包围起来,如:
compatible = "simple-bus";   
  • 字节序列,用中括号包围起来,如:
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";   

实例

/dts-v1/;	/* 版本 */
/* 包含的设备树文件 */
#include "sun8i-h3.dtsi"
#include "sunxi-common-regulators.dtsi"

/* 包含的 C 头文件 */
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>

/ {	/* 根节点 */
	/* 根节点的一些属性 */
	model = "Xunlong Orange Pi PC";	
	compatible = "xunlong,orangepi-pc", "allwinner,sun8i-h3";

	/* 子节点 1、2、3 */
	...

	/* 子节点 4 */
	r_gpio_keys {	/* 节点名称(Name) */
        /* 节点属性 */
		compatible = "gpio-keys";

        /* 子节点的子节点 */
		sw4 {
            /* 子节点的子节点的属性 */
			label = "sw4";
			linux,code = <KEY_RESTART>;
			gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>;
		};
	};
};

一些标准属性

compatible

表示"兼容",对于某个 LED,内核中可能有 A、B、C 三个驱动都支持它,那可以这样写:

led {   
	compatible = A, B, C;   
};

内核启动时,就会为这个LED按这样的优先顺序为它找到驱动程序:A、B、C。

model

model 属性与 compatible 属性有些类似,但是有区别,compatile 属性是一个字符串列表,表示你的硬件兼容 A、B、C 等驱动;model 用来准确地定义这个硬件是什么。

status

设备的状态信息

img

#address-cells 和 #size-cells 属性

格式:

#address-cells:address 要用多少个 32 位数来表示;   
#size-cells:size要用多少个 32 位数来表示。 

比如一段内存,怎么描述它的起始地址和大小?下例中,address-cells 为 1,所以reg中用 1 个数来表示地址,即用 0x80000000 来表示地址;size-cells 为 1,所以 reg 中用 1 个数来表示大小,即用 0x20000000 表示大小:

/ {
    #address-cells = <1>;
    #size-cells = <1>;
    memory {
        reg = <0x80000000 0x20000000>;	/* 512 */
    };
};

reg

reg 的本意是 register,用来表示寄存器地址。但是在设备树里,它可以用来描述一段空间。反正对于 ARM 系统,寄存器和内存是统一编址的,即访问寄存器时用某块地址,访问内存时用某块地址,在访问方法上没有区别。

reg 属性的值,是一系列的 “address size”,用多少个 32 位的数来表示 address 和 size,由其父节点的 #address-cells、#size-cells 决定。

示例:

/dts-v1/;
/ {
    #address-cells = <1>;
    #size-cells = <1>;
    memory {
        reg = <0x80000000 0x20000000>;
    };
};

常用节点

根节点

用 / 标识根节点,如:

/dts-v1/;   
/ {   
    model = "SMDK24440";   
    compatible = "samsung,smdk2440";   

    # address-cells = <1>;   
    # size-cells = <1>;   
};   

CPU节点

一般不需要我们设置,在 dtsi 文件中都定义好了,如:

cpus {
    #address-cells = <1>;
    #size-cells = <0>;

    cpu0: cpu@0 {
        .......
    }
};

memory 节点

芯片厂家不可能事先确定你的板子使用多大的内存,所以 memory 节点需要板厂设置,比如:

memory {
	reg = <0x80000000 0x20000000>;
};

chosen 节点

我们可以通过设备树文件给内核传入一些参数,这要在 chosen 节点中设置 bootargs 属性:

chosen {
    bootargs = "noinitrd root=/dev/mtdblock4 rw init=/linuxrc console=ttySAC0,115200";
};

参考

【Linux笔记】设备树基础知识

arm设备树 基础,语法

Linux设备树详解 为什么需要设备树,由浅入深的实例,终于理解设备树为什么可以独立于内核单独编译了

Linux设备树详解(一) 基础知识

Device Tree

Device Tree(一):背景介绍 (wowotech.net)

初识设备树

Linux设备树特殊节点( aliases、chosen )介绍 bootz->do_bootz()…

Linux 内核:设备树中的特殊节点 黄树超 kernel起来后如果查看device tree的信息

在根文件系统中查看设备树(有助于调试)

01-Linux设备树系列-基本语法

【Linux笔记】设备树基础知识 语法、一些标准属性

linux设备树详解 good