dts基础总结
参考官网例程:https://elinux.org/Device_Tree_Usage#Sample_Machine
- dts语法
Linux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离。设备树就是有一些属性和节点组成的一种数据结构,属性一般会赋予一些属性值,而节点是由属性跟其下的子节点构成。
这是官网的一个语法例程,可以看到dts的语法很像格式化JSON字符串和python字典,都是由节点和键值对组成,只不过dts是由dtc编译器编译成dtb给内核解析的。其组成为:
- 一个唯一的根节点/
- 由子节点node1和node2,node1和node2又包含了一系列属性和子节点。
其属性赋值格式为:
- Text strings (null terminated) are represented with double quotes:
- string-property = "a string";
- 'Cells' are 32 bit unsigned integers delimited by angle brackets:
- cell-property = <0xbeef 123 0xabcd1234>;
- Binary data is delimited with square brackets:
- binary-property = [0x01 0x23 0x45 0x67];
- Data of differing representations can be concatenated together using a comma:
- mixed-property = "a string", [0x01 0x23 0x45 0x67], <0x12345678>;
- Commas are also used to create lists of strings:
- string-list = "red fish", "blue fish";
- 关键属性
1,node节点就是挂载在CPU下的设备或者总线,Linux内核约定设备名应形式:
<name>[@<unit_address>]
其中name是设备名,unit_address一般是设备地址,用来唯一标识一
个节点。chosen不描述硬件节点信息,而是传递给kernel一些参数。如:
chosen {
bootargs = "root=/dev/nfs rw nfsroot=192.168.1.1 console=ttyS0,115200";
};
2,compatile属性
Compatile = "<manufacturer>,<model>"
设备节点都会有compatible属性, 设备与驱动之间的结合就依赖这个属性的匹配。Compatible属性是由字符串列表组成,有两个属性值,以一个字符串确切的表示该设备的信息,第二个字符串描述的与该节点描述符相兼容的设备。
3,reg属性
reg 格式:reg = <address1 length1 [address2 length2] [address3 length3]>;
#address-cells = <xxx> //表示reg中address元素的个数
#size-cells = <xxx> //表示length元素的个数
父类的address-cells和size-cells决定了子类的相关属性要包含多少个cell,如果子节点有特殊需求的话,可以自己再定义,这样就可以摆脱父节点的控制。
4,range属性
如果根节点的子节点已经使用了CPU地址域,就不需要任何显式映射了,例如,串口serial@101f0000被直接分配到地址0x101f0000。如果根节点的间接子节点没有使用CPU的地址域,为了获得一个内存映射地址,设备树必须指定如何翻译地址。ranges属性为一个地址转换表。表中的每一行都包含了子地址、父地址、在自地址空间内的区域大小。
- Offset 0 from chip select 0 is mapped to address range 0x10100000..0x1010ffff
- Offset 0 from chip select 1 is mapped to address range 0x10160000..0x1016ffff
- Offset 0 from chip select 2 is mapped to address range 0x30000000..0x30ffffff
5,interrutpt属性
描述中断连接需要四个属性:
interrupt-controller 一个空属性用来声明这个node接收中断信号;
#interrupt-cells 这是中断控制器节点的属性,用来标识这个控制器需要几个单位做中断描述符;
#interrupt-cells = <2>时第一个表示中断索引,第二个表示触发方式
1 = low-to-high edge triggered 2 = high-to-low edge triggered
4 = active high level-sensitive 8 = active low level-sensitive
#interrupt-cells = <3>时第3个参数表示优先级,0~7,对应优先级从高到低
interrupt-parent 标识此设备节点属于哪一个中断控制器,根节点下所有中断均继承此中断号,如果没有设置这个属性,会自动依附父节点;
interrupts 一个中断标识符列表,表示每一个中断输出信号。
详细见官网例程:
/dts-v1/;
/ {
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 >;
};
...
intc: interrupt-controller@10140000 {
compatible = "arm,pl190";
reg = <0x10140000 0x1000 >;
interrupt-controller;
#interrupt-cells = <2>;
};
...
6, alias属性
aliases别名,不必一级一级的访问。
aliases {
spi0 = "/spi@12340000";
spi1 = "/spi@12341000";
.....
- 解析流程
- 编译与反编译
dtc [-I input-format] [-O output-format][-o output-filename] [-V output_version] input_filename
控制参数dtc和dtb可以编译与反编译。
2,初步解析
在arch/arm/mach-******/******.c找到DT_MACHINE_START和 MACHINE_END 宏,其中.dt_compat= ******_dt_compat 这个结构体是匹配是哪个dts文件,这个"xlnx,zynq-7000" 字符串可以在我们的dts的根节点下可以找到.
- 总结
本总结仅仅参考官网dts入门使用,后续详细流程待学习完善。