RK3568驱动指南|第八篇 设备树插件-第80章 注册attribute实验

news/2025/1/15 8:46:45/

瑞芯微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主板


第80章 注册attribute实验

   在前面的几章实验中,我们编写驱动程序,实现了注册ConfigFS子系统,注册group容器,支持使用mkdir命令创建item,完善了drop和release函数的功能。在之前的实验中,我们成功创建了item,但是item下面没有创建属性和操作项,那么本章节我们来学习如何注册属性。

 

80.1实验程序的编写

80.1.1 驱动程序编写

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

本章编写的驱动文件在上个章节驱动文件的基础上进行编写。驱动实现在item目录下生成属性read和write,并对read属性进行读取和对write属性进行写入。编写完成的attr.c代码如下所示:

#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/configfs.h>// 定义一个名为"mygroup"的config_group结构体
static struct config_group mygroup;// 自定义的配置项结构体
struct myitem
{struct config_item item;int size;void *addr;
};// 配置项释放函数
void myitem_release(struct config_item *item)
{struct myitem *myitem = container_of(item, struct myitem, item);kfree(myitem);printk("%s\n", __func__);
};// 读取配置项内容的回调函数
ssize_t myread_show(struct config_item *item, char *page)
{struct myitem *myitem = container_of(item, struct myitem, item);memcpy(page, myitem->addr, myitem->size);printk("%s\n", __func__);return myitem->size;
};// 写入配置项内容的回调函数
ssize_t mywrite_store(struct config_item *item, const char *page, size_t size)
{struct myitem *myitem = container_of(item, struct myitem, item);myitem->addr = kmemdup(page, size, GFP_KERNEL);myitem->size = size;printk("%s\n", __func__);return myitem->size;
};// 创建只读配置项
CONFIGFS_ATTR_RO(my, read);
// 创建只写配置项
CONFIGFS_ATTR_WO(my, write);// 配置项属性数组
struct configfs_attribute *my_attrs[] = {&myattr_read,&myattr_write,NULL,
};// 配置项操作结构体
struct configfs_item_operations myitem_ops = {.release = myitem_release,
};// 配置项类型结构体
static struct config_item_type mygroup_item_type = {.ct_owner = THIS_MODULE,.ct_item_ops = &myitem_ops,.ct_attrs = my_attrs,
};// 创建配置项函数
struct config_item *mygroup_make_item(struct config_group *group, const char *name)
{struct myitem *myconfig_item;printk("%s\n", __func__);myconfig_item = kzalloc(sizeof(*myconfig_item), GFP_KERNEL);config_item_init_type_name(&myconfig_item->item, name, &mygroup_item_type);return &myconfig_item->item;
}// 删除配置项函数
void mygroup_delete_item(struct config_group *group, struct config_item *item)
{struct myitem *myitem = container_of(item, struct myitem, item);config_item_put(&myitem->item);printk("%s\n", __func__);
}// 配置组操作结构体
struct configfs_group_operations mygroup_ops = {.make_item = mygroup_make_item,.drop_item = mygroup_delete_item,
};// 配置项类型结构体
static const struct config_item_type mygroup_config_item_type = {.ct_owner = THIS_MODULE,.ct_group_ops = &mygroup_ops,
};// 配置项类型结构体
static const struct config_item_type myconfig_item_type = {.ct_owner = THIS_MODULE,.ct_group_ops = NULL,
};// 定义一个configfs_subsystem结构体实例"myconfigfs_subsystem"
static struct configfs_subsystem myconfigfs_subsystem = {.su_group = {.cg_item = {.ci_namebuf = "myconfigfs",.ci_type = &myconfig_item_type,},},
};// 模块的初始化函数
static int myconfig_group_init(void)
{// 初始化配置组config_group_init(&myconfigfs_subsystem.su_group);// 注册子系统configfs_register_subsystem(&myconfigfs_subsystem);// 初始化配置组"mygroup"config_group_init_type_name(&mygroup, "mygroup", &mygroup_config_item_type);// 在子系统中注册配置组"mygroup"configfs_register_group(&myconfigfs_subsystem.su_group, &mygroup);return 0;
}// 模块退出函数
static void myconfig_group_exit(void)
{// 注销子系统configfs_unregister_subsystem(&myconfigfs_subsystem);
}module_init(myconfig_group_init); // 指定模块的初始化函数
module_exit(myconfig_group_exit); // 指定模块的退出函数MODULE_LICENSE("GPL");   // 模块使用的许可证
MODULE_AUTHOR("topeet"); // 模块的作者

80.2 运行测试

80.2.1 编译驱动程序

在上一小节中的attr.c代码同一目录下创建 Makefile 文件,Makefile 文件内容如下所示:

export ARCH=arm64#设置平台架构
export CROSS_COMPILE=aarch64-linux-gnu-#交叉编译器前缀
obj-m += attr.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的内容注释已在上图添加,保存退出之后,来到存放attr.c和Makefile文件目录下,如下图(图80-1)所示:

图 80-1

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

图 80-2

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

至此驱动模块就编译成功了,接下来进行测试。

80.2.2 运行测试

开发板启动之后,使用以下命令进行驱动模块的加载,如下图(图80-4)所示:

insmod attr.ko

图80-4

驱动加载之后,我们进入/sys/kernel/config目录下,可以看到注册生成的myconfigfs子系统,如下图(图80-5)所示:

图80-5

然后我们进入注册生成的myconfigfs子系统,如下图(图 80-6)所示,可以看到注册生成的mygroup容器。

图 80-6

然后输入“mkdir test”命令创建config_item,如下图(图 80-7)所示,创建成功之后,打印“mygroup_make_item”。

图 80-7

然后进入到test目录下,如下图(图 80-8)所示。有生成的属性:read和write

图 80-8

我们输入以下命令对属性进行读写操作,如下图(图 80-9)所示:

cat read

echo 1 > write

 

图 80-9

在上图中,我们分别对属性read和write进行读写操作后,分别打印“myread_show”和“mywrite_store”。

输入“rmdir test”命令删除item,如下图(图 80-10)所示:

图 80-10

最后可以使用以下命令进行驱动的卸载,如下图(图80-11)所示:

rmmod attr

 

图 80-11

至此,注册attribute实验就完成了。



http://www.ppmy.cn/news/1278002.html

相关文章

测试:DFX DFS

DFX DFX&#xff08;Design for X&#xff09;指的是一种设计方法&#xff0c;它关注于产品的非功能性属性&#xff0c;旨在提高产品的整体竞争力和生命周期价值。这里的“X”代表产品生命周期中的某个环节或特性&#xff0c;例如供应、安装、维护等&#xff0c;也可以是影响产…

ICC2:Less than minimum edge length和Concave convex edge enclosure

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 首先,要介绍一下这两种drc Less than minimum edge length对应的tf rule如下: 而Concave convex edge enclosure对应图示和tf 规则如下,可

美易官方:美股空头今年损失1780亿美元

今年&#xff0c;美股市场的空头们遭遇了前所未有的打击。据统计&#xff0c;美股空头在今年损失了高达1780亿美元&#xff0c;创下了历史新高。这一数字令人震惊&#xff0c;因为空头通常是股市的投资者&#xff0c;他们通过借入股票并立即卖出&#xff0c;期待在股价下跌时再…

拥抱鸿蒙 - 在展讯T606平台上的探索与实践

前 言 自OpenHarmony 问世后受到了社会各界的广泛关注&#xff0c;OpenHarmony 的生态系统在如火如荼的发展。 酷派作为一家积极拥抱变化的公司&#xff0c;经过一段时间的探索与实践&#xff0c;成功实现将OpenHarmony 系统接入到展讯平台上&#xff0c;我们相信这是一个重要…

paddle 53 基于PaddleClas2.5训练自己的数据(训练|验证|推理|c++ 部署)

项目地址:https://github.com/PaddlePaddle/PaddleClas 文档地址:https://paddleclas.readthedocs.io/zh-cn/latest/tutorials/install.html paddleclas的最新项目已经不适应其官网的使用案例(训练、验证、推理命令均不适用),为此博主对其进行命令重新进行修改。同时padd…

Sentinel 流量治理组件教程

前言 官网首页&#xff1a;home | Sentinel (sentinelguard.io) 随着微服务的流行&#xff0c;服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件&#xff0c;主要以流量为切入点&#xff0c;从流量路由、流量控制、流量整形…

在Portainer创建Nginx容器并部署Web静态站点实现公网访问

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《Linux》《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;…

Spring事务回滚规则,是否只读,超时时间,事务失效

一:回滚规则 默认情况下&#xff0c;事务只有遇到运行期异常(RuntimeExcertion的子类)以及 Error 时才会回滚&#xff0c;在遇到检查型(Checked Exception)异常时不会回滚。像 1/0&#xff0c;空指针这些是RuntimeException&#xff0c;而IOException 则算是 Checked Exception…