目录
③查找节点的 OF 函数之of_find_node_by_path 函数
④提取属性值的 OF 函数之一of_find_property 函数
⑤提取属性值的 OF 函数之of_property_read_string 函数
⑥提取属性值的 OF 函数之of_property_read_u32 函数
⑦提取属性值的 OF 函数之of_property_count_elems_of_size 函数
⑨提取属性值的 OF 函数之一of_property_read_u32_array 函数
下面用函数把在设备树种的设备属性一一提取,比如/proc/devicetree 目录下backlight目录在设备树中的具体属性如下
backlight {
compatible = "pwm-backlight";
pwms = <&pwm1 0 5000000>;
brightness-levels = <0 4 8 16 32 64 128 255>;
default-brightness-level = <6>;
status = "okay";}
一、工作区
1、基本框架
2、头文件
二、编写代码
1、提取compatible属性
这里用到device_node与property结构体,of_find_node_by_path 与of_find_property函数
compatible参数是backlight在dtb中的属性之一
①device_node结构体
设备都是以节点的形式“挂”到设备树上的,因此要想获取这个设备的其他属性信息,必须先获取到这个设备的节点。 Linux 内核使用 device_node 结构体来描述一个节点,此结构体定义在文件 include/linux/of.h 中,定义如下:
②property结构体
节点的属性信息里面保存了驱动所需要的内容,因此对于属性值的提取非常重要, Linux 内核中使用结构体 property 表示属性,此结构体同样定义在文件 include/linux/of.h 中
③查找节点的 OF 函数之of_find_node_by_path 函数
of_find_node_by_path 函数通过路径来查找指定的节点,函数原型如下:
inline struct device_node *of_find_node_by_path(const char *path)
path:带有全路径的节点名,可以使用节点的别名,如“/backlight”是 backlight 这个节点的全路径
返回值: 找到的节点,如果为 NULL 表示查找失败
④提取属性值的 OF 函数之一of_find_property 函数
of_find_property 函数用于查找指定的属性,函数原型如下
property *of_find_property(const struct device_node *np,const char *name,int *lenp)
np:设备节点;name: 属性名字;lenp:属性值的字节数
返回值: 找到的属性
编译验证
这打印出来的属性值和节点的属性是一样的
2、提取status属性
这里用到of_property_read_string 函数
⑤提取属性值的 OF 函数之of_property_read_string 函数
of_property_read_string 函数用于读取属性中字符串值,函数原型如下
int of_property_read_string(struct device_node *np,const char *propname,
const char **out_string)
np:设备节点;proname: 要读取的属性名字;out_string:读取到的字符串值
返回值: 0,读取成功,负值,读取失败
编译验证
这打印出来的属性值和节点的属性是一样的
3、获取数组的数据属性
这里用到of_property_read_u32 函数和of_property_count_elems_of_size 函数
⑥提取属性值的 OF 函数之of_property_read_u32 函数
有些属性只有一个整形值,这函数就是用于读取这种只有一个整形值的属性,只需要把函数名后缀修改,即可分别用于读取 u8、 u16、 u32 和 u64 类型属性值,函数原型如下:
int of_property_read_u32(const struct device_node *np,
const char *propname,
u32 *out_value
np:设备节点;proname: 要读取的属性名字;out_value:读取到的数组值。
返回值: 0,读取成功,负值,读取失败, -EINVAL 表示属性不存在, -ENODATA 表示没有要读取的数据, -EOVERFLOW 表示属性值列表太小。
⑦提取属性值的 OF 函数之of_property_count_elems_of_size 函数
of_property_count_elems_of_size 函数用于获取属性中元素的数量,比如 reg 属性值是一个
数组,那么使用此函数可以获取到这个数组的大小,此函数原型如下
int of_property_count_elems_of_size(const struct device_node *np,
const char *propname,
int elem_size)
np:设备节点;proname: 需要统计元素数量的属性名字;elem_size:元素长度;
返回值: 得到的属性元素数量。
编译验证
这打印出来的俩个属性值和节点的属性是一样的
4、把数组中数据打印出来
这使用申请内存kmalloc,释放内存kfree和of_property_read_u32_array 函数
⑧kmalloc和kfree
需要头文件#include<linux/slab.h>
kmalloc原型如下
void *kmalloc(size_t size, int flags);
参数size是要分配的块的大小,flags参数, 分配标志。
这里的GFP_KERNEL标志是内核内存的正常分配. 可能睡眠.
kfree原型如下
kfree(const void *);
负责释放由kmalloc分配出来的内存块,指针参数指向要被释放的内存
⑨提取属性值的 OF 函数之一of_property_read_u32_array 函数
修改”u类型“分别对应读取属性中 u8、 u16、 u32 和 u64 类型的数组数据,比如大多数的 reg 属性都是数组数据,可以使用这 4 个函数一次读取出 reg 属性中的所有数据。这四个函数的原型如下:
int of_property_read_u32_array(const struct device_node *np,const char *propname,
u32 *out_values,
size_t sz)
np:设备节点,proname: 要读取的属性名字
out_value:读取到的数组值,分别为 u8、 u16、 u32 和 u64。
sz: 要读取的数组元素数量
返回值: 0,读取成功,负值,读取失败, -EINVAL 表示属性不存在, -ENODATA 表示没有要读取的数据, -EOVERFLOW 表示属性值列表太小
编译验证