
xx.dts:device tree source设备树源文件
xx.dtb:device tree binary 设备树二进制文件
xx.dtc:device tree compiler 设备树编译器,作用:将dts转为dtb
dtc文件的Makefile如下:它在目录scripts\dtc\Makefile下

在linux的源码目录下输入make或make all会编译出all依赖的所有目标,包括zImage,.ko文件和驱动,输入 make tdbs只编译目标dtbs对应的文件也就是所有的设备树文件
而设备树文件是众多的,一个板子就对应一个设备树文件,如何编译我们想要的设备树文件呢,那当然是看设备树文件对应的makefile,在目录arch\arm\boot\dts\Makefile如下:

以后为我们要自己做一块板子时,将板子设备树写好后,将对应的dtb文件名字加入进来,在编译设备树时自然就会编译它
DTS语法
设备树也支持头文件,设备树的头文件后缀名为:.dtsi
设备树文件永include可以包含的头文件包括.h,.dtsi,.dts三种
一般来说,.dtsi文件用于描述soc的内部外设信息,如:cpu架构,主频,I2C,我们不需要改变。比如I.mx6ull.dtsi,要看懂它先得学一下dts语法
/ 它表示根节点
节点命名法则:

node-name:节点名字,是ASCLL字符串
unit-address是节点地址,没有可以省略
可以用标签代替节点名字,避免节点名字太长不方便使用,用法如下:

访问该节点时,用&label访问,不用标签则需使用全路径

属性
属性的名字可以随便取,但是属性的值却有三种取值

compatiable:兼容属性,属性值为字符串列表,字符串值之间以逗号隔开,它的值是优先匹配到的字符串
rag属性表示设备的起始地址和大小
#adress-cells和#size-cells属性
一个cell表示一个32位数据,adress与size属性是用来设置子节点的rag属性
eg:

它表示子节点的起始地址是一个用32位数据表示的数,大小也是。
status属性
要用到的模块值设置为“ok";不用设置为”disable“。fail与fail-ss一般不用
e.chosen属性
chosen节点下面的bootargs属性下面保存的便是我们设置uboot的该参数值,具体如下

f.model 属性
它的值也一个字符串,一般 model 属性描述设备模块信息,比如名字什么的
如何编写dts
.dtsi文件是对用这个芯片一系列板子所共用的头文件,一般不会更改,它里面也是设备树的一系列描述,主要是片内外设资源的描述。
我们通常是通过追加的方式去更改或者写设备树:&label
设备树文件存在的形式是:proc/device-tree/目录下,如图

属性的存在形式是文件,图中白色
子节点的存在形式是目录,图中蓝色
Linux内核解析dtb文件

具体实现不用管,知道在启动内核后,unflatten_dt_node函数会去解析设备节点即可
设备树常用操作函数:of函数集
linux用device_node结构体来描述一个设备节点

节点查找函数,定义在linux内核源码的include/linux/of.h中
of_find_node_by_name()
作用:通过节点名字查找节点

参数1:开始查找的节点位置,NULL表示从根节点开始查找
参数2:节点名字
返回值:成功:找到的节点;失败:NULL
of_find_node_by_type()

参数1:开始查找的节点位置
参数2:要查找的节点对应的 type 字符串,也就是 device_type 属性
返回值:查找成功返回找到的节点,失败为NULL
of_find_compatible_node()

from:开始查找的节点,如果为 NULL 表示从根节点开始查找整个设备树。
type:要查找的节点对应的 type 字符串,也就是 device_type 属性值,可以为 NULL,表示
忽略掉 device_type 属性。
compatible:要查找的节点所对应的 compatible 属性列表。
返回值:找到的节点,如果为 NULL 表示查找失败
of_find_matching_node_and_match()

from:开始查找的节点,如果为 NULL 表示从根节点开始查找这个设备。
matches:of_device_id 匹配表,也就是在此匹配表里面查找节点。
match:找到的匹配的 of_device_id。
返回值:找到的节点,如果为 NULL 表示查找失败
of_find_node_by_path ()

path:带有全路径的节点名,可以使用节点的别名
返回值:找到的节点,如果为 NULL 表示查找失败
查找父/子节点的 OF 函数
of_get_parent ()
作用:于获取指定节点的父节点

参数:要查找的父节点的节点。
返回值:找到的父节点。
b.of_get_next_child()
作用:于获取指定节点的子节点(迭代查找)

node:父节点。
prev:前一个子节点,也就是从哪一个子节点开始迭代的查找下一个子节点。可以设置为
NULL,表示从第一个子节点开始。
返回值:找到的下一个子节点。
提取属性值的 OF 函数
of_find_property()
作用:查找指定的属性

np:设备节点。
name: 属性名字。
lenp:属性值的字节数
返回值:找到的属性。
b.of_property_count_elems_of_size()
作用:查找元素属性数量

np:设备节点。
proname: 需要统计元素数量的属性名字。
elem_size:元素长度。
返回值:得到的属性元素数量。
c.of_property_read_u32_index()
作用:从属性中获取指定标号的 u32 类型数据值

np:设备节点。
proname: 要读取的属性名字。
index:要读取的值标号。
out_value:读取到的值
返回值:0 读取成功,负值,读取失败,-EINVAL 表示属性不存在,-ENODATA 表示没有
要读取的数据,-EOVERFLOW 表示属性值列表太小。
d.of_property_read_u8_array ()
of_property_read_u16_array ()
of_property_read_u32_array ()
of_property_read_u64_array ()
其他常用的 OF 函数
of_device_is_compatible()
作用:查找compatiable属性之中是否含有compat指定的字符串

参数:device:设备节点。
compat:要查看的字符串。
返回值:0,节点的 compatible 属性中不包含 compat 指定的字符串;正数,节点的 compatible
属性中包含 compat 指定的字符串
b.of_get_address()
作用:获取地址相关属性,如reg,assigned-addresses属性

dev:设备节点。
index:要读取的地址标号。
size:地址长度。
flags:参数,比如 IORESOURCE_IO、IORESOURCE_MEM 等
返回值:读取到的地址数据首地址,为 NULL 的话表示读取失败
c.of_translate_address()
作用:将从设备树读到的虚拟地址转换为物理地址

dev:设备节点。
in_addr:要转换的地址。
返回值:得到的物理地址,如果为 OF_BAD_ADDR 的话表示转换失败。
d.of_address_to_resource()
linux内核使用resource结构体来描述一段内存空间

对于 32 位的 SOC 来说,resource_size_t 是 u32 类型的,
start:内存起始地址
end:内存结束地址
name:资源名字
flags:资源标志位,一般表示资源的类型
作用:将reg属性值转化为resource结构体
对于of_address_to_resource:

dev:设备节点。
index:地址资源标号。
r:得到的 resource 类型的资源值。
返回值:0,成功;负值,失败。
e.of_iomap()
作用:of_iomap 函数用于直接内存映射,以前的ioremap也可以,但是在设备树中习惯用of_iomap函数来完成内存映射。

np:设备节点。
index:reg 属性中要完成内存映射的段,如果 reg 属性只有一段的话 index 就设置为 0。
返回值:经过内存映射后的虚拟内存首地址,如果为 NULL 的话表示内存映射失败。