Device-tree
-----------------------------------------------------------------------------------------------------
Notice: 本博主查看了device-tree的相关资料觉得链接博主讲的非常详细,所以摘录过来,方便查看。
转载博主链接:https://blog.youkuaiyun.com/hpu11/article/details/54965020
转载博主链接:https://docs.oracle.com/cd/E38902_01/html/E38873/kernelovr-64300.html
参考链接:http://blog.51cto.com/jiangniu/2068560
英文翻译链接:https://elinux.org/Device_Tree_Usage#Notes
------------------------------------------------------------------------------------------------------
基本数据格式
——————————————————————————————
——————————————————————————————
- 一个根节点: "/"
- 两个子节点: "node1" 和 "node2"
- node1下面又有两个子节点:"child-node1" 和 "child-node2"
- 一堆的属性分散与整颗树的各个节点上
- text string(以null结束),以双引号括起来,如:
- string-property = "a string"
- cells 是32位无符号整形数,以尖括号括起来,如
- cell-property = <0xbeef 123 0xabcd1234>
- binary data 以方括号括起来,如:
- binary-property = [0x01 0x23 0x45 0x67];
- 不同类型数据可以在同一个属性中存在,以逗号分格,如:
- mixed-property = "a string", [0x01 0x23 0x45 0x67], <0x12345678>;
- 多个字符串组成的列表也使用逗号分格,如:
- string-list = "red fish","blue fish";
基本概念
- 32bit ARM CPU
- 处理器的本地内存总线连接如下设备:串口,SPI总线控制器,I2C控制器,终端控制器以及外总线桥
- 256MB SDRAM 位于地址:0x0
- 两个串口,位于地址:0x101F1000 及 0x101F2000
- GPIO控制器位于地址:0x101F3000
- SPI控制器位于地址:0x10170000,在它下面连接了如下设备:
- MMC卡槽,其SS脚连接了GPIO1
- 外部总线桥上接了如下设备:
- SMC91111 以太网控制器,位于地址:0x10100000
- I2C控制器,位于地址:0x10160000,在它下面连接了如下设备:
- Maxim DS1338实时时钟,I2C地址为0x58
- 64MB NOR flash 位于地址:0x30000000
初始结构
第一步是要建立一个基本结构来使得这颗设备树能描述对应的Machine
/ {
compatible = "acme,coyotes-revenge";
};
|
compatible这个属性用于执行系统名,通常它是以 "厂商,型号" 这样的字符串形式存在。它能准确的描述
对应的设备的特征。
CPU描述
/ {
compatible = "acme,coyotes-revenge";
cpus {
cpu@0 {
compatible = "arm,cortex-a9";
};
cpu@1 {
compatible = "arm,cortex-a9";
};
};
};
|
/ {
compatible = "acme,coyotes-revenge";
cpus {
cpu@0 {
compatible = "arm,cortex-a9";
};
cpu@1 {
compatible = "arm,cortex-a9";
};
};
serial@101F0000 {
compatible = "arm,pl011";
};
serial@101F2000 {
compatible = "arm,pl011";
};
gpio@101F3000 {
compatible = "arm,pl061";
};
interrupt-controller@10140000 {
compatible = "arm,pl190";
};
spi@10115000 {
compatible = "arm,pl022";
};
external-bus {
ethernet@0,0 {
compatible = "smc,smc91c111";
};
i2c@1,0 {
compatible = "acme,a1234-i2c-bus";
rtc@58 {
compatible = "maxim,ds1338";
};
};
flash@2,0 {
compatible = "samsung,k8f1315ebm", "cfi-flash";
};
};
};
|
- 每个设备节点都都一个compatible属性
- flash这个节点的compatible属性有两个字串,下面一节将介绍为什么这么写。
可寻址设备是通过使用以下属性来将地址信息编码到设备树中的:
- reg
- #address-cells
- #size-cells
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
compatible = "arm,cortex-a9";
reg = <0>;
};
cpu@1 {
compatible = "arm,cortex-a9";
reg = <1>;
};
};
|
/ {
#address-cells = <1>;
#size-cells = <1>;
...
serial@101f0000 {
compatible = "arm,pl011";
reg = <0x101f0000 0x1000 >;
};
serial@101f2000 {
compatible = "arm,pl011";
reg = <0x101f2000 0x1000 >;
};
gpio@101f3000 {
compatible = "arm,pl061";
reg = <0x101f3000 0x1000
0x101f4000 0x0010>;
};
interrupt-controller@10140000 {
compatible = "arm,pl190";
reg = <0x10140000 0x1000 >;
};
spi@10115000 {
compatible = "arm,pl022";
reg = <0x10115000 0x1000 >;
};
...
};
|
external-bus {
#address-cells = <2>
#size-cells = <1>;
ethernet@0,0 {
compatible = "smc,smc91c111";
reg = <0 0 0x1000>;
};
i2c@1,0 {
compatible = "acme,a1234-i2c-bus";
reg = <1 0 0x1000>;
rtc@58 {
compatible = "maxim,ds1338";
};
};
flash@2,0 {
compatible = "samsung,k8f1315ebm", "cfi-flash";
reg = <2 0 0x4000000>;
};
};
|
i2c@1,0 {
compatible = "acme,a1234-i2c-bus";
#address-cells = <1>;
#size-cells = <0>;
reg = <1 0 0x1000>;
rtc@58 {
compatible = "maxim,ds1338";
reg = <58>;
};
};
|
/ {
compatible = "acme,coyotes-revenge";
#address-cells = <1>;
#size-cells = <1>;
...
external-bus {
#address-cells = <2>
#size-cells = <1>;
ranges = <0 0 0x10100000 0x10000 // Chipselect 1, Ethernet
1 0 0x10160000 0x10000 // Chipselect 2, i2c controller
2 0 0x30000000 0x1000000>; // Chipselect 3, NOR Flash
ethernet@0,0 {
compatible = "smc,smc91c111";
reg = <0 0 0x1000>;
};
i2c@1,0 {
compatible = "acme,a1234-i2c-bus";
#address-cells = <1>;
#size-cells = <0>;
reg = <1 0 0x1000>;
rtc@58 {
compatible = "maxim,ds1338";
reg = <58>;
};
};
flash@2,0 {
compatible = "samsung,k8f1315ebm", "cfi-flash";
reg = <2 0 0x4000000>;
};
};
};
|
- CS0,偏移量为0的本地地址被映射到父节点地址空间的 0x10100000~0x1010ffff
- CS1,偏移量为1的本地地址被映射到父节点地址空间的 0x10160000~0x1016ffff
- CS2,偏移量为0的本地地址被映射到父节点地址空间的 0x30000000~0x31000000
不想地址空间映射表那样是遵循设备树的自然结构的(父传子),中断信号可以被machine中
- interrupt-controller 这个属性没有值,他表示这个节点是一个接收中断信号的设备
- #interrupt-cells 这个属性是一个interrupt-controller节点的属性,他说明了这个
interrupt-controller的每个中断说明符(interrupt specifier)有几个cells,
类似#address-cells 与 #size-cells的作用 - interrupt-parent 这是一个设备节点的属性,用于表明当前设备的中断是属于哪一个
interrupt-controller的,如果没有这个属性,则继承其父节点的interrupt-parent属性 - interrupts 这是一个设备节点的属性,他是 中断说明符 列表,每一个 中断说明符
表示此设备的一个中断信号输出。
/ {
compatible = "acme,coyotes-revenge";
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&intc>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
compatible = "arm,cortex-a9";
reg = <0>;
};
cpu@1 {
compatible = "arm,cortex-a9";
reg = <1>;
};
};
serial@101f0000 {
compatible = "arm,pl011";
reg = <0x101f0000 0x1000 >;
interrupts = < 1 0 >;
};
serial@101f2000 {
compatible = "arm,pl011";
reg = <0x101f2000 0x1000 >;
interrupts = < 2 0 >;
};
gpio@101f3000 {
compatible = "arm,pl061";
reg = <0x101f3000 0x1000
0x101f4000 0x0010>;
interrupts = < 3 0 >;
};
intc: interrupt-controller@10140000 {
compatible = "arm,pl190";
reg = <0x10140000 0x1000 >;
interrupt-controller;
#interrupt-cells = <2>;
};
spi@10115000 {
compatible = "arm,pl022";
reg = <0x10115000 0x1000 >;
interrupts = < 4 0 >;
};
external-bus {
#address-cells = <2>
#size-cells = <1>;
ranges = <0 0 0x10100000 0x10000 // Chipselect 1, Ethernet
1 0 0x10160000 0x10000 // Chipselect 2, i2c controller
2 0 0x30000000 0x1000000>; // Chipselect 3, NOR Flash
ethernet@0,0 {
compatible = "smc,smc91c111";
reg = <0 0 0x1000>;
interrupts = < 5 2 >;
};
i2c@1,0 {
compatible = "acme,a1234-i2c-bus";
#address-cells = <1>;
#size-cells = <0>;
reg = <1 0 0x1000>;
interrupts = < 6 2 >;
rtc@58 {
compatible = "maxim,ds1338";
reg = <58>;
interrupts = < 7 3 >;
};
};
flash@2,0 {
compatible = "samsung,k8f1315ebm", "cfi-flash";
reg = <2 0 0x4000000>;
};
};
};
|
- 此machine仅有一个中断控制器:interrupt-controller@10140000
- 标签"intc:"被加到了中断控制器的节点上,这个标签在父节点上创建了一个phandle,
这个phandle就是父节点的interrupt-parent。所以这个中断控制器就成了系统所有
子节点的默认终端控制器,只有当子节点明确的声明了其interrupt-parent才会被覆盖。 - 每个设备使用interrupt属性来区分不同的终端输入线。
- #interrupt-cells(在interrupt-controller@10140000节点中)的值是2,所以,
每个中断说明符由两个cell数据组成。这个例子中用的是最常见的 中断说明符 形式,
第一个cell表示中断线的序号,第二个cell表示终端类型的flag(表示高有效,低有效。。。),
对于不同的终端控制器,需要阅读对应的binding document来得知其 中断说明符 的格式。
在常用的属性之外,我们还能为一个节点自行添加属性及子节点。只要是系统需要的任何数据都
aliases 节点
aliases {
ethernet0 = ð0;
serial0 = &serial0;
};
|
/********************************************************************************************
以上内容则是对device-tree的基本写法讲解,若有不详细之处请评论。
********************************************************************************************/