本文介绍如何为新的机器或板卡编写设备树(Device Tree), 它旨在概要性的介绍设备树概念,以及如何使用它们来描述机器或者板卡。
有关设备树数据格式的完整技术描述,请参阅ePAPR v1.1规范。 ePAPR技术规范比本文所介绍的基础主题更加详细,所以请参阅它了解本页未涉及的更高级用法。 ePAPR目前正在用Devicetree规范文档的新名称进行更新。
1 基础数据结构
设备树(Device Tree)是一种包含节点和属性的简单树形结构。属性是键值对,节点则可能包含属性和子节点。 例如,下面是一个.dts格式的简单设备树:
/dts-v1/; / { node1 { a-string-property = "A string"; a-string-list-property = "first string", "second string"; // hex is implied in byte arrays. no '0x' prefix is required a-byte-data-property = [01 23 34 56]; child-node1 { first-child-property; second-child-property = <1>; a-string-property = "Hello, world"; }; child-node2 { }; }; node2 { an-empty-property; a-cell-property = <1 2 3 4>; /* each number (cell) is a uint32 */ child-node1 { }; }; };
上面这个设备树,显然没有实际用处,因为它没有描述任何信息,但是它确实显示了节点的结构和属性:
-
一个简单的root节点:“/”
-
一组子节点:“node1”和“node2”
-
一组node1的子节点:“child-node1”和“child-node2”
-
一堆分散在设备树中的属性
属性是简单的键-值对,其中的值可以是空的,也可以包含任意的字节流。虽然数据类型没有编码到数据结构中,但是有一些基本的数据表示可以在设备树源文件中表示。
-
文本字符串(以null结尾),用双引号表示:
-
string-property = "a string";
-
‘cell’是被<>括号括起来的32bit无符号int数
-
cell-property = <0xbeef 123 0xabcd1234>;
-
二进制数据是被[]括号括起来
-
binary-property = [0x01 0x23 0x45 0x67];
-
不同类型的数据,可以以逗号“,”串起来
-
mixed-property = "a string", [0x01 0x23 0x45 0x67], <0x12345678>;
-
逗号“,”也可以用来表示字符串列表:
-
string-list = "red fish", "blue fish";
2 基础概念Basic Concepts
为了理解设备树(device tree)如何使用,我们将从一个简单的设备(machine)开始,建立一个设备树(device tree),然后一步一步描述它。
2.1示例设备(sample machine)
假设有这样一台虚拟的设备(基于ARM的通用版本),由“Acme”公司生产,名为“Cpyote's Revenge”:
-
一个32位宽的ARM CPU
-
处理器本地总线连接到内存映射串口、spi总线控制器、i2c控制器、中断控制器和外部总线桥
-
从0地址开始的256MB 字节的SDRAM
-
2个串口,寄存器基地址分别是0x101F1000和0x101F2000
-
GPIO的控制寄存器的基地址是0x101F3000
-
SPI的控制寄存器的基地址是0x10170000,并挂载下列设备
-
MMC slot,SS管脚连接到GPIO1
-
外部总线桥接着下列设备
-
SMC SMC91111网络设备连接到外部总线,基地址是0x10100000
-
i2c 控制寄存器基地址是0x10160000,并挂载下列设备
-
Maxim DS1338实时时钟,其地址是1101000(0x58)
-
64M的Nor flash基地址是0x30000000
2.2 初始化结构体(Initial structure)
第一步是为设备铺设骨架, 这是有效设备树所需的最小结构。在这一阶段,你需要能唯一的标识设备。
/dts-v1/; / { compatible = "acme,coyotes-revenge"; };
“compatible”表明系统的名字。它包含一个以“制造商”,“品牌”形式组成的字符串。准确的表明设备非常重要,而且需要包含制造商的名称以避免命名冲突。 由于操作系统将使用compatible值来决定如何在机器上运行,因此将正确的数据写入此属性中非常重要。理论上,一个操作系统唯一识别一台设备只要有“compatible”属性就够了。如果所有设备细节都是硬编码的,那么操作系统可以专门在Device Tree的最顶层的“compatible”属性中查找 "acme,coyotes-revenge"即可。
2.3 CPUs
下一步是描述每一个CPU。添加一个名为“cpus”的容器节点,为每一个CPU创建一个子节点。在当前的例子里,该系统是一个源自ARM的双核Cortex A9系统。
/dts-v1/; / { compatible = "acme,coyotes-revenge"; cpus { cpu@0 { compatible = "arm,cortex-a9"; }; cpu@1 { compatible = "arm,cortex-a9"; }; }; };
每个CPU节点的“compatible”的属性都是一个字符串,以“制造商”,“型号”的形式表明CPU的准确型号,就像设备树(DT)最顶层的“compatible”属性一样。
稍后将向cpu节点添加更多属性,但是我们首先需要讨论更多的基本概念。
2.4 节点名字(Node Names)
首先,我们需要了解命名的规则。每一个节点必须有一个名字,名字的形式必须是“ <name>[@<unit-address>”。<name>是一个简单的ascii字符串,最大长度为31字节。通