1.什么是设备树
设备树(Device Tree)是用来描述(存储)硬件信息的一种树形结构,设备树在linux内核启动的时候传递给内核被内核解析,用来描述设备信息的一种方式(地址,中断号...)。设备节点中信息(属性)构成一个链表,如果你的驱动想要使用这个设备信息只需要在这个链表中获取设备信息即可。
2.设备树文的格式
****.dts//设备树的源码文件,类似于.c后缀的文件
****.dtsi//设备树的头文件,里面是对于源码文件的补充,类似.h后缀的文件
|
DTC //编译工具 (make dtbs 单独编译设备树源码文件生成设备树镜像文件)
|
****.dtb //设备树的二进制文件
2.1设备树语法实现
/dts-v1/; //设备树的版本号
/ { //根节点
node1 { //根节点的子节点node1
a-string-property = "A string"; //属性 以键值对的形式存在
a-string-list-property = "first string", "second string";
// hex is implied in byte arrays. no '0x' prefix is required
a-byte-data-property = [01 23 34 56];
child-node1 { //node1的子节点child_node1
first-child-property;
second-child-property = <1>;
a-string-property = "Hello, world";
};
child-node2 {//node1的子节点child_node2
};
};
node2 {//根节点的子节点
an-empty-property;//空的键值对,一般起到标识作用
a-cell-property = <1 2 3 4>; /* each number (cell) is a uint32 */
child-node1 {
};
};
};
- 设备树是从根节点 /{};开始描述
- node1和node2是设备树的子节点
- 设备树文件注释和c是一样的
- 设备树每一句话后面都要以;结尾
- 节点内部的属性是键值对:键名=数值
2.2设备树的节点命名
节点的命名形式:<name>[@<unit-adress>]
<name>:节点名字,是一个简单的 ASCII 字符串,长度最多为 31 个字符,通常,节点是根据它所代表的设备类型来命名的。
<unit-adress>:如果节点使用地址描述设备,则包含单元地址。通常,单元地址是用于访问设备的主要地址,列在节点的属性中。
例:LED@50006000{ };
同级节点必须具有唯一名称,但只要地址不同(即serial@101f1000&serial@101f2000),多个节点使用相同的通用名称是正常的。
2.3键值对的格式
属性是简单的键值对,其中值可以为空或包含任意字节流。虽然数据类型未编码到数据结构中,但可以在设备树源文件中表示一些基本数据表示形式。
1.文本字符串(以 null 结尾)用双引号表示:
string-property = "a string";
2.“cell”是 32 位无符号整数,由尖括号分隔:
cell-property = <0xbeef 123 0xabcd1234>;
3.二进制数据用方括号分隔(用十六进制表示的单字节整数):
binary-property = [0x01 0x23 0x45 0x67];
4.不同表示形式的数据可以使用逗号连接在一起:
mixed-property = "a string", [0x01 0x23 0x45 0x67], <0x12345678>;
5.逗号也用于创建字符串列表:
string-list = "red fish", "blue fish";
在linux内核里面有一些具有特殊含义的键,比如:
compatible=“厂商,设备名”
compatible="hqyj,si7006"
reg=<地址>
#address-cells:用于描述地址的uint32的个数
#size-cells:用于描述地址长度的uint32的个数
2.4向内核中添加自己的设备树节点
vi 内核源码顶层目录/arch/arm/boot/dts/stm32mp157a-fsmp1a.dts
//将下面这个节点添加在根节点内部
mynode@0x12345678{
compatible = "hqyj,mynode";
astring="hello 22081";
uint =<0xaabbccdd 0x11223344>;
binarry=[00 0c 29 7b f9 be];
mixed ="hello",[11 22],<0x12345678>;
};
3.在驱动中获取到设备树节点信息
3.1设备树节点结构体
struct device_node {
const char *name; //节点名 mynode
const char *full_name;//节点全名mynode@0x12345678
struct property *properties;//设备树节点属性链表头节点地址指针
struct device_node *parent;//当前节点父节点地址
struct device_node *child;//当前节点子节点地址
struct device_node *sibling;//兄弟节点地址
};
3.2 属性结构体
struct property {
char *name;//键名
int length;//值的长度
void *value;//值
struct property *next;//指向下一个属性节点的指针
};
3.3获取设备数节点相关API
#include<linux/of.h>
1.struct device_node *of_find_node_by_path(const char *path)
功能:通过路径获取设备树节点信息
path:设备树节点路径 ("/mynode@0x12345678")
返回值:成功返回目标节点首地址,失败返回NULL
2.struct device_node *of_find_node_by_name(struct device_node *from,
const char *name);
功能:通过节点名获取设备树节点信息
参数:
from:已知的节点首地址,(NULL,默认从根节点开始解析)
name:节点名字:"mynode"
返回值:成功返回目标节点首地址,失败返回NULL
3.struct device_node *of_find_compatible_node(struct device_node *from,
const char *type, const char *compat);
功能:通过节点中的conpatible来解析获取设备树节点信息
参数
from:已知的节点首地址,(NULL,默认从根节点开始解析)
type:填NULL
cpmpat:compatible的值
返回值:成功返回目标节点首地址,失败返回NULL
3.4获取属性结构体相关API
struct property *of_find_property(const struct device_node *np,
const char *name,
int *lenp)
功能:
通过节点信息结构体和键名获取指定属性信息
参数:
np:节点结构体指针
name:键名
lenp:获取到属性值的长度指针
返回值:成功返回目标属性结构体指针,失败返回NULL
3.5获取属性数值相关API
1.int of_property_read_u32_index(const struct device_node *np,
const char *propname, u32 index, u32 *out_value)
功能:获取u32类型的值
参数:
np:设备树节点结构体指针
proname:键名
index:索引号,第一个数值索引号为0,依次+1
out_value:获取到的值存放的空间首地址
返回值:成功返回0,失败返回错误码
2.int of_property_read_variable_u32_array(const struct device_node *np,
const char *propname,
u32 *out_values,
size_t sz_min,
size_t sz_max)
功能:将获取到的u32类型的值存放在array数组中
参数:
np:设备树节点结构体指针
proname:键名
out_value:获取到的值存放的空间首地址(数组名)
min:期待读取到的值的最小数量
max:期待读取到的值的最大数量
返回值:成功返回0,失败返回错误码
3.int of_property_read_string(const struct device_node *np,
const char *propname,
const char **out_string)
功能:获取字符串类型的值
参数:
np:设备树节点结构体指针
proname:键名
out_string:获取到的字符串类型的值的首地址
返回值:成功返回0,失败返回错误码
4.int of_property_read_variable_u8_array(const struct device_node *np,
const char *propname, u8 *out_values,
size_t sz_min, size_t sz_max)
功能:读取u8类型的数组
参数:
np:设备树节点结构体指针
proname:键名
out_value:获取到的值存放的空间首地址(数组名)
min:期待读取到的值的最小数量
max:期待读取到的值的最大数量
返回值:成功返回0,失败返回错误码
5.int of_property_read_u8_array(const struct device_node *np,
const char *propname,
u8 *out_values, size_t sz)
功能:读取u8类型的数组
参数:
np:设备树节点结构体指针
proname:键名
out_value:获取到的值存放的空间首地址(数组名)
sz:数组成员的个数
返回值:成功返回0,失败返回错误码