驱动开发-day10

驱动代码:

#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
struct cdev* cdev;
unsigned int major = 500;
unsigned int minor = 0;
dev_t devno;
struct class* cls;
struct device* dev;struct resource* res;
unsigned int irqno;
struct gpio_desc* gpiono;unsigned int number;
// 定义等待队列头
wait_queue_head_t wq_head;
unsigned int condition = 0;ssize_t mycdev_read(struct file* file, char* ubuf, size_t size, loff_t* lof)
{int ret;// 将进程切换到休眠状态wait_event_interruptible(wq_head, condition);if (size > sizeof(number)) {size = sizeof(number);}ret = copy_to_user(ubuf, &number, size);if (ret) {printk("copy_to_user filed\n");return -EIO;}condition = 0; // 下次硬件的数据没有准备好return size;
}
irqreturn_t myirq_led_handler(int irqno, void* dev_id)
{gpiod_set_value(gpiono, !gpiod_get_value(gpiono));number = gpiod_get_value(gpiono);condition = 1; // 数据准备就绪// 唤醒休眠的进程wake_up_interruptible(&wq_head);return IRQ_HANDLED;
}struct file_operations fops = {.read = mycdev_read,};
int pdrv_probe(struct platform_device* pdev)
{int ret, i;// 初始化等待队列头init_waitqueue_head(&wq_head);// 分配字符设备驱动对象空间cdev = cdev_alloc();if (cdev == NULL) {printk("申请字符设备驱动空间失败\n");ret = -EFAULT;goto out1;}// 字符设备驱动对象部分初始化cdev_init(cdev, &fops);// 静态申请设备号if (major > 0) {ret = register_chrdev_region(MKDEV(major, minor), 3, "mykey");if (ret) {printk("静态指定设备号失败\n");goto out2;}} else { // 动态申请设备号ret = alloc_chrdev_region(&devno, minor, 3, "mykey");if (ret) {printk("动态指定设备号失败\n");goto out2;}major = MAJOR(devno);minor = MINOR(devno);}// 注册字符设备驱动对象ret = cdev_add(cdev, MKDEV(major, minor), 3);if (ret) {printk("注册字符设备驱动对象失败\n");goto out3;}printk("注册字符设备驱动对象成功\n");// 向上提交目录cls = class_create(THIS_MODULE, "mykey");if (IS_ERR(cls)) {printk("向上提交目录失败\n");ret = -PTR_ERR(cls);goto out4;}printk("向上提交目录成功\n");// 向上提交设备节点for (i = 0; i < 3; i++) {dev = device_create(cls, NULL, MKDEV(major, i), NULL, "mykey%d", i);if (IS_ERR(dev)) {printk("向上提交节点信息失败\n");ret = -PTR_ERR(dev);goto out5;}}printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);// printk("向上提交设备节点信息成功\n");// 获取设备信息res = platform_get_resource(pdev, IORESOURCE_MEM, 0);if (res == NULL) {printk("获取资源失败\n");return -ENXIO;}printk("获取资源信息成功 %x\n", res->start);irqno = platform_get_irq(pdev, 0);if (irqno < 0) {printk("获取中断资源失败\n");return irqno;}printk("中断类型资源为%d\n", irqno);// 获取gpio信息gpiono = gpiod_get_from_of_node(pdev->dev.of_node, "led1", 0, GPIOD_OUT_LOW, NULL);if (IS_ERR(gpiono)) {printk("解析GPIO信息失败\n");return -PTR_ERR(gpiono);}// 注册中断ret = request_irq(irqno, myirq_led_handler, IRQF_TRIGGER_FALLING, "key1", NULL);if (ret) {printk("注册失败\n");return ret;}return 0;
out5:// 销毁提交的设备信息device_destroy(cls, MKDEV(major, minor));class_destroy(cls);
out4:cdev_del(cdev);
out3:unregister_chrdev_region(MKDEV(major, minor), 3);
out2:kfree(cdev);
out1:return ret;
}
// remove 设备和驱动分离时执行
int pdrv_remove(struct platform_device* pdev)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);// 灭灯gpiod_set_value(gpiono, 0);// 释放gpio信息free_irq(irqno, NULL);gpiod_put(gpiono);// 销毁设备信息int i;for (i = 0; i < 3; i++) {device_destroy(cls, MKDEV(major, i));}// 销毁目录class_destroy(cls);// 注销对象cdev_del(cdev);// 释放设备号unregister_chrdev_region(MKDEV(major, minor), 3);// 释放对象空间kfree(cdev);return 0;
}
// 构建设备树匹配表
struct of_device_id oftable[] = {{.compatible = "hqyj,myplatform",},{.compatible = "hqyj,myplatform1",},{},
};
struct platform_driver pdrv = {.probe = pdrv_probe,.remove = pdrv_remove,.driver = {.name = "aaaaa",.of_match_table = oftable,},};
// 一键注册宏
module_platform_driver(pdrv);
MODULE_LICENSE("GPL");

 测试代码:


#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char const* argv[])
{int fd;unsigned int number;// 打开LEDfd = open("/dev/mykey0", O_RDWR);if (fd < 0) {printf("打开设备文件失败\n");exit(-1);}while (1) {read(fd, &number, sizeof(number));printf("number=:%d\n", number);}close(fd);return 0;
}

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

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

相关文章

本地服务器localhost:3000一直连接不上

1.检查使用端口3000的进程: 在Windows上,运行 netstat -ano | findstr :3000在Mac/Linux上,运行lsof -i :3000 这将列出当前使用端口3000的任何进程。您要终止这些进程以释放该端口。 2.检查防火墙规则: 确保您的防火墙允许连接到localhost:3000。在MacOS和Windows上,通常不…

【分布式能源的选址与定容】基于多目标粒子群算法分布式电源选址定容规划研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

防范 XSS 攻击的措施

防范 XSS 攻击的措施 XSS&#xff08;Cross-site scripting&#xff09;攻击是一种常见的网络安全漏洞&#xff0c;它可以通过注入恶意代码来攻击用户的计算机和浏览器&#xff0c;从而窃取用户的敏感信息或执行恶意操作。本篇文章将介绍防范 XSS 攻击的措施&#xff0c;并提供…

JConsole或者JvisualVM远程连接jetty进行jvm监控

最近项目发现了服务有内存泄漏的问题&#xff0c;但是在jvm上并没有配置即jvm没有配置 -XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath/tmp/heapdump.hprof 这两个参数&#xff0c;导致在发生了oom后只能看到日志中有OOM异常&#xff0c;其他的并不能分析出来&#xff0c;等…

CSS3 动画 animation 入门学习笔记 之 属性详解

文章目录 简单介绍 CSS 动画CSS 动画的作用CSS 动画语法介绍CSS 动画属性animation-nameanimation-durationanimation-delayanimation-directionanimation-iteration-countanimation-play-stateanimation-timing-functionanimation-fill-modeanimation 简单介绍 CSS 动画 引用…

css3提供的网页布局

css3提供的网页布局 弹性盒子模型&#xff08;flex box&#xff09;&#xff1a; 设置成弹性盒子 默认横着排放&#xff08;div也是&#xff09; 当子盒子给的宽度过大&#xff0c;总的子盒子宽度超过父级盒子&#xff0c;会自动适配&#xff0c;计算整个盒子父级的大小&#…

【计算机视觉 | 图像分割】arxiv 计算机视觉关于图像分割的学术速递(7 月 13 日论文合集)

文章目录 一、分割|语义相关(7篇)1.1 Correlation-Aware Mutual Learning for Semi-supervised Medical Image Segmentation1.2 RFENet: Towards Reciprocal Feature Evolution for Glass Segmentation1.3 Sem-CS: Semantic CLIPStyler for Text-Based Image Style Transfer1.4…

Django_静态资源配置和ajax(九)

目录 一、静态资源配置 二、AJAX ajax作用 使用ajax 1、环境配置 2、创建html模板文件 3、编写视图函数并添加路由 4、运行django开发服务器进行验证 源码等资料获取方法 一、静态资源配置 静态资源的相关配置都在项目目录下的 settings.py 文件中进行配置。配置参数如…

MySQL主从复制

文章目录 介绍配置——前置条件配置——主库配置——从库测试读写分离案例背景Sharding-JDBC介绍入门案例 介绍 MySQL主从复制是一个异步的复制过程&#xff0c;底层是基于MySQL数据库自带的二进制日志功能。就是一台或多台MySQL数据库&#xff08;slave&#xff0c;即从库&…

23数字图像置乱技术(matlab程序)

1.简述 一、引言 所谓“置乱”&#xff0c;就是将图像的信息次序打乱&#xff0c;a像素移动到b像素位置上&#xff0c;b像素移动到c像素位置上&#xff0c;……&#xff0c;使其变换成杂乱无章难以辨认的图片。数字图像置乱技术属于加密技术&#xff0c;是指发送发借助数学或者…

6.EFLFK(EFLK+kafka)

文章目录 EFLFK(EFLKkafka)zookeeper概述Zookeeper 特点数据结构和工作场景选举机制&#xff08;重要&#xff09;总结部署Zookeeper kafka为什么用消息队列&#xff08;MQ&#xff09;中间件使用消息队列的好处消息队列模式消息队列总结&#xff1a;kafka概述Kafka特性Kafka架…

怎样优雅地增删查改(六):按任意字段关键字查询

文章目录 实现应用测试 实现 定义按任意字段关键字查询过滤器&#xff08;IKeywordOrientedFilter&#xff09;接口&#xff0c;查询实体列表Dto若实现该接口&#xff0c;将筛选指定的目标字段&#xff08;TargetFields&#xff09;包含指定的关键字&#xff08;Keyword&#…