1.1、设备树是什么
(1)device tree,设备树,是一种linux内核中采用的参数表示和传递技术
(2)dts,device tree source,设备树源文件
(3)dtc,device tree compiler,设备树编译/反编译/调试工具
(4)dtb,device tree blob,二进制设备树镜像
1.2、为什么需要设备树
(1)典型需求就是内核设备驱动,我们以驱动为例分析,但是不止可以用于驱动场景
(2)驱动源码包括2大部分:策略(操作函数)和数据(硬件信息)
(3)早期解决方案:策略和数据都在kernel源码中硬编码
(4)坏处:kernel源码中充斥大量描述硬件信息的文件,污染内核
1.3、设备树技术如何工作
(1)驱动开发者编写/改写dts,适配硬件和自己的需求
(2)make uImage时,kernel内部会先编译出dtc,然后用dtc将dts加工成dtb
(3)uboot启动kernel时,将uImage和dtb都准备好并告知uImage在哪里找dtb
(4)kernel启动初期调用内部函数解析dtb,得到硬件信息,并组装成数据结构,配合策略函数工作
设备树源码dts的格式讲解
2.1、dts文件在哪里
(1)早期版本的硬件信息.h文件多放在arch/arm/mach-xxx 或者arch/arm/plat-xxx中
(2)dts文件放在arch/arm/boot/dts目录中
2.2、dts的格式简介
(1)后缀名一般为dts和dtsi,可以被include,甚至可以include那些C语言的头文件
(2)dtsi一般写soc共性部分,而dts一般写目标单板特性部分,所以一般dts包含并重写部分dtsi
(3)注释用/* */,注意#开头的不是注释
(4)分号是段落块之间的分隔符,{}和[]和<>是段落块的封装符号,和C语言语言类似
(5)/dts-v1/节点,表示dts的版本号,目前都是v1
(6)/{}是根节点root node,理论上只应该有一个根节点,有说法dtc会合并所有root node为同一个
(7)dts是树状的多节点组织,基本单元是node,除root外其他node都有parent,还可以有child
2.3、dts的节点格式
(1)格式定义
[label:] [@]{
[property]
[child nodes]
[child nodes]
......
};
(2)格式解读
[]:表示该项可以省略,<>表示不可省略
[label]:标签,为了方便访问节点,后面可以直接通过&label来访问该节点。
node-name:节点名称。根节点的名称必须是/
[@unit-address]:地址,如cpu node就是0、1这种,reg node就是0x12010000这种
(3)实战演练,看3516dv300的dts
(4)一般一个节点描述一个硬件模块,但是不是所有硬件模块都需要dts来描述,usb或emmc等可以自己探测
3.设备树源码dts的格式讲解2
3.1、property属性格式
(1)每个property就是一个key value对,property-name就是key
(2)属性可以有值或者没有值
[label:] prooerty-name = value; //有值
[label:]property-name; //没有值
(3)value的几种可能情况
字符串 compatible = "arm,cortex-a7";
32位无符号整数 reg =
16进制字节序列 reg = [00 11 22 33] //每个数据必须是2位,也可以附加上0x
字符串列表 compatible = "fsl,imx6ull-gpmi-nand", "fsl,imx6ul-gpmi-nand";
3.2、常见预定义标准属性
(1)compatible,节点数据将来去匹配内核策略部分的兼容性设置
案例1:compatible = "manufacturer, model"
案例2:compatible = "fsl, imx6ul-evk-wm8960", "fsl, imx-audio-wm8960"
案例3:16dv300的串口uart
注意1:根节点的compatible属性是确认内核是否适配该dtb的,作用类似于老版本的machine id
而设备节点的compatible属性是为了匹配Linux内核中的驱动程序,作用类似于以前的.name
注意2:compatible如果有多个,前面的更精准,后面的越来越泛化,所以优先匹配前面
4.设备树源码dts的格式讲解3
4.1、继续上节讲常见属性
(2)model,描述设备模块信息,比如名字、详细版本号
案例1:model = "wm8960-audio-V1.0"
案例2:model = "Hisilicon HI3516DV300 DEMO Board"
(3)status,描述设备状态信息,有以下几个值
"okey" 表示设备是可操作的
"disabled" 表示当前不可操作,但是后续是可以更改为可操作性的
"fail" "failed" 表示有严重错误,几乎不可能再可操作了
(4)reg,配置某个硬件模块对应的地址范围信息,reg是region
#address-cells = // 表示reg里面的数据address占用一个字长,注意字长不是字节
#size-cells = // 表示reg里面的数据size占用一个字长,注意字长不是字节
gpio-spi: gpio_spi@0{
compatible = ".spi"
reg =
//address一般用来表示起始地址,length一般表示持续长度
}
实例参考16dv300的dts
4.2、中断描述的属性
(1)interrupt-controller 无值属性,表示这是个中断控制器node
(2)#interrupt-cells 这是中断控制器节点的属性,用来标识这个控制器需要几个cell做中断描述符
(3)interrupt-parent 标识此设备节点属于哪一个中断控制器,如果没有这个属性,会自动依附父节点
(4)interrupts 一个中断标识符列表,表示每一个中断输出信号