设备树
设备树语法
设备树由节点和属性构成,节点可以包含属性和子节点,树型结构。
属性为 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
设备的状态信息
#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";
};
参考
arm设备树 基础,语法
Linux设备树详解 为什么需要设备树,由浅入深的实例,终于理解设备树为什么可以独立于内核单独编译了
Device Tree(一):背景介绍 (wowotech.net)
Linux设备树特殊节点( aliases、chosen )介绍 bootz->do_bootz()…
Linux 内核:设备树中的特殊节点 黄树超 kernel起来后如果查看device tree的信息
【Linux笔记】设备树基础知识 语法、一些标准属性
linux设备树详解 good