瑞芯微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主板
第158章 DS18B20编写字符设备驱动框架
接着上个章节的驱动编写,本章节实现DS18b20编写字符设备驱动框架。
158.1 驱动程序的编写
本实验对应的网盘路径为:iTOP-RK3568开发板【底板V1.7版本】\03_【iTOP-RK3568开发板】指南教程\02_Linux驱动配套资料\04_Linux驱动例程\94_ds18b20_02。
编写完成的ds18b20.c代码如下所示。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/kdev_t.h>
#include <linux/slab.h>struct ds18b20_data
{dev_t dev_num; // 设备号struct cdev ds18b20_cdev; // 字符设备结构struct class *ds18b20_class; // 设备类struct device *ds18b20_device; // 设备
};struct ds18b20_data *ds18b20; // 全局设备数据指针// 设备打开函数
int ds18b20_open(struct inode *inode, struct file *file)
{return 0;
}// 设备读取函数
ssize_t ds18b20_read(struct file *file, char __user *buf, size_t size, loff_t *offs)
{return 0;
}// 设备释放函数
int ds18b20_release(struct inode *inode, struct file *file)
{return 0;
}// 定义设备文件操作结构
struct file_operations ds18b20_fops = {.open = ds18b20_open,.read = ds18b20_read,.release = ds18b20_release,.owner = THIS_MODULE,
};// 设备探测函数
int ds18b20_probe(struct platform_device *dev)
{int ret;printk("This is probe \n");// 分配设备数据结构内存ds18b20 = kzalloc(sizeof(*ds18b20), GFP_KERNEL);if (ds18b20 == NULL){printk("kzalloc error\n");ret = -ENOMEM;goto error_0;}// 分配字符设备号ret = alloc_chrdev_region(&ds18b20->dev_num, 0, 1, "myds18b20");if (ret < 0){printk("alloc_chrdev_region error\n");ret = -EAGAIN;goto error_1;}// 初始化字符设备并添加到系统cdev_init(&ds18b20->ds18b20_cdev, &ds18b20_fops);ds18b20->ds18b20_cdev.owner = THIS_MODULE;cdev_add(&ds18b20->ds18b20_cdev, ds18b20->dev_num, 1);// 创建设备类ds18b20->ds18b20_class = class_create(THIS_MODULE, "sensors");if (IS_ERR(ds18b20->ds18b20_class)){printk("class_create error\n");ret = PTR_ERR(ds18b20->ds18b20_class);goto error_2;}// 创建设备ds18b20->ds18b20_device = device_create(ds18b20->ds18b20_class, NULL, ds18b20->dev_num, NULL, "ds18b20");if (IS_ERR(ds18b20->ds18b20_device)){printk("device_create error\n");ret = PTR_ERR(ds18b20->ds18b20_device);goto error_3;}return 0;error_3:class_destroy(ds18b20->ds18b20_class);error_2:cdev_del(&ds18b20->ds18b20_cdev);unregister_chrdev_region(ds18b20->dev_num, 1);error_1:kfree(ds18b20);error_0:return ret;
}// 定义设备匹配表
const struct of_device_id ds18b20_match_table[] = {{ .compatible = "ds18b20" },{ },
};// 定义平台驱动
struct platform_driver ds18b20_driver = {.driver = {.owner = THIS_MODULE,.name = "ds18b20",.of_match_table = ds18b20_match_table,},.probe = ds18b20_probe,
};// 模块初始化函数
static int __init ds18b20_init(void)
{int ret;ret = platform_driver_register(&ds18b20_driver);if (ret < 0){printk("platform_driver_register error\n");return -1;}return 0;
}//模块退出函数
static void __exit ds18b20_exit(void)
{// 销毁设备device_destroy(ds18b20->ds18b20_class, ds18b20->dev_num);// 销毁设备类class_destroy(ds18b20->ds18b20_class);// 删除字符设备cdev_del(&ds18b20->ds18b20_cdev);// 注销字符设备号unregister_chrdev_region(ds18b20->dev_num, 1);// 释放设备数据结构内存kfree(ds18b20);// 注销平台驱动platform_driver_unregister(&ds18b20_driver);
}// 注册模块初始化和退出函数
module_init(ds18b20_init);
module_exit(ds18b20_exit);MODULE_LICENSE("GPL");
158.2 编译驱动程序
在上一小节中的ds18b20.c代码同一目录下创建 Makefile 文件,Makefile 文件内容如下所示:
export ARCH=arm64#设置平台架构
export CROSS_COMPILE=aarch64-linux-gnu-#交叉编译器前缀
obj-m +=ds18b20.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的内容注释已在上图添加,保存退出之后,来到存放ds18b20.c和Makefile文件目录下,如下图所示:
然后使用命令“make”进行驱动的编译,编译完成如下图所示:
编译完生成ds18b20.ko目标文件,如下图所示:
至此DS18b20字符设备驱动框架编写完成了,并且编译驱动模块成功了。