<linux/of_device.h>头文件

文章讲述了<linux/of_device.h>头文件在Linux内核中的作用,它是处理设备树的关键,允许驱动程序根据设备树信息动态配置硬件。通过包含此头文件,开发者可以使用提供的函数和数据结构查找、读取和操作设备树节点,实现设备的自动识别和配置。文章列举了如of_find_node_by_name、of_property_read_系列函数等在设备树操作中的应用,并强调了遵循设备树约定和错误处理的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<linux/of_device.h> 是 Linux 内核中的头文件,提供了处理设备树(Device Tree)的相关功能。设备树是一种用于描述硬件设备信息的数据结构,用于在 Linux 内核中动态识别和配置硬件设备。

该头文件中包含了一些与设备树相关的函数和数据结构,用于在 Linux 内核中操作设备树节点的属性、子节点、驱动和设备等信息。这些函数和数据结构可以帮助开发者在设备树中添加、修改、删除和查询节点的属性和信息,以便于设备驱动程序在运行时根据设备树的描述来识别和配置硬件设备。

使用 <linux/of_device.h> 头文件可以在 Linux 内核驱动程序中实现对设备树的操作,从而实现设备的自动识别和配置。这对于嵌入式系统和嵌入式设备驱动开发非常有用,可以方便地在设备树中描述硬件设备,并在 Linux 内核中通过相应的函数和数据结构来访问和配置设备树中的信息。

当使用 <linux/of_device.h> 头文件时,需要注意以下步骤:

  1. 包含头文件:在需要使用设备树相关功能的 Linux 内核驱动程序中,使用 #include <linux/of_device.h> 指令来包含该头文件。

  2. 获取设备节点信息:

    使用函数 of_find_node_by_name() 可以根据节点的名称来查找设备树节点,并返回相应的设备节点指针。例如:
    struct device_node *node;
    node = of_find_node_by_name(NULL, "my_device_node");
    if (node) {
        // 处理设备节点信息
    }
    

    使用函数 of_find_node_by_type() 可以根据节点的类型来查找设备树节点,并返回相应的设备节点指针。例如:

    struct device_node *node;
    node = of_find_node_by_type(NULL, "my_device_type");
    if (node) {
        // 处理设备节点信息
    }
    

    使用函数 of_find_node_by_path() 可以根据节点的路径来查找设备树节点,并返回相应的设备节点指针。例如:

    struct device_node *node;
    node = of_find_node_by_path("/my_device_node");
    if (node) {
        // 处理设备节点信息
    }
    

  3. 获取节点属性值: 使用函数 of_property_read_bool()of_property_read_u32()of_property_read_string() 等函数来读取设备节点的属性值。这些函数可以根据属性的名称和类型,将属性值读取到指定的变量中,以便进一步处理和配置设备。例如:

    bool my_bool;
    u32 my_u32;
    char my_string[32];
    
    if (of_property_read_bool(node, "my_bool_property"))
        my_bool = true;
    if (of_property_read_u32(node, "my_u32_property", &my_u32) == 0)
        // 处理 my_u32 的值
    if (of_property_read_string(node, "my_string_property", my_string, sizeof(my_string)) >= 0)
        // 处理 my_string 的值
    

  4. 遍历子节点: 使用函数 of_for_each_child() 可以遍历设备节点的所有子节点,通过传入回调函数来处理每个子节点的信息。例如:

    struct device_node *child;
    of_for_each_child(node, child) {
        // 处理 child 节点信息
    }
    

    使用函数 of_child_by_index() 可以根据子节点的索引来获取特定位置的子节点的指针。例如:

    struct device_node *child;
    child = of_child_by_index(node, 0);
    if (child) {
        // 处理 child 节点信息
    }
    

    使用函数 of_get_next_child() 可以遍历设备节点的子节点链表,通过传入当前子节点的指针来获取下一个子节点的指针。例如:

    struct device_node *child;
    child = of_get_next_child(node, NULL) {
    // 处理 child 节点信息
    }
    ```

    这些是使用 <linux/of_device.h> 头文件时的一些基本步骤,可以根据实际需求和设备树结构来使用其他相关函数和数据结构进行更复杂的设备树操作。需要注意的是,使用设备树相关功能时,应该遵循 Linux 内核的设备树约定和最佳实践,并进行错误检查和错误处理,以确保设备树操作的正确性和稳定性。

 

总而言之,<linux/of_device.h> 头文件是用于在 Linux 内核中处理设备树的头文件。它提供了一些用于解析和处理设备树节点信息的函数和数据结构,使得 Linux 内核驱动可以从设备树中获取设备信息,从而实现设备的初始化和配置。使用 <linux/of_device.h> 头文件时,通常需要遵循以下步骤:

  1. 在驱动程序中包含 <linux/of_device.h> 头文件。

  2. 使用 of_match_table 定义设备树节点和驱动程序之间的匹配规则,以便内核可以自动将设备树节点与相应的驱动程序关联起来。

  3. 在驱动程序的初始化函数中,使用 of_find_matching_node 函数从设备树中查找匹配的节点,并使用 of_property_read_* 函数读取节点的属性信息。

  4. 根据设备节点的属性信息,进行设备的初始化和配置,如设置设备寄存器、注册中断处理函数等。

  5. 可选地,可以使用 of_for_each_child 函数遍历设备节点的子节点,以处理更复杂的设备树结构。

  6. 应该遵循 Linux 内核的设备树约定和最佳实践,并进行错误检查和错误处理,以确保设备树操作的正确性和稳定性。

综上所述,<linux/of_device.h> 头文件提供了处理设备树的功能,使得 Linux 内核驱动可以从设备树中获取设备信息并进行初始化和配置,从而实现设备的驱动和管理。

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/kernel.h> #include <linux/proc_fs.h> #include <linux/of.h> #include <linux/of_device.h> static int ab_system_status_value = 0; static int ab_sync_status_value = 0; static int ota_status_value = 0; // ab_system_status节点读写 static ssize_t ab_system_status_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { char buffer[32]; int len = snprintf(buffer, sizeof(buffer), "%d\n", ab_system_status_value); return simple_read_from_buffer(buf, count, ppos, buffer, len); } static ssize_t ab_system_status_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char input[32]; int value; if (count > sizeof(input) - 1) return -EINVAL; if (copy_from_user(input, buf, count)) return -EFAULT; input[count] = '\0'; if (sscanf(input, "%d", &value) == 1) { ab_system_status_value = value; return count; } return -EINVAL; } // ab_sync_status节点读写 static ssize_t ab_sync_status_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { char buffer[32]; int len = snprintf(buffer, sizeof(buffer), "%d\n", ab_sync_status_value); return simple_read_from_buffer(buf, count, ppos, buffer, len); } static ssize_t ab_sync_status_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char input[32]; int value; if (count > sizeof(input) - 1) return -EINVAL; if (copy_from_user(input, buf, count)) return -EFAULT; input[count] = '\0'; if (sscanf(input, "%d", &value) == 1) { ab_sync_status_value = value; return count; } return -EINVAL; } // ota_status节点读写 static ssize_t ota_status_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { char buffer[32]; int len = snprintf(buffer, sizeof(buffer), "%d\n", ota_status_value); return simple_read_from_buffer(buf, count, ppos, buffer, len); } static ssize_t ota_status_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char input[32]; int value; if (count > sizeof(input) - 1) return -EINVAL; if (copy_from_user(input, buf, count)) return -EFAULT; input[count] = '\0'; if (sscanf(input, "%d", &value) == 1) { ota_status_value = value; return count; } return -EINVAL; } // proc节点操作结构体 static const struct proc_ops ab_system_status_ops = { .proc_read = ab_system_status_read, .proc_write = ab_system_status_write, }; static const struct proc_ops ab_sync_status_ops = { .proc_read = ab_sync_status_read, .proc_write = ab_sync_status_write, }; static const struct proc_ops ota_status_ops = { .proc_read = ota_status_read, .proc_write = ota_status_write, }; // 设备树匹配表 static const struct of_device_id fibo_ab_ota_of_match[] = { { .compatible = "fibocom,fibo_ab_ota", }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, fibo_ab_ota_of_match); // probe函数 static int fibo_ab_ota_probe(struct platform_device *pdev) { pr_info("fibo_ab_ota_probe called\n"); if (!proc_create("ab_system_status", 0664, NULL, &ab_system_status_ops)) { pr_err("Failed to create ab_system_status proc entry\n"); return -ENOMEM; } if (!proc_create("ab_sync_status", 0664, NULL, &ab_sync_status_ops)) { pr_err("Failed to create ab_sync_status proc entry\n"); remove_proc_entry("ab_system_status", NULL); return -ENOMEM; } if (!proc_create("ota_status", 0664, NULL, &ota_status_ops)) { pr_err("Failed to create ota_status proc entry\n"); remove_proc_entry("ab_system_status", NULL); remove_proc_entry("ab_sync_status", NULL); return -ENOMEM; } return 0; } // remove函数 static int fibo_ab_ota_remove(struct platform_device *pdev) { pr_info("fibo_ab_ota_remove called\n"); remove_proc_entry("ab_system_status", NULL); remove_proc_entry("ab_sync_status", NULL); remove_proc_entry("ota_status", NULL); return 0; } // 平台驱动结构体 static struct platform_driver fibo_ab_ota_driver = { .probe = fibo_ab_ota_probe, .remove = fibo_ab_ota_remove, .driver = { .name = "fibo_ab_ota", .owner = THIS_MODULE, .of_match_table = fibo_ab_ota_of_match, }, }; static int __init fibo_ab_ota_init(void) { return platform_driver_register(&fibo_ab_ota_driver); } static void __exit fibo_ab_ota_exit(void) { platform_driver_unregister(&fibo_ab_ota_driver); } module_init(fibo_ab_ota_init); module_exit(fibo_ab_ota_exit); MODULE_DESCRIPTION("fibo ab ota Module"); MODULE_AUTHOR("qujunyang"); MODULE_LICENSE("GPL"); 请你将节点改为生成在/sys/class下
最新发布
08-12
make -C /lib/modules/3.10.0-1160.119.1.el7.x86_64/build M=/home/user/1/core_test_folder modules make[1]: Entering directory '/usr/src/kernels/3.10.0-1160.119.1.el7.x86_64' CC [M] /home/user/1/core_test_folder/icmp_ping_monitor.o In file included from include/linux/cache.h:4:0, from include/linux/time.h:4, from include/linux/stat.h:18, from include/linux/module.h:10, from /home/user/1/core_test_folder/icmp_ping_monitor.c:1: /home/user/1/core_test_folder/icmp_ping_monitor.c: 在函数‘ping_stat_show’中: include/linux/kernel.h:792:17: 警告:比较不相关的指针时缺少类型转换 [默认启用] (void) (&_min1 == &_min2); \ ^ /home/user/1/core_test_folder/icmp_ping_monitor.c:83:21: 附注:in expansion of macro ‘min’ for (i = 0; i < min(stats.count, MAX_ENTRIES); i++) { ^ /home/user/1/core_test_folder/icmp_ping_monitor.c: 在文件作用域: /home/user/1/core_test_folder/icmp_ping_monitor.c:100:21: 错误:变量‘ping_stat_fops’有初始值设定但类型不完全 static const struct proc_ops ping_stat_fops = { ^ /home/user/1/core_test_folder/icmp_ping_monitor.c:101:5: 错误:初始值设定项里有未知的字段‘proc_open’ .proc_open = ping_stat_open, ^ /home/user/1/core_test_folder/icmp_ping_monitor.c:101:5: 警告:结构初始值设定项中有多余元素 [默认启用] /home/user/1/core_test_folder/icmp_ping_monitor.c:101:5: 警告:(在‘ping_stat_fops’的初始化附近) [默认启用] /home/user/1/core_test_folder/icmp_ping_monitor.c:102:5: 错误:初始值设定项里有未知的字段‘proc_read’ .proc_read = seq_read, ^ /home/user/1/core_test_folder/icmp_ping_monitor.c:102:5: 警告:结构初始值设定项中有多余元素 [默认启用] /home/user/1/core_test_folder/icmp_ping_monitor.c:102:5: 警告:(在‘ping_stat_fops’的初始化附近) [默认启用] /home/user/1/core_test_folder/icmp_ping_monitor.c:103:5: 错误:初始值设定项里有未知的字段‘proc_lseek’ .proc_lseek = seq_lseek, ^ /home/user/1/core_test_folder/icmp_ping_monitor.c:103:5: 警告:结构初始值设定项中有多余元素 [默认启用] /home/user/1/core_test_folder/icmp_ping_monitor.c:103:5: 警告:(在‘ping_stat_fops’的初始化附近) [默认启用] /home/user/1/core_test_folder/icmp_ping_monitor.c:104:5: 错误:初始值设定项里有未知的字段‘proc_release’ .proc_release = single_release, ^ /home/user/1/core_test_folder/icmp_ping_monitor.c:104:5: 警告:结构初始值设定项中有多余元素 [默认启用] /home/user/1/core_test_folder/icmp_ping_monitor.c:104:5: 警告:(在‘ping_stat_fops’的初始化附近) [默认启用] /home/user/1/core_test_folder/icmp_ping_monitor.c: 在函数‘ping_stat_init’中: /home/user/1/core_test_folder/icmp_ping_monitor.c:121:15: 警告:从不兼容的指针类型赋值 [默认启用] nfho.hook = ping_hook; ^ /home/user/1/core_test_folder/icmp_ping_monitor.c:125:5: 错误:隐式声明函数‘nf_register_net_hook’ [-Werror=implicit-function-declaration] nf_register_net_hook(&init_net, &nfho); ^ /home/user/1/core_test_folder/icmp_ping_monitor.c:128:5: 警告:传递‘proc_create’的第 4 个参数时在不兼容的指针类型间转换 [默认启用] proc_entry = proc_create("ping_stats", 0, NULL, &ping_stat_fops); ^ In file included from /home/user/1/core_test_folder/icmp_ping_monitor.c:3:0: include/linux/proc_fs.h:30:38: 附注:需要类型‘const struct file_operations *’,但实参的类型为‘const struct proc_ops *’ static inline struct proc_dir_entry *proc_create( ^ /home/user/1/core_test_folder/icmp_ping_monitor.c:130:9: 错误:隐式声明函数‘nf_unregister_net_hook’ [-Werror=implicit-function-declaration] nf_unregister_net_hook(&init_net, &nfho); ^ cc1: some warnings being treated as errors scripts/Makefile.build:339: recipe for target '/home/user/1/core_test_folder/icmp_ping_monitor.o' failed make[2]: *** [/home/user/1/core_test_folder/icmp_ping_monitor.o] Error 1 Makefile:1316: recipe for target '_module_/home/user/1/core_test_folder' failed make[1]: *** [_module_/home/user/1/core_test_folder] Error 2 make[1]: Leaving directory '/usr/src/kernels/3.10.0-1160.119.1.el7.x86_64' Makefile:7: recipe for target 'default' failed make: *** [default] Error 2
08-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值