问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

如何使用dtc编译设备树 devicetree

发布网友 发布时间:2022-04-21 23:44

我来回答

1个回答

热心网友 时间:2022-04-27 00:20

  DTS (device tree source)
  .dts文件是一种ASCII 文本格式的Device
Tree描述,此文本格式非常人性化,适合人类的阅读习惯。基本上,在ARM
Linux在,一个.dts文件对应一个ARM的machine,一般放置在内核的arch/arm/boot/dts/目录。由于一个SoC可能对应多个machine(一个SoC可以对应多个产品和电路板),势必这些.dts文件需包含许多共同的部分,Linux内核为了简化,把SoC公用的部分或者多个machine共同的部分一般提炼为.dtsi,类似于C语言的头文件。其他的machine对应的.dts就include这个.dtsi。譬如,对于VEXPRESS而言,vexpress-v2m.dtsi就被vexpress-v2p-ca9.dts所引用,
vexpress-v2p-ca9.dts有如下一行:
/include/
"vexpress-v2m.dtsi"
当然,和C语言的头文件类似,.dtsi也可以include其他的.dtsi,譬如几乎所有的ARM
SoC的.dtsi都引用了skeleton.dtsi。
.dts(或者其include的.dtsi)基本元素即为前文所述的结点和属性:

  [plain] view
plaincopyprint?

  / {

  node1 {

  a-string-property = "A string";

  a-string-list-property = "first string", "second string";

  a-byte-data-property = [0x01 0x23 0x34 0x56];

  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 {

  };

  };

  };
  / {
node1 {
a-string-property = "A string";
a-string-list-property = "first string", "second string";
a-byte-data-property = [0x01 0x23 0x34 0x56];
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 {
};
};
};
上述.dts文件并没有什么真实的用途,但它基本表征了一个Device
Tree源文件的结构:
1个root结点"/";
root结点下面含一系列子结点,本例中为"node1" 和
"node2";
结点"node1"下又含有一系列子结点,本例中为"child-node1" 和
"child-node2";
各结点都有一系列属性。这些属性可能为空,如"
an-empty-property";可能为字符串,如"a-string-property";可能为字符串数组,如"a-string-list-property";可能为Cells(由u32整数组成),如"second-child-property",可能为二进制数,如"a-byte-data-property"。
下面以一个最简单的machine为例来看如何写一个.dts文件。假设此machine的配置如下:
1个双核ARM
Cortex-A9 32位处理器;
ARM的local bus上的内存映射区域分布了2个串口(分别位于0x101F1000 和
0x101F2000)、GPIO控制器(位于0x101F3000)、SPI控制器(位于0x10170000)、中断控制器(位于0x10140000)和一个external
bus桥;
External bus桥上又连接了SMC SMC91111
Ethernet(位于0x10100000)、I2C控制器(位于0x10160000)、64MB NOR
Flash(位于0x30000000);
External bus桥上连接的I2C控制器所对应的I2C总线上又连接了Maxim
DS1338实时钟(I2C地址为0x58)。
其对应的.dts文件为:

  [plain] view
plaincopyprint?

  / {

  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>;

  };

  };

  };
  / {
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>;
};
};
};
上述.dts文件中,root结点"/"的compatible 属性compatible =
"acme,coyotes-revenge";定义了系统的名称,它的组织形式为:<manufacturer>,<model>。Linux内核透过root结点"/"的compatible
属性即可判断它启动的是什么machine。
在.dts文件的每个设备,都有一个compatible
属性,compatible属性用户驱动和设备的绑定。compatible
属性是一个字符串的列表,列表中的第一个字符串表征了结点代表的确切设备,形式为"<manufacturer>,<model>",其后的字符串表征可兼容的其他设备。可以说前面的是特指,后面的则涵盖更广的范围。如在arch/arm/boot/dts/vexpress-v2m.dtsi中的Flash结点:

  [plain] view
plaincopyprint?

  flash@0,00000000 {

  compatible = "arm,vexpress-flash", "cfi-flash";

  reg = <0 0x00000000 0x04000000>,

  <1 0x00000000 0x04000000>;

  bank-width = <4>;

  };
  flash@0,00000000 {
compatible = "arm,vexpress-flash", "cfi-flash";
reg = <0 0x00000000 0x04000000>,
<1 0x00000000 0x04000000>;
bank-width = <4>;
};
compatible属性的第2个字符串"cfi-flash"明显比第1个字符串"arm,vexpress-flash"涵盖的范围更广。
再比如,Freescale
MPC8349 SoC含一个串口设备,它实现了国家半导体(National Semiconctor)的ns16550
寄存器接口。则MPC8349串口设备的compatible属性为compatible = "fsl,mpc8349-uart",
"ns16550"。其中,fsl,mpc8349-uart指代了确切的设备, ns16550代表该设备与National Semiconctor
的16550
UART保持了寄存器兼容。
接下来root结点"/"的cpus子结点下面又包含2个cpu子结点,描述了此machine上的2个CPU,并且二者的compatible
属性为"arm,cortex-a9"。
注意cpus和cpus的2个cpu子结点的命名,它们遵循的组织形式为:<name>[@<unit-address>],<>中的内容是必选项,[]中的则为可选项。name是一个ASCII字符串,用于描述结点对应的设备类型,如3com
Ethernet适配器对应的结点name宜为ethernet,而不是3com509。如果一个结点描述的设备有地址,则应该给出@unit-address。多个相同类型设备结点的name可以一样,只要unit-address不同即可,如本例中含有cpu@0、cpu@1以及serial@101f0000与serial@101f2000这样的同名结点。设备的unit-address地址也经常在其对应结点的reg属性中给出。ePAPR标准给出了结点命名的规范。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
手机变砖变砖的原因 新手H1073C 刷机变砖了,求助 黄鼠狼怎么控制人 要造一个工程,工程总造价为78000000,施工前要办理施工许可证,请问办 ... 78000000万元等于多少亿? 胃炎犯了能吃水果吗 胃炎吃水果要注意什么 慢性胃炎不可以吃什么水果 慢性胃炎不能吃什么水果 Gmapping-移动机器人是怎么构建地图 牙龈出血是怎么回事啊? 汇编语言问题 16位的寄存器 的16位是指的地址总线吗 牙龈会自动出血,刷牙也会出血是怎么回事? 在16位CPU中,有哪些8位寄存器、16位寄存器? 牙齿自动出血是什么原因 单片机里面的寄存器的字节地址是用来干什么的,怎么用? 牙龈老出血是怎么回事啊?? 如何保存微信语音制作视频 8250有多少个寄存器,简述其功能? 牙龈频繁少量自动出血怎么回事 串口有哪些芯片 数据寄存器的使用方法 平常牙龈就自动出血 怎么回事阿? 16位的寄存器 牙龈最近天天自动 出血,是怎么回事撒 牙龈突然毫无征兆的出血了,而且出的挺多是怎么回事 牙龈怎么会突然出血咋回事 我想他来 和 我叫他来 在语法结构上有什么区别 磨刀什么什么 历年湖北高考录取分数线 如何保存微信聊天语音记录 单片机特殊功能寄存器怎么用呀? 最近牙龈总是出血,怎么回事。 uart是干吗的? 司法行政机关 16位CPU在进行堆栈操作时,分别用到的寄存器有哪些? 牙龈经常自主流血是怎么回事 为什么牙龈会自动流血 每天牙齿都会出血?请问怎么回事? 司法机关的职能是什么 单片机里面的寄存器的字节地址是用来干什么的?怎... 牙龈总出血是咋么回事 如何配置寄存器的地址 司法的特点是什么? 女生米白色开衫应该如何搭配? 牙龈出血是怎么回事?不痛不痒就是莫名其妙的出血! 米白色开衫怎么搭配 什么是U A R T 司法途径都包括什么 牙龈总出血是怎么回事呀?