文章目录
- [一、设备树 DTS (Device Tree Source)](#一、设备树 DTS (Device Tree Source))
- 二、语法
- 三、帮助文档
- 四、驱动获取设备树节点属性
- 问题
一、设备树 DTS (Device Tree Source)
1、设备树简介
设备树(Device Tree)是对板级硬件资源的结构化抽象描述,它以独立的描述文件向内核传递硬件信息,实现内核代码与板级硬件配置的解耦分离。内核通过解析设备树获取硬件资源信息,并依据匹配规则完成设备与对应驱动程序的绑定,从而让同一内核镜像能够适配不同硬件平台。
2、设备树文件
以dts、dtsi 结尾,一般来说dts描述板卡资源。dtsi描述SOC资源(肯定是芯片厂家提供)
3、设备树编译
dts通过dtc编译位二进制的dtb。DTC 工具源码在 Linux 内核的 scripts/dtc 目录下。
二、语法
1、引用
在dts文件中可以通过#include 引用 dtsi、dts以及C语言的.h文件
c
#include "imx6ull-14x14-evk.dts"
#include <dt-bindings/input/input.h>
#include "imx6ull.dtsi"
2、DTS数据类型
| 类型 | 用法 | 用途 |
|---|---|---|
| 字符串 | model = "My Board"; | 描述文本、compatible、status 等 |
| 字符串列表 | compatible = "fsl,imx6ull-gpmi-nand", "fsl, imx6ul-gpmi-nand"; | |
| 32 位无符号整数(u32) | reg = <0x02020000 0x4000>; | 地址、长度、中断号、时钟、GPIO 编号 |
| 64 位无符号整数(u64) | reg = <0x0 0x10000000 0x0 0x80000000>; | |
| 字节数组(Byte Array) | local-mac-address = [00 11 22 33 44 55]; | MAC 地址、二进制数据 |
| 引用类型(phandle) | interrupt-parent = <&gpc>; | 节点之间互相引用 |
设备树属性的值数量、类型、顺序,不由 DTS 语法决定,而是由该设备对应的驱动程序或内核绑定规则(binding)定义的。DTS 只负责传递数据,驱动负责解析每一位值的含义。
3、节点
设备树是采用树形结构来描述板子上的设备信息的文件,每个设备都是一个节点,叫做设
备节点,每个节点都通过一些属性信息来描述节点信息,属性就是键---值对。如果引用的文件中有相同的节点,节点在编译时会合并为一个节点。
节点的定义(两种方式)
c
node-name@unit-address // 节点名@寄存器地址或设备地址
label: node-name@unit-address //节点标签:节点名@寄存器地址或设备地址
节点可以通过节点标签名称 &lable 被引用
1、aliases 子节点
定义节点别名,属于根节点
2、chosen 子节点
chosen 节点主要是为了uboot向Linux内核传递数据,重点是 bootargs 参数。
Linux启动时uboot向设备树添加bootargs 参数。
4、常用属性
| 名称 | 值 | 作用 |
|---|---|---|
| compatible | 字符串列表 "manufacturer,model" 厂家名称,模块名称 | compatible 属性用于将设备和驱动绑定起来。字符串列表用于选择设备所要使用的驱动程序 |
| model | 字符串 | 描述设备模块信息 |
| status | 预定义的字符串"okay" 等 | 表明设备状态 |
| #address-cells | u32 | 描述子节点reg属性的起始地址长度 |
| #size-cells | u32 | 描述子节点reg属性地址长度 |
| reg | <\u32 add u32 len> reg = <0x02020000 0x4000>; | 描述设备地址空间资源信息,一般都是某个外设的寄存器地址范围信息 |
| ranges | 由子地址、父地址和地址空间长度组成(child-bus-address,parent-bus-address,length) | ,ranges是一个地址映射/转换表 |
1、根节点compatible
作用
根节点的compatible属性值为 <设备名,SOC名称>。。Linux内核会通过根节点的compoatible属性查看是否支持此设备,如果支持的话设备就会启动Linux内核。内核在arch/arm/include/asm/mach/arch.h 中定义板卡名称。Linux内核调用start_kernel函数来启动内核,start_kernel函数会调用setup_arch函数来匹配machine_desc。

5、向节点追加内容
在自己的dts中include厂商的dtsi文件,通过对应的节点标签应用对应节点,然后添加子节点或新的属性。
引用节点(&label): 使用 & 符号引用 .dtsi 中定义的节点标签,实现在 .dts 中追加 / 修改节点。
相同属性:后定义覆盖先定义(.dts 覆盖 .dtsi)。
不同属性:自动合并,共存。
子节点:自动合并,共存。
6、设备树在Linux系统中的体现
/proc/device-tree 目录就是设备树在根文件系统中的体现。
三、帮助文档
Linux源码目录 /Documentation/devicetree/bindings目录下
四、驱动获取设备树节点属性
通过include/linux/of.h 下定义的一些列of_xx 函数
问题
1、dts引用h文件,可以使用里面的那些内容?他们的语法都不用一致
- DTS 可以 #include 头文件(.h),和 C 语言写法一样
- 但 DTS 不是 C 语言,只能用头文件里的 宏定义(#define)
- 不能用:函数、结构体、变量、enum 枚举(直接报错)
- 语法规则:DTS 只识别纯数字宏,必须是整数常量,在dts中作为字符串使用
2、通过DTS如何对应驱动程序?驱动程序放在那里?如何在内核中查找?查找过程是怎样的?
设备树节点中定义 compatible 字符串
驱动程序中通过 of_device_id 结构体定义同样的字符串
内核启动时遍历设备树,只要字符串完全一致,就完成设备与驱动的绑定