13、通过OF函数获取属性*
📢本篇将介绍通过OF函数获取属性。
of相关函数:kernel/include/linux/of.h
一、获取获取属性
① of_find_property
函数
在设备树中查找某个节点下指定名称的属性。如果找到,返回该属性的指针,后续可用它获取属性值或属性长度等信息。
② of_property_count_elems_of_size
函数
在设备树中查找指定名称的属性,并计算该属性包含的元素数量。例如,可以统计一个整数数组中有多少个数,或字符串列表中有多少个条目。
③ of_property_read_u32_index
函数
根据属性名查找设备树中的属性,读取指定位置(索引)的32位整数值。例如,读取数组中第2个元素的数值。
④ of_property_read_u64_index
函数
类似 of_property_read_u32_index
,但读取的是64位整数值。
⑤ of_property_read_variable_u32_array
函数
从设备树中读取一个可变长度的32位整数数组。需要指定数组的最小和最大长度,确保读取的数据符合预期范围。
还有类似功能的函数可读取其他类型数组:
of_property_read_u8_array
:读取8位数组of_property_read_u16_array
:读取16位数组of_property_read_u64_array
:读取64位数组
⑥ of_property_read_string
函数
根据属性名查找设备树中的属性,返回该属性的字符串值。例如,读取设备名称或配置字符串。
:::
总结
这些函数帮助开发者从设备树中快速获取属性值:
查找属性:of_find_property
统计元素:of_property_count_elems_of_size
读取单个值:of_property_read_u32/u64_index
读取数组:of_property_read_variable_u32_array
等
读取字符串:of_property_read_string
每个函数都通过属性名和节点定位数据,简化了设备树信息的提取流程。 :::
二、实验
C++
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
#include <linux/of.h>
struct device_node *mydevice_node;
int num;
u32 value_u32;
u64 value_u64;
u32 out_value[2];
const char *value_compatible;
struct property *my_property;
// 平台设备的探测函数
static int my_platform_probe(struct platform_device *pdev)
{
printk(KERN_INFO "my_platform_probe: Probing platform device\n");
// 通过节点名称查找设备树节点
mydevice_node = of_find_node_by_name(NULL, "myLed");
printk("mydevice node is %s\n", mydevice_node->name);
// 查找compatible属性
my_property = of_find_property(mydevice_node, "compatible", NULL);
printk("my_property name is %s\n", my_property->name);
// 获取reg属性的元素数量
num = of_property_count_elems_of_size(mydevice_node, "regtest", 4);
printk("reg num is %d\n", num);
// 读取reg属性的值
of_property_read_u32_index(mydevice_node, "regtest", 0, &value_u32);
of_property_read_u64_index(mydevice_node, "regtest", 0, &value_u64);
printk("value u32 is 0x%X\n", value_u32);
printk("value u64 is 0x%llx\n", value_u64);
// 读取reg属性的变长数组
of_property_read_variable_u32_array(mydevice_node, "regtest", out_value, 1, 2);
printk("out_value[0] is 0x%X\n", out_value[0]);
printk("out_value[1] is 0x%X\n", out_value[1]);
// 读取compatible属性的字符串值
of_property_read_string(mydevice_node, "compatible", &value_compatible);
printk("compatible value is %s\n", value_compatible);
return 0;
}
// 平台设备的移除函数
static int my_platform_remove(struct platform_device *pdev)
{
printk(KERN_INFO "my_platform_remove: Removing platform device\n");
// 清理设备特定的操作
// ...
return 0;
}
const struct of_device_id of_match_table_id[] = {
{.compatible="rockchip,test_devicetree"},
};
// 定义平台驱动结构体
static struct platform_driver my_platform_driver = {
.probe = my_platform_probe,
.remove = my_platform_remove,
.driver = {
.name = "my_platform_device",
.owner = THIS_MODULE,
.of_match_table = of_match_table_id,
},
};
// 模块初始化函数
static int __init my_platform_driver_init(void)
{
int ret;
// 注册平台驱动
ret = platform_driver_register(&my_platform_driver);
if (ret) {
printk(KERN_ERR "Failed to register platform driver\n");
return ret;
}
printk(KERN_INFO "my_platform_driver: Platform driver initialized\n");
return 0;
}
// 模块退出函数
static void __exit my_platform_driver_exit(void)
{
// 注销平台驱动
platform_driver_unregister(&my_platform_driver);
printk(KERN_INFO "my_platform_driver: Platform driver exited\n");
}
module_init(my_platform_driver_init);
module_exit(my_platform_driver_exit);
MODULE_LICENSE("GPL");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
设备树:
c
myLed{
compatible = "rockchip,test_devicetree";
regtest = <0xFDD60000 0x00000004>;
mode = "2";
status = "okay";
};
1
2
3
4
5
6
2
3
4
5
6