linux设备驱动模型的前提就是设备以及驱动适配了才可以加载驱动probe工作,一开始linux的硬件设备信息都是通过rch/arm/mach-xxx文件描述成许多多的设备信息的,然后在系统加载起来的时候设备与驱动匹配成功开始加载驱动程序呢,但是这些代码包含许多硬件板级信息细节,代码多而且冗余,不好搞。所以提出设备树设备配置方式,说那么多就是linux觉得以前那套设备信息配置方式不好,提出了一种新的硬件设备描述方式。而这种就是设备树。
1.设备树的组成以及设计概念。
设备树组成通过节点以及属性组成,从最开始/根节点开始,节点包含属性,节点也可以包含节点,这样不断铺展开来成树型似的,所以叫设备树。节点可以说是像我们的目录一样,从最开始的根目录开始,目录可以包含文件也可以包含目录,不断展开成目录树,目录下面有可以包含文件,而我们的属性对于节点来说,就像是目录下的文件。
总结:
每个目录储存者我们不同的信息内容,例如照片目录存放的照片,视频目录存放着视频。设备树如我们的目录一样,通过每个节点描述者我们不同硬件信息,i2c描述i2c硬件设备的信息,spi描述spi硬件设备的信息。我们的视频目录又可以具体分为电影目录,又可以分为电视剧目录等等具体信息。而我们的设备树也是这样,例如i2c设备节点的用到可以分为触摸屏设备节点,收音机设备节点。因为触摸屏以及收音机大多数采用i2c方式通讯。因此设备树的设计跟目录树概念一样。真的很佩服那些架构设计的人。
2.设备树后缀文件名
.dtsi:代表共有的设备属性写成一个dtsi设备树文件后缀,可以通过像c语言的include "xxx.dtsi"一样把该文件的设备属性包含进来。
.dts :设备树文件名后缀,里面描述各种设备信息,并且通过节点形式形成。
dtc:设备树解析编译的工具文件,在scripts/dtc/目录下,可以这样理解,c语言是一门语言,定义c语言的编写规范,但是还是需要有编译器等工具才能将其解析成机器识别的二进制文件,这样才可以执行。同样,设备树是一种硬件设备信息描述信息的规范,也有一定的语法规则,因此同样需要工具解析编译才能编译成内核识别的文件才行。而dtc文件便是这样的工具。
.dtb:设备解析编译后的二进制文件后缀名,同样c语言进过编译后会形成xxx.o的二进制文件,而设备树也是通过dtc编译成二进制的.dtb后缀的文件。
总结:
设备树包含dtsi,dts,dtc以及dtb文件,这样文件编写或者编译过程生成真的很像一门语言的规范设计,但是其比一门语言的规范简单的多很多,只能说设计概念很像。
1.节点组成格式:
lable:name[@unit_address]{
xxxx;
};
name:设备节点的名字
@unit_address:设备地址
uart0: serial@f8036000 {/*串口的设备名字为serial,地址为f8036000*/
compatible = "arm,pl011", "arm,primecell";
reg = <0xf8036000 0x1000>;
interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clkctrl ARTPEC6_CLK_UART_REFCLK>,
<&clkctrl ARTPEC6_CLK_UART_PCLK>;
clock-names = "uart_clk", "apb_pclk";
status = "disabled";
};
lable:lable代表的是该节点的别名标签,通过&lable来引用lable来包含该节点,其方式通过phandle进行的(可以先不用理解),甚至可以通过&lable来拓展该节点。例如:
(1)引用lable来包含该节点
```powershell
syscon: syscon@f8000000 {/*此处定义syscon lable*/
compatible = "axis,artpec6-syscon", "syscon";
reg = <0xf8000000 0x48>;
};
pcie: pcie@f8050000 {
compatible = "axis,artpec6-pcie", "snps,dw-pcie";
reg = <0xf8050000 0x2000
0xf8040000 0x1000
0xc0000000 0x2000>;
reg-names = "dbi", "phy", "config";
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
/* downstream I/O */
ranges = <0x81000000 0 0 0xc0002000 0 0x00010000
/* non-prefetchable memory */
0x82000000 0 0xc0012000 0xc0012000 0 0x1ffee000>;
num-lanes = <2>;
bus-range = <0x00 0xff>;
interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "msi";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
interrupt-map = <0 0 0 1 &intc GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>,
<0 0 0 2 &intc GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
<0 0 0 3 &intc GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
<0 0 0 4 &intc GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
axis,syscon-pcie = <&syscon>;/*此处通过&syscon lable来将节点syscon包含到pcie节点信息中了*/
status = "disabled";
};
(2)&lable拓展
/*的方式就是在原来的基础上在即扩展了该lable节点的信息。*/
&lable{
xxx
};
2.节点属性的编写规则
节点{}里面的信息代表者节点属性,每个属性内核都有对应接口解析以及获取,至于原理是如何我们后续可以再分析,这里我们只需要了解属性的编写规范以及代表的意思便可。
lable:name[@unit_address]{
.compatible = "," ;
#address-cells=<>;
#size-cells=<>;
reg=<>;
gipo-controller;
xx-gpio=<&gpio 0>;
#interrupt-cells=<>;
interrupt-controller;
interrupt-parent=;
interrupt=<>;
clocks =<>;
clock-names= ;
pinctrl-name = ;
pinctrl-0=;
pinctrl-1=;
}
3.设备树与驱动匹配过程
4.设备树常用接口