
设备树作为描述芯片以及单板的架构、组成的一种ABI形式的载体,其自身的构成、传输、展开、应用必然遵循一定的规则,以便达到独立于kernel代码且适配能力强大的效果。作为一种独立于kernel镜像的ABI载体,其需要独立编写并生成二进制文件传递给kernel。kernel按照既定规则解析出所需数据供kernel驱动代码使用。
摘抄kernel: usage-model.rst的描述如下:
The"Open Firmware Device Tree", or simply Device Tree (DT), is a datastructure and language for describing hardware. More specifically, it is a description ofhardware that is readable by an operating system so that the operatingsystem doesn't need to hard code details of the machine.
#设备树生命周期

设备树文件经历源码阶段、编译阶段、复制传输阶段、解析增添阶段,最终变成可用的Expanded device tree供驱动代码使用。
##源码阶段
设备树源文件有两种尾缀,分别是dts以及dtsi。dtsi常规意义上定义SoC级别的硬件信息,而dts常规意义上定义board级别的硬件信息。dts通过#include的方式包含进dtsi文件。设备树的代码实现遵循device tree协议以及各厂商规定的兼容binding规则,device tree协议官网:
https://www.devicetree.org/

各厂商规定的兼容binding规则需要在社区提交审核,最终出现在release kernel的documents中。

##编译阶段
kernel编译时使用scritpts下的dtc工具(宿主机同样也有dtc工具),根据arch/arm/boot/dts/Makefile中的规则,将设备树源码编译成dtb格式的ABI文件。

##复制传输阶段
dtb文件可独立于kernel镜像,亦可以追加到zImage镜像之后,由U-Boot将其复制加载到memory。
当使用前者进行复制加载时,通过U-Boot提供的fdt命令可对设备树文件进行局部修改。修改后再传递给kernel。

当使用后者将dtb追加到zImage文件之后的时候,kernel未提供相关的工具链。需要kernel打开CONFIG_ARM_APPENDED_DTB。将dtb文件cat到zImage文件之后即可。


##解析阶段
当U-Boot通过ARM通用寄存器r2将设备树dtb文件memory地址传递给kernel之后,kernel会将平滑的FDT文件解析成EDT文件,提取出root、chosen、aliases、nodes等信息供驱动代码使用。
#设备树的源码实现
##设备树基本组成元素
以vexpress-v2p-ca9.dts为例,设备树文件的基本组成元素包括根节、设备类型、chosen结点、aliaes结点、某bus类型的各种node。如下图:

###model
在设备树应用于ARM平台前,U-Boot通过给ARM通用寄存器r1赋值来给kernel传递machine type,在设备树文件应用于ARM平台后,kernel通过解析设备树文件的model来识别匹配对应的设备以进行适配初始化硬件。
###chosen
这个结点不描述具体的硬件信息,用于设备树和kernel之间传递信息用,通常传递的是bootargs。在设备树中可以将该节点置空,当然也可以预先定义一些bootargs,然后在kernel的boot阶段填充。例如当前的设备树文件中chosen结点是空的,当kernel启动后去查看chosen结点已经被填充的bootargs。

###aliases
kernel通常是按照绝对路径查询一个设备结点,而aliases将普通的设备结点的label取一个别名,方便后面查看设备。例如vexpress-v2p-ca9.dts文件中将串口和i2c作了别名处理,那么我们在查看dtb的反汇编文件时,别名是按照绝对路径展开的。

使用了别名的串口、i2c同未使用别名的watchdog对比很明显,可以清楚的知道串口设备的编号。

###nodes
普通设备结点是设备树文件中存在最多的内容。这部分结点要从属于某一个总线类型,可以是simple-bus,也可以是amba-bus。普通设备结点下包含设备的适配名、寄存器、中断、时钟、DMA通道、引脚复用等的硬件描述信息。根据具体的设备做具体的描述。对于USB、PCI、Graph等总线结构的设备,还需要在设备树中体现出拓扑结构、中断映射map等相关的特性。
##设备树的头文件
设备树头文件包含是以一种覆盖、插入的方式实现的。xxx.dts包含xxx.dtsi文件,当dts以及dtsi都包含同一个结点node_A但结点信息不同时,编译器会将dtsi中node_A的硬件信息条目插入到dts的node_A结点。
##设备树编译
关于dtc前面有介绍,另外补充说明的是dtc具有反汇编的功能,当手头有一个dtb文件,希望查看其dts文件时,反汇编功能显的很有用。若kernel启动后文件系统中具备dtc工具,通过反汇编可以查看U-Boot是否对dtb文件有修改。下面是一个反汇编的实例。

##设备树编写参考文档
https://elinux.org/Device_Tree_Usage
kernel: Documentation/devicetree
https://www.devicetree.org/
END
小哥搜集了一些嵌入式学习资料,公众号内回复【1024】即可找到下载链接!
推荐好文点击蓝色字体即可跳转
☞专辑|Linux应用程序编程大全 ☞ 专辑|学点网络知识 ☞ 专辑|手撕C语言 ☞ 专辑|手撕C++语言
☞ 专辑|经验分享 ☞ 专辑|从单片机到Linux ☞ 专辑|电能控制技术 ☞ 专辑|嵌入式必备数学知识 ☞ MCU进阶专辑
☞ 经验分享