RK3568驱动指南|第七篇 设备树-第67章 of操作函数实验:获取属性

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工智能应用。RK3568 支持安卓 11 和 linux 系统,主要面向物联网网关、NVR 存储、工控平板、工业检测、工控盒、卡拉 OK、云终端、车载中控等行业。


【公众号】迅为电子

【粉丝群】824412014(加群获取驱动文档+例程)

【视频观看】嵌入式学习之Linux驱动(第七期_设备树_全新升级)_基于RK3568

【购买链接】迅为RK3568开发板瑞芯微Linux安卓鸿蒙ARM核心板人工智能AI主板


第67章 of操作函数实验:获取属性

67.1 of操作:获取属性

67.1.1 of_find_property函数

of_find_property函数用于在设备树中查找节点 下具有指定名称的属性。如果找到了该属性,可以通过返回的属性结构体指针进行进一步的操作,比如获取属性值、属性长度等。

函数原型:

struct property *of_find_property(const struct device_node *np, const char *name, int *lenp)

头文件:

#include <linux/of.h>

函数作用:

该函数用于在节点 np 下查找指定名称 name 的属性。

函数参数:

np: 要查找的节点。

name: 要查找的属性的属性名。

lenp: 一个指向整数的指针,用于接收属性值的字节数。

返回值:

如果成功找到了指定名称的属性,则返回对应的属性结构体指针 struct property *;如果未找到,则返回 NULL。

67.1.2 of_property_count_elems_of_size函数

该函数在设备树中的设备节点下查找指定名称的属性,并获取该属性中元素的数量。调用该函数可以用于获取设备树属性中某个属性的元素数量,比如一个字符串列表的元素数量或一个整数数组的元素数量等。

函数原型:

int of_property_count_elems_of_size(const struct device_node *np, const char *propname, int elem_size)

头文件:

#include <linux/of.h>

函数作用:

该函数用于获取属性中指定元素的数量。

函数参数和返回值:

np: 设备节点。

propname: 需要获取元素数量的属性名。

elem_size: 单个元素的尺寸。

返回值:

如果成功获取了指定属性中元素的数量,则返回该数量;如果未找到属性或属性中没有元素,则返回 0。

 

67.1.3 of_property_read_u32_index函数

该函数在设备树中的设备节点下查找指定名称的属性,并获取该属性在给定索引位置处的 u32 类型的数据值。

这个函数通常用于从设备树属性中读取特定索引位置的整数值。通过指定属性名和索引,可以获取属性中指定位置的具体数值。

函数原型:

int of_property_read_u32_index(const struct device_node *np, const char *propname, u32 index, u32 *out_value)

头文件:

#include <linux/of.h>

函数作用:

该函数用于从指定属性中获取指定索引位置的 u32 类型的数据值。

函数参数:

np: 设备节点。

propname: 要读取的属性名。

index: 要读取的属性值在属性中的索引,索引从 0 开始。

out_value: 用于存储读取到的值的指针。

返回值:

如果成功读取到了指定属性指定索引位置的 u32 类型的数据值,则返回 0;如果未找到属性或读取失败,则返回相应的错误码。

67.1.4 of_property_read_u64_index函数

该函数在设备树中的设备节点下查找指定名称的属性,并获取该属性在给定索引位置处的 u64 类型的数据值。

这个函数通常用于从设备树属性中读取特定索引位置的 64 位整数值。通过指定属性名和索引,可以获取属性中指定位置的具体数值。

函数原型:

static inline int of_property_read_u64_index(const struct device_node *np, const char *propname, u32 index, u64 *out_value)

头文件:

#include <linux/of.h>

函数作用:

该函数用于从指定属性中获取指定索引位置的 u64 类型的数据值。

函数参数和返回值:

np: 设备节点。

propname: 要读取的属性名。

index: 要读取的属性值在属性中的索引,索引从 0 开始。

out_value: 用于存储读取到的值的指针。

返回值:

如果成功读取到了指定属性指定索引位置的 u64 类型的数据值,则返回 0;如果未找到属性或读取失败,则返回相应的错误码。

67.1.5 of_property_read_variable_u32_array函数

该函数用于从设备树中读取指定属性名的变长数组。通过提供设备节点、属性名和输出数组的指针,可以将设备树中的数组数据读取到指定的内存区域中。同时,还需要指定数组的最小大小和最大大小,以确保读取到的数组符合预期的大小范围。

函数原型:

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 数组。

函数参数和返回值:

np: 设备节点。

propname: 要读取的属性名。

out_values: 用于存储读取到的 u8 数组的指针。

SZ_min: 数组的最小大小。

SZ_max: 数组的最大大小。

返回值:

如果成功读取到了指定属性的 u8 数组,则返回数组的大小。如果未找到属性或读取失败,则返回相应的错误码。

 上面介绍的函数用于从指定属性中读取变长的 u32 数组,下面是另外三个读取其他数组大小的函数:

这里给出了四个函数,用于从设备树中读取数组类型的属性值:

从指定属性中读取变长的 u8 数组:

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)

从指定属性中读取变长的 u16 数组:

int of_property_read_variable_u16_array(const struct device_node *np, const char *propname, u16 *out_values, size_t SZ_min, size_t SZ_max)

从指定属性中读取变长的 u64 数组:

int of_property_read_variable_u64_array(const struct device_node *np, const char *propname, u64 *out_values, size_t SZ_min, size_t SZ_max)

67.1.6 of_property_read_string函数

该函数在设备树中的设备节点下查找指定名称的属性,并获取该属性的字符串值,最后返回读取到的字符串的指针,通常用于从设备树属性中读取字符串值。通过指定属性名,可以获取属性中的字符串数据。

函数原型:

static inline int of_property_read_string(const struct device_node *np, const char *propname, const char **out_string)

头文件:

#include <linux/of.h>

函数作用:

该函数用于从指定属性中读取字符串。

函数参数:

np: 设备节点。

propname: 要读取的属性名。

out_string: 用于存储读取到的字符串的指针。

返回值:

如果成功读取到了指定属性的字符串,则返回 0;如果未找到属性或读取失败,则返回相应的错误码。

67.2 实验程序编写

本实验驱动对应的网盘路径为:iTOP-RK3568开发板【底板V1.7版本】\03_【iTOP-RK3568开发板】指南教程\02_Linux驱动配套资料\04_Linux驱动例程\56_of_02

本小节驱动程序是由65章驱动程序修改而来,由于本章节获取设备树属性的函数需要在查找到设备树节点的前提下使用,所以在下面的程序中,先在probe函数中添加获取设备树节点的相关内容,然后添加了本章节学习的of操作相关代码,用来获取设备树节点相关属性。

编写完成的platform_driver.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, "reg", 4);printk("reg num is %d\n", num);// 读取reg属性的值of_property_read_u32_index(mydevice_node, "reg", 0, &value_u32);of_property_read_u64_index(mydevice_node, "reg", 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, "reg", 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="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);MODULE_LICENSE("GPL");
MODULE_AUTHOR("topeet");

67.3 运行测试

67.3.1 编译驱动程序

export ARCH=arm64#设置平台架构
export CROSS_COMPILE=aarch64-linux-gnu-#交叉编译器前缀
obj-m += platform_driver.o    #此处要和你的驱动源文件同名
KDIR :=/home/topeet/Linux/linux_sdk/kernel    #这里是你的内核目录                                                                                                                            
PWD ?= $(shell pwd)
all:make -C $(KDIR) M=$(PWD) modules    #make操作
clean:make -C $(KDIR) M=$(PWD) clean    #make clean操作

对于Makefile的内容注释已在上图添加,保存退出之后,来到存放platform_driver.c和Makefile文件目录下,如下图(图67-1)所示:

图 67-1

然后使用命令“make”进行驱动的编译,编译完成如下图(图67-2)所示:

图 67-2

编译完生成platform_driver.ko目标文件,如下图(图67-3)所示:

图 67-3

至此驱动模块就编译成功了。

67.3.2 运行测试

在进行实验之前,首先要确保开发板烧写的是我们在65.2.1小节中编译出来的boot.img,开发板启动之后,使用以下命令进行驱动模块的加载,如下图(图67-4)所示:

insmod platform_driver.ko

图 67-4

可以看到总共有8个打印,第一个打印表示查找到的节点为myLed,接下来的打印都是使用该节点进行的属性查找。第二个打印表示查找的属性名为“compatible”,第三个打印表示查找的reg属性数量为2,第四个和第五个分别表示读取到的32位和64位的reg属性值,第6个和第7个打印表示reg的第一个属性值和第二个属性值,第8个打印表示compatite属性值为“my devicetree”。

然后使用以下命令进行驱动模块的卸载,如下图(图67-5)所示:

rmmod platform_driver.ko

 

图 67-5

至此,使用of操作函数获取设备树节点实验就完成了。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/190120.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vmware workstation pro 17.5 安装 macos 13.5.2 虚拟机超详细图文教程

前言 本文很细&#xff0c;甚至有点墨迹&#xff0c;主要为了方便从来没用过 vmware 的新人&#xff0c;其实大部分步骤和正常安装虚拟机没有区别&#xff0c;详细贴图以方便大家对比细节 参考文章 感谢大佬们的无私分享 https://blog.csdn.net/qq_19731521/article/details…

Python每日一练@前言

Python每日一练前言 导读 人生苦短&#xff0c;我用Python 大家好&#xff0c;我是鹅不糊涂 欢迎大家来到Python每日一练 好处 加强编程能力: 每日一练可以帮助提升编程技能&#xff0c;通过解决各种编程问题和挑战&#xff0c;你能够不断锻炼自己的逻辑思维和解决问题的能力…

互联网医院牌照|智慧医疗离不开牌照办理

互联网医院牌照是由卫生健康行政部门颁布的&#xff0c;所有材料审核通过后&#xff0c;相关部门授予《医疗机构执业许可证》&#xff0c;取得牌照后才有开展互联网诊疗活动的资质&#xff0c;但开展线上问诊也需要向发证机关提出申请&#xff0c;下面小编就给大家讲解下互联网…

4.1指令系统-指令格式

现代计算机的结构 计算机的工作过程 指令的定义 指令&#xff08;又称机器指令&#xff09;&#xff1a; 是指示计算机执行某种操作的命令&#xff0c;是计算机运行的最小功能单位。 一台计算机的所有指令的集合构成改机指令系统&#xff0c;也称为指令集。 注意&#xff1…

4.6 Windows驱动开发:内核遍历进程VAD结构体

在上一篇文章《内核中实现Dump进程转储》中我们实现了ARK工具的转存功能&#xff0c;本篇文章继续以内存为出发点介绍VAD结构&#xff0c;该结构的全程是Virtual Address Descriptor即虚拟地址描述符&#xff0c;VAD是一个AVL自平衡二叉树&#xff0c;树的每一个节点代表一段虚…

AlphaControls控件TsDBCombobox出错:访问违规

日常使用AlphaControls控件TsDBCombobox&#xff0c;作为数据变化数据的控件。通常正常使用&#xff0c;一日 发现&#xff0c;出现以下错误&#xff1a; 控件访问违规的源代码&#xff0c;出错代码&#xff1a; function TacMainWnd.CallPrevWndProc(const Handle: hwnd; co…

LrC ACR :优化的 AI 天空蒙版

在 Lightroom Classic 和 Adobe Camera Raw 中创建基于 AI 技术的天空蒙版时&#xff0c;可能由于底层算法的原因&#xff0c;选中的天空蒙版在边缘处有晕开的现象&#xff08;又称为“出血” Bleed&#xff09;&#xff0c;从而导致天空蒙版不是很精准。 本文提供了一种特殊方…

无需公网IP,使用MCSM面板一键搭建我的世界Minecraft服务器联机游戏

文章目录 前言1.Mcsmanager安装2.创建Minecraft服务器3.本地测试联机4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射内网端口 5.远程联机测试6. 配置固定远程联机端口地址6.1 保留一个固定TCP地址6.2 配置固定TCP地址 7. 使用固定公网地址远程联机 前言 MCSManager是一个…

Ghidra逆向工具配置 MacOS 的启动台显示(Python)

写在前面 通过 ghidra 工具, 但是只能用命令行启动, 不太舒服, 写个脚本生成 MacOS 的 app 格式并导入启动台. 不算复杂, 主要是解析包的一些元信息还有裁剪软件图标(通过 MacOS 自带的 API) 脚本 #!/opt/homebrew/bin/python3import os import re import subprocess as sp…

软件质量保护与测试(第2版)学习总结第十三章 集成测试

很多人都认为微软是一家软件开发公司&#xff0c;事实上我们是一家软件测试公司。 ---比尔盖茨 集成测试是在单元测试的基础上将多个模块组合在一起进行测试的过程。 13.1.1 区别 单元测试主要关注模块内部&#xff0c;系统测试则是在用户的角度来评价系统&#xff…

【Python3】【力扣题】303. 区域和检索 - 数组不可变

【力扣题】题目描述&#xff1a; 【Python3】代码&#xff1a; 1、解题思路&#xff1a;从列表中获取指定下标的所有元素&#xff0c;求和。 知识点&#xff1a;列表[start:end]&#xff1a;切片。从列表中获取起始下标start&#xff08;含&#xff09;到结束下标end&#xf…

【漏洞复现】​金和OA存在任意文件读取漏洞

漏洞描述 金和OA协同办公管理系统C6软件(简称金和OA),本着简单、适用、高效的原则,贴合企事业单位的实际需求,实行通用化、标准化、智能化、人性化的产品设计,充分体现企事业单位规范管理、提高办公效率的核心思想,为用户提供一整套标准的办公自动化解决方案,以帮助企…