前言:本章介绍.dts与.dtb文件规范
一、dts文件解析
1.1 dts文件布局
/dts-v1/;
[memory reservations] // 格式为: /memreserve/ <address> <length>;
/ {
model = "xxx";
compatible = "xxx";
#address-cells = <x>;
#size-cells = <x>;
[property definitions]
[child nodes]
};
1.2 dts语法格式
从上面文件布局我们能看到大概分为以下几部分,我们依次介绍:
- /dts-v1/;
- [memory reservations]
- / {
model = “xxx”;
compatible = “xxx”;
#address-cells = ;
#size-cells = ;
[property definitions]
[child nodes]
};
(1)
/dts-v1/; 表示dts文件的版本
(2)
[memory reservations] // 格式为: /memreserve/ <address> <length>;表示留给自己使用的内存。即内核不能使用这部分内存空间,地址与大小在dtb中都是使用64位的数表示。
(3)
/ {
model = "xxx";
compatible = "xxx";
#address-cells = <x>;
#size-cells = <x>;
[property definitions]
[child nodes]
};
/ 根,设备树的起点,根节点中包含一般的属性及特殊的属性以及子节点。
1.我们先介绍特殊的属性
#address-cells // 在它的子节点的reg属性中, 使用多少个u32整数来描述地址(address)
#size-cells // 在它的子节点的reg属性中, 使用多少个u32整数来描述大小(size)
compatible // 定义一系列的字符串, 用来指定内核中哪个machine_desc可以支持本设备
// 即这个板子兼容哪些平台
// uImage : smdk2410 smdk2440 mini2440 ==> machine_desc
model // 咱这个板子是什么
// 比如有2款板子配置基本一致, 它们的compatible是一样的
// 那么就通过model来分辨这2款板子
2.一般的属性
[property definitions]
Property格式1:
[label:] property-name = value;
Property格式2(没有值):
[label:] property-name;
Property取值只有3种:
arrays of cells(1个或多个32位数据, 64位数据使用2个32位数据表示),
string(字符串),
bytestring(1个或多个字节)
示例:
a. Arrays of cells : cell就是一个32位的数据
interrupts = <17 0xc>;
b. 64bit数据使用2个cell来表示:
clock-frequency = <0x00000001 0x00000000>;
c. A null-terminated string (有结束符的字符串):
compatible = "simple-bus";
d. A bytestring(字节序列) :
local-mac-address = [00 00 12 34 56 78]; // 每个byte使用2个16进制数来表示,可以不用加空格
local-mac-address = [000012345678]; // 每个byte使用2个16进制数来表示
e. 可以是各种值的组合, 用逗号隔开:
compatible = "ns16550", "ns8250";
example = <0xf00f0000 19>, "a strange property format";
3.Devicetree node格式:
[label:] node-name[@unit-address] {
[properties definitions]
[child nodes]
};
需要注意俩个部分label与node-name,node-name要保证在同节点下的唯一性,label是一个标签,当别的节点引用的时候会用到它。
后面再介绍引用的内容。
1.3 引用其它节点
比如我们有一个表示中断控制器的节点,然后有一个使用中断的设备,我们使用中断的设备产生中断后要传给中断控制器,所以就需要引用中断控制器的节点,怎么引用呢?有两种办法,如下:
第一种:
使用phandle应用 : // 节点中的phandle属性, 它的取值必须是唯一的,如果别的节点中有该属性,要确保所有的phandle都不一样。
pic@10000000 {
phandle = <1>;
interrupt-controller;
};
another-device-node {
interrupt-parent = <1>; 这里指定 interrupt-parent为<1>,就是将中断指向了中断控制器节点中的phandle属性。
};
第二种:
. label:
PIC: pic@10000000 {
interrupt-controller;
};
another-device-node {
interrupt-parent = <&PIC>; // 使用label来引用上述节点,
// 使用lable时实际上也是使用phandle来引用,
// 在编译dts文件为dtb文件时, 编译器dtc会在dtb中插入phandle属性
};
1.4 dtsi文件
这里再介绍一下dtsi文件,该文件是将一类的设备共有的资源打包到一个文件中,当我们写一个自己的开发板的设备树时,只需要include “”xxx.dtsi“”就能包含该文件。dts中的节点可以对dtsi中的节点进行重写。
二、dtb文件解析
dtc会把dts文件编译成dtb文件
这里我们举个例子来学习DTB文件,先给出dts文件内容:
#define S3C2410_GPA(_nr) ((0<<16) + (_nr))
#define S3C2410_GPB(_nr) ((1<<16) + (_nr))
#define S3C2410_GPC(_nr) ((2<<16) + (_nr))
#define S3C2410_GPD(_nr) ((3<<16) + (_nr))
#define S3C2410_GPE(_nr) ((4<<16) + (_nr))
#define S3C2410_GPF(_nr) ((5<<16) + (_nr))
#define S3C2410_GPG(_nr) ((6<<16) + (_nr))
#define S3C2410_GPH(_nr) ((7<<16) + (_nr))
#define S3C2410_GPJ(_nr) ((8<<16) + (_nr))
#define S3C2410_GPK(_nr) ((9<<16) + (_nr))
#define S3C2410_GPL(_nr) ((10<<16) + (_nr))
#define S3C2410_GPM(_nr) ((11<<16) + (_nr))
/dts-v1/;
/memreserve/ 0x33f00000 0x100000;
/ {
model = "SMDK24440";
compatible = "samsung,smdk2440";
#address-cells = <1>;
#size-cells = <1>;
memory { /* /memory */
device_type = "memory";
reg = <0x30000000 0x4000000 0 4096>;
};
/*
cpus {
cpu {
compatible = "arm,arm926ej-s";
};
};
*/
chosen {
bootargs = "noinitrd root=/dev/mtdblock4 rw init=/linuxrc console=ttySAC0,115200";
};
led {
compatible = "jz2440_led";
pin = <S3C2410_GPF(5)>;
};
};
将上述文件编译成dtb文件,查看dtb文件,如下是学习的dts文件与dtb文件对应关系: