设备树学习(二)(设备树的规范)

it2023-04-01  71

前言:本章介绍.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位数据使用232位数据表示), 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文件对应关系:

最新回复(0)