11、通过OF函数获取设备树节点实验
📢本篇将介绍通过OF函数获取设备树节点实验
一、获取获取设备树节点
① of_find_node_by_name
函数
作用:通过节点的名字直接找到对应的设备树节点。 用法:
- 如果设备树里某个节点的名字是“uart”,就可以用这个函数输入名字“uart”来找它。
- 返回值是找到的节点的指针(即
device_node
结构体)。
② of_find_node_by_path
函数
作用:通过节点的完整路径找到对应的节点。 用法:
- 设备树的路径像文件路径一样,比如
/soc/uart
,从根节点开始一步步到目标节点。 - 输入正确的路径字符串,函数会直接返回对应节点的指针。
- 适合已知确切路径的情况。
③ of_get_parent
函数
作用:获取某个节点的父节点(即上级节点)。 用法:
- 输入一个节点,函数返回它的直接父节点。
- 例如,如果节点A是节点B的子节点,调用
of_get_parent(B)
就能得到节点A。
④ of_get_next_child
函数
作用:遍历某个节点的所有子节点,逐个获取下一个子节点。 用法:
- 需要输入当前节点和上一个找到的子节点。
- 例如,已知某个子节点B,调用此函数会返回B之后的下一个子节点C。
- 常用于循环遍历所有子节点。
⑤ of_find_compatible_node
函数
作用:根据节点的“兼容性字符串”查找匹配的节点。 用法:
- 兼容性字符串通常包含设备的厂商和型号(例如
"vendor,uart-v1"
)。 - 输入起始节点和目标字符串,函数会从该节点开始搜索,返回第一个匹配的节点。
⑥ of_find_matching_node_and_match
函数
作用:用预定义的匹配表(of_device_id
)查找匹配的节点。 用法:
- 匹配表里列出多个兼容性字符串(例如驱动支持的设备列表)。
- 函数会遍历设备树,找到与匹配表中任意一条规则符合的节点,并返回它。
- 常用于驱动与设备树节点的自动绑定。
:::
总结
这些函数的核心目的都是在设备树中定位特定节点,通过名字、路径、父子关系、兼容性字符串或匹配表等方式,最终返回对应的 device_node
结构体。它们是驱动开发中获取设备信息或配置的关键工具。 :::
二、驱动程序
驱动代码:
C
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
#include <linux/of.h>
struct device_node *mydevice_node;
const struct of_device_id *mynode_match;
struct of_device_id mynode_of_match[] = {
{.compatible="my devicetree"},
{},
};
const char *value_compatible;
const int int_value;
// 平台设备的初始化函数
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);
// 通过节点路径查找设备树节点
mydevice_node = of_find_node_by_path("/myLed");
printk("mydevice node is %s\n", mydevice_node->name);
// 获取父节点
mydevice_node = of_get_parent(mydevice_node);
printk("myled's parent node is %s\n", mydevice_node->name);/
// 获取子节点
mydevice_node = of_get_next_child(mydevice_node, NULL);
printk("myled's sibling node is %s\n", mydevice_node->name);
// 使用compatible值查找节点
mydevice_node=of_find_compatible_node(NULL ,NULL, "my devicetree");
printk("mydevice node is %s\n" , mydevice_node->name);
//根据给定的of_device_id匹配表在设备树中查找匹配的节点
mydevice_node=of_find_matching_node_and_match(NULL , mynode_of_match, &mynode_match);
printk("mydevice node is %s\n" ,mydevice_node->name);
return 0;
of_property_read_string(mydevice_node, "compatible", &value_compatible);
printk("compatible value is %s\n", value_compatible); //my devicetree
of_property_read_u32(mydevice_node, "modetest", &int_value);
}
// 平台设备的移除函数
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="my 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);
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
105
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
105
设备树代码:
C++
myLed{
compatible = "my devicetree";
reg = <0xFDD60000 0x00000004>;
mode = "2";
modetest = 2;
};
1
2
3
4
5
6
2
3
4
5
6