瑞芯微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主板
第100章 在总线目录下创建属性文件实验
在上个章节中,我们成功注册了一个自定义总线,并为其创建了必要的数据结构和函数。现在,在本章节中,我们将继续深入了解总线的概念,并在总线目录下创建属性文件以扩展其功能。通过创建属性文件,我们可以为总线添加额外的信息和控制选项,以便与设备和驱动进行交互。这些属性文件可以用于读取总线的状态、设置参数或执行其他相关操作。让我们开始吧!
100.1 总线下创建属性API函数
bus_create_file() 函数用于在总线的 sysfs 目录下创建一个属性文件。
int bus_create_file(struct bus_type *bus, struct kobject *kobj, const struct attribute *attr);
参数说明:
- bus:指向总线类型结构体 struct bus_type的指针,表示要创建属性文件的总线。
- kobj:指向内核对象 struct kobject的指针,表示要在其下创建属性文件的内核对象。
- attr:指向属性 struct attribute的指针,表示要创建的属性文件的属性。
- 返回值:成功时返回 0,否则返回负数错误代码。
在调用 bus_create_file()函数之前,需要先定义好属性结构体 struct attribute,并将其相关字段填充好。通常,属性结构体会包含以下字段:
.name:属性的名称。
.mode:属性的访问权限。
示例用法:
struct bus_attribute mybus_attr = {
.attr = {
.name = "value",
.mode = 0664,
},
.show = mybus_show,
};
ret = bus_create_file(&mybus, &mydevice.kobj, &mybus_attr.attr);
上述示例代码创建了一个名为 "value" 的属性文件,并指定了访问权限为 0664。在创建属性文件时,还可以指定其他属性的回调函数,如 .show、.store等,以实现对属性值的读取和写入操作。
请注意,在使用 bus_create_file() 函数之前,需要确保总线对象和内核对象已正确初始化和注册。
接下来我们开始编写驱动文件,进行实验。
100.2实验程序的编写
100.2.1 驱动程序编写
本实验对应的网盘路径为:iTOP-RK3568开发板【底板V1.7版本】\03_【iTOP-RK3568开发板】指南教程\02_Linux驱动配套资料\04_Linux驱动例程\75_bus02\module。
我们编写驱动代码,定义了一个名为 "mybus" 的总线,并实现了总线的匹配回调函数 mybus_match 和设备探测回调函数 mybus_probe。同时,还定义了一个名为 "value" 的属性文件,并实现了属性的显示回调函数 mybus_show。编写完成的bus.c代码如下所示:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/configfs.h>
#include <linux/kernel.h>
#include <linux/kobject.h>
#include <linux/device.h>
#include <linux/sysfs.h>
int mybus_match(struct device *dev, struct device_driver *drv)
{
// 检查设备名称和驱动程序名称是否匹配
return (strcmp(dev_name(dev), drv->name) == 0);
};
int mybus_probe(struct device *dev)
{
struct device_driver *drv = dev->driver;
if (drv->probe)
drv->probe(dev);
return 0;
};
struct bus_type mybus = {
.name = "mybus", // 总线的名称
.match = mybus_match, // 设备和驱动程序匹配的回调函数
.probe = mybus_probe, // 设备探测的回调函数
};
ssize_t mybus_show(struct bus_type *bus, char *buf)
{
// 在 sysfs 中显示总线的值
return sprintf(buf, "%s\n", "mybus_show");
};
struct bus_attribute mybus_attr = {
.attr = {
.name = "value", // 属性的名称
.mode = 0664, // 属性的访问权限
},
.show = mybus_show, // 属性的 show 回调函数
};
// 模块的初始化函数
static int bus_init(void)
{
int ret;
ret = bus_register(&mybus); // 注册总线
ret = bus_create_file(&mybus, &mybus_attr); // 在 sysfs 中创建属性文件
return 0;
}
// 模块退出函数
static void bus_exit(void)
{
bus_remove_file(&mybus, &mybus_attr); // 从 sysfs 中移除属性文件
bus_unregister(&mybus); // 取消注册总线
}
module_init(bus_init); // 指定模块的初始化函数
module_exit(bus_exit); // 指定模块的退出函数
MODULE_LICENSE("GPL"); // 模块使用的许可证
MODULE_AUTHOR("topeet"); // 模块的作者
100.3 运行测试
100.3.1 编译驱动程序
在上一小节中的bus.c代码同一目录下创建 Makefile 文件,Makefile 文件内容如下所示:
export ARCH=arm64#设置平台架构
export CROSS_COMPILE=aarch64-linux-gnu-#交叉编译器前缀
obj-m += bus.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的内容注释已在上图添加,保存退出之后,来到存放bus.c和Makefile文件目录下,如下图(图100-1)所示:
图 100-1
然后使用命令“make”进行驱动的编译,编译完成如下图(图100-2)所示:
图 100-2
编译完生成bus.ko目标文件,如下图(图100-3)所示:
图 100-4
至此驱动模块就编译成功了,接下来进行测试。
100.3.2 运行测试
开发板启动之后,使用以下命令进行驱动模块的加载,如下图(图100-5)所示:
insmod bus.ko
图100-5
驱动加载之后,我们进入/sys/bus目录下,可以看到创建生成的总线mybus,如下图所示,我们进到mybus目录下,可以看到创建属性文件value。
图100-6
最后可以使用以下命令进行驱动的卸载,如下图(图100-7)所示:
rmmod bus
图 100-7
至此,在总线目录下创建属性文件实验就完成了。