什么是设备树?
设备树(Device Tree)是一种描述硬件的数据结构,是结构化的语言,有点像C语言的结构体。在操作系统引导启动阶段进行设备初始化的时候,设备树中描述硬件的信息被检测到并传递给操作系统。
设备树前世今生
在没有设备树之前,嵌入式linux下的所有设备信息,都是分散集成定义在代码中的,即与设备相关的数据结构都通过结构体数据在代码中体现。
试想,各大厂商们制造的各种SOC,每个SOC的外设都不尽相同,那么外设的定义在源码中就大量充斥,五花八门的设备定义也给移植和修改带来了大量的工作量。
有了设备树后,可以将SOC的所有外设全部抽象出来,统一放入到设备树中,按照设备树规则来进行描述,这样就实现了设备与驱动的分离。系统先通过扫描设备树上的所有设备,通过扫描到的设备再来对应设备的驱动程序。
有人说,原先在代码中集成设备信息的方法也挺好,只要管理好了,也很方便,如之前所说的,如果没有设备树,设备定义就会在不同的SOC上五花八门,当你涉及多种SOC生产产品时,面对五花八门的设备树,进行设备信息和驱动程序移植,就会造成大量的工作量。
使用设备树好处?
好处如下:
1,在开发产品时,一个SOC(CPU)可能会根据不通客户要求,所涉及到的外设数量也不同。比如使用同一型号SOC来生产三种不同功能的产品:A,B,C, 那么我们就可以定制三分A,B,C的设备树DTA,DTB,DTC,驱动程序完全不动,根据产品型号A,B,C来加载对应的设备树即可,大大减少了工作量。
2,使用设备树使得设备信息和驱动代码完全分离。
设备树基本结构?
1,设备树涉及几种文件?
A,CPU厂商提供的dtsi文件
SOC厂家会提供一份SOC的设备树,这些设备树如:CPU设备信息,时钟设备信息,显示控制器设备信息的等等的基础设备信息,以rockchip rk3568为例,厂商提供的基础设备树文件为:rk3568.dtsi,这里面的设备除了上电必要的设备外是使能的,其它的都是默认关闭的(即:status=”disabled"),如:
vop_mmu: iommu@fe043e00 {
compatible = "rockchip,iommu-v2";
reg = <0x0 0xfe043e00 0x0 0x100>, <0x0 0xfe043f00 0x0 0x100>;
interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "vop_mmu";
clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>;
clock-names = "aclk", "iface";
#iommu-cells = <0>;
status = "disabled";
};
iommu@fe043e00设备默认是关闭的(disabled)。
B,客户定义的CPU dtsi或dts文件
客户可以创建两种dtsi文件:一种是客户自定义的外设文件。一种是板级dts文件。
客户自定义的外设文件:
假设客户创建产品型号为A,那么一般会定义自己的A-rk3668.dtsi文件,里面包含客户产品型号A所对应的外设设备信息,如I2C下挂载的设备:如音频芯片,视频解码芯片,RTC芯片等等。另外还包含一些厂商提供的设备树(rk3568.dtsi)里面的一些设备信息开关,如:
&vop_mmu {
status = “okay”
}
表示再产品型号A中要使用“iommu@fe043e00”这个设别,vop_mmu是这个设备的简称(为了dts设备书中书写方便)。
板子dts文件:
该文件就是最终的产品型号A的设备树入口文件。
这个dts和dtsi文件区别是?
简单来说,dtsi可以定义无数个,每个dtsi可以只定义一个设备信息。而一个dts文件就表示一个板子(一个产品型号),里面包含了SOC基础的dtsi(如rk3568.dtsi)和用户自定义的dtsi文件,最后dtc工具将dts编译出来形成了dtb(设备树镜像文件)。
当你使用同一个SOC芯片来生产多种产品:A,B,C时,那么你可以创建A.dts,B.dts, C.dts, 最后编译出来后,就生成了A.dtb, B.dtb, C.dtb,在系统启动时,根据需要加载不同的dtb设备树镜像即实现了不同的产品功能了。
设备树欣赏
从dts入手,即先找到dts文件:
rk3568-xxx.dts
内容如下:
/dts-v1/; #dts版本
#include "rk3568.dtsi" #表示产生SOC的设备树文件,包含进来
#include "rk3568-linux.dtsi" #表示linux下使用的设备树文件,包含进来
#include "rk3568-A-xxx.dtsi" #表示用户根据产品型号定义的设备树文件,包含进来
/delete-node/ &board_id; #删除board_id这个设备节点
/ { #/表示根节点
compatible = "rockchip,rk3568-toybrick-dev-linux-x0","rockchip,rk3568";
};
以上表示的就是一个完整的dts的设备树信息了。
你入门了吗?