字符设备驱动led灯实验

news2024/12/26 23:35:10

 应用程序代码

#include<stdio.h>
#include<string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main (int argc, const char *argv[])
{
	char buf[128] = "";
	int fd = open("/dev/led0",O_RDWR);
	if(fd < 0)
	{
		printf("打开文件失败\n");
		return -1;
	}
	while(1)
	{
		memset(buf,0,sizeof(buf));
		read(fd,buf,sizeof(buf));
		printf("%s\n",buf);
	}

	close(fd);
	return 0;
}	

驱动代码

#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/uaccess.h>

struct cdev *cdev;
unsigned int irqnum;
unsigned int major;
unsigned int minor;
dev_t devnum;
struct class *cls;
struct device *dev;
struct device_node *dnode;
//gpio结构体
struct gpio_desc *gpionum;
//定义等待队列头
wait_queue_head_t wq_head;
unsigned int number = 0;
char kbuf[128] = "";
unsigned int condition=0;
//中断处理函数
irqreturn_t myirq_handler(int irqnum,void *dev_id)
{
    number = !number;
    gpiod_set_value(gpionum,!gpiod_get_value(gpionum));
     condition=1;//表示硬件数据就绪
    wake_up_interruptible(&wq_head);//唤醒休眠的进程
    return IRQ_HANDLED;
}
int mycdev_open (struct inode *inode, struct file *file)
{
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    return 0;

}
ssize_t mycdev_read (struct file *file, char __user *ubuf, size_t size, loff_t * lof)
{
    
    int ret;
    if(sizeof(kbuf) < size)
    {
        size = sizeof(kbuf);
    }
    wait_event_interruptible(wq_head,condition);//将进程切换为休眠
    ret = copy_to_user(ubuf,kbuf,size);
    if(ret)
    {
        printk("copy_tO_user filed\n");
        return -EIO;
    }
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    condition=0;//表示下一次硬件数据没有准备好
    return 0;
}
int mycdev_close (struct inode *inode, struct file *file)
{
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    return 0;
}
struct file_operations fops=
{
    .open = mycdev_open,
    .read = mycdev_read,
    .release = mycdev_close,
};
static int __init mycdev_init(void)
{
    int ret;
    //初始化等待队列头
    init_waitqueue_head(&wq_head);
    //申请字符设备对象空间
    cdev = cdev_alloc();
    if(cdev == NULL)
    {
        printk("为字符设备对象申请空间失败\n");
        return -EIO;
    }
    printk("为字符设备对象申请空间成功\n");
    //初始化字符设备对象
    cdev_init(cdev,&fops);
    //申请设备号
    //动态申请
    ret = alloc_chrdev_region(&devnum,0,1,"myled");
    if(ret < 0)
    {
        printk("led灯申请设备号失败\n");
        ret = -EFAULT;
        return ret;
    }
    major = MAJOR(devnum);
    minor = MINOR(devnum);
     printk("led灯申请设备号成功,major = %d\n",major);
    //注册字符设备驱动
    ret = cdev_add(cdev,MKDEV(major,minor),1);
    if(ret < 0)
    {
        printk("注册字符设备驱动失败");
        return -EFAULT;
    }
    printk("注册字符设备驱动成功");
    //向上提交目录
    cls = class_create(THIS_MODULE,"myled");
    if(IS_ERR(cls))
    {
        printk("向上提交目录失败\n");
        ret = -PTR_ERR(cls);
        return ret;
    }
    printk("向上提交目录成功\n");
    dev = device_create(cls,NULL,MKDEV(major,minor),NULL,"led0");
    if(IS_ERR(dev))
    {
        printk("向上提交节点信息失败\n");
        ret = -PTR_ERR(dev);
        return ret;
    }
    printk("向上提交节点信息成功\n");
    //解析设备树节点信息
    dnode = of_find_node_by_name(NULL,"mydevs");
    if(dnode == NULL)
    {
        printk("解析设备树节点信息失败\n");
        return -ENXIO;
    }
    printk("解析设备树节点信息成功\n");
    //根据设备树节点解析led1  gpio结构体并向内核注册
    gpionum = gpiod_get_from_of_node(dnode,"led1",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(gpionum))
    {
        printk("申请gpio失败\n");
        return -PTR_ERR(gpionum);
    }
    printk("申请gpio成功\n");
    //默认灭灯
    gpiod_set_value(gpionum,1);
    //获取软中断号
    irqnum = irq_of_parse_and_map(dnode,0);
    if(!irqnum)
    {
        printk("软中断号获取失败\n");
        return -ENOMEM;
    }
    printk("软中断号获取成功,irqnum = %d\n",irqnum);
    //注册中断
    ret = request_irq(irqnum,myirq_handler,IRQF_TRIGGER_FALLING,"key1",NULL);
    if(ret)
    {
        printk("注册中断失败\n");
        return ret;
    }
    printk("key1注册中断成功\n");
    return 0;
}
static void __exit mycdev_exit(void)
{
    //注销中断
    free_irq(irqnum,NULL);
    //灭灯
    gpiod_set_value(gpionum,0);
    //注销gpio信息
    gpiod_put(gpionum);
    //释放设备树节点信息
    device_destroy(cls,MKDEV(major,minor));
    class_destroy(cls);
    //注销字符设备驱动
    cdev_del(cdev);
    //释放申请的设备号
    unregister_chrdev_region(MKDEV(major,minor),1);
    //释放字符驱动对象空间
    kfree(cdev);

}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

马上就要到2023年秋招的黄金时期了,计算机专业面试究竟需要注意些什么?

说说自己&#xff0c;不算很突出。本人 17 年就读于一所普通的本科学校&#xff0c;20 年 6 月在三年经验的时候顺利通过校招实习面试进入大厂&#xff0c;现就职于某大厂安全实验室。 所以我还是比较有话语权的吧。 话不多说直接进入主题。 1.理论知识准备&#xff1a;复习计算…

驱动 day9 作业

要求&#xff1a; 现象 按下key1 led1灯的状态取反&#xff0c;number的值取反&#xff0c;然后应用程序打印从内核读到的number的值 应用程序test.c #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #incl…

Bash 有效电话号码

193 有效电话号码 给定一个包含电话号码列表&#xff08;一行一个电话号码&#xff09;的文本文件 file.txt&#xff0c;写一个单行 bash 脚本输出所有有效的电话号码。 你可以假设一个有效的电话号码必须满足以下两种格式&#xff1a; (xxx) xxx-xxxx 或 xxx-xxx-xxxx。&…

三维重建以及神经渲染中的学习(三)

三维重建以及神经渲染中的学习 公众号AI知识物语 本文内容为参加过去一次暑期课程学习时的笔记&#xff0c;浅浅记录下。 三维图形可控生成&#xff1a; 1&#xff1a;学习一个图形生成模型 2&#xff1a;具有可控三维变量&#xff1a;1物体形状&#xff1b;2物体位置&…

ScannerException: while scanning for the next token found character ‘@‘ 问题解决

问题描述 后端项目启动的时候报ScannerException: while scanning for the next token found character ‘‘ 异常&#xff0c;自己有些疑问&#xff0c;项目前一会都还可以&#xff0c;到报错的过程中&#xff0c;项目都没有动过。 解决办法 重新刷新项目就解决了。

RxSwift 使用方式

背景 最近项目业务&#xff0c;所有模块已经支持Swift混编开发&#xff0c;正在逐步使用Swift 方式进行开发新业务&#xff0c;以及逐步替换老业务方式进行发展&#xff0c;所以使用一些较为成熟的Swift 的三方库&#xff0c;成为必要性&#xff0c;经过调研发现RxSwift 在使用…

HarmonyOS/OpenHarmony应用开发-程序包多HAP机制(上)

一、多HAP机制设计目标 方便开发者模块化的管理应用&#xff0c;好的应用一般都是模块化管理&#xff0c;模块之间属于松耦合关系。多HAP方便了开发者将业务划分成多个模块&#xff0c;每个模块放到独立的HAP中。例如支付类应用&#xff0c;有统一的主界面&#xff0c;主界面管…

命令注入(Command Injection)安全漏洞(SQL注入、LDAP注入、OS命令注入、XPath注入、JavaScript注入)

文章目录 命令注入&#xff08;Command Injection&#xff09;发生场景示例防范手段其他类型命令注入漏洞1. SQL注入&#xff08;SQL Injection&#xff09;2. LDAP注入&#xff08;LDAP Injection&#xff09;3. OS命令注入&#xff08;OS Command Injection&#xff09;4. XP…

VectorCAST对外部函数打桩和查看覆盖率

一、对外部函数打桩 在单元测试中&#xff0c;如果要调用到外部函数调用的时候&#xff0c;就要对外部函数进行打桩。 对外部函数进行打桩的目的&#xff0c;一方面是为了验证外部函数接口的正确性&#xff0c;另一方面是对外部函数打桩 之后就可以自定义外部函数返回值。 对…

Unity5.4.1打砖块游戏Breakout_Game_Starter_Kit

Unity5.4.1打砖块游戏Breakout_Game_Starter_Kit 童年的回忆 项目地址&#xff1a;https://download.csdn.net/download/Highning0007/88042779

vue 使用 npm run dev命令后 自动打开浏览器为谷歌

文章目录 需求分析 需求 vue 启动后&#xff0c;想要其自动打开指定浏览器&#xff08;谷歌&#xff09;并设置要打开的IP地址和端口号 分析 package.json 打开package.json文件加上 --open chrome index.js 打开index.js文件&#xff0c;将浏览器设置为自动打开

【力扣刷题 | 第十七天】

目录 前言&#xff1a; 55. 跳跃游戏 - 力扣&#xff08;LeetCode&#xff09; 45. 跳跃游戏 II - 力扣&#xff08;LeetCode&#xff09; 总结&#xff1a; 前言&#xff1a; 今天两道类型都是贪心算法&#xff0c;希望可以有所收获 55. 跳跃游戏 - 力扣&#xff08;LeetC…

入门车载以太网

前言 近些年来,随着为了让汽车更加安全、智能、环保等,一系列的高级辅助驾驶功能喷涌而出。未来满足这些需求,就对传统的电子电器架构带来了严峻的考验,需要越来越多的电子部件参与信息交互,导致对网络传输速率,稳定性,负载率等方面都提出了更为严格的挑战。 除此以外…

哪些职位需要CISP证书?快进来看看你需不需要

CISP是目前中国最主流的信息行业的证书&#xff0c;也是业界公认的最专业的信息安全技术和管理资格培训。无论是政府部门、金融、电力、交通能源、IT等相关行业&#xff0c;都可以看到CISP证书的持有人。现在持证的人数日趋上升&#xff0c;成为一个必备证书。CISP知识体系是国…

【JavaEE】HTTP协议和抓包工具的使用

目录 1、HTTP的概述和抓包工具的使用 1.1、HTTP是什么 1.2、了解HTTP协议的工作过程 1.3、抓包工具的使用 1.3.1、抓包工具在HTTP传输时的工作原理 1.3.2、Fiddler抓包工具的下载和使用 2、HTTP协议格式 2.1、HTTP 请求格式 2.1.1.基本格式 2.1.2、了解HTTP请求包中的…

有趣的命令——————用随机密码新建20个用户,并输出密码

vim test.sh 输入以下内容&#xff1a;for i in seq 10douseradd user$ipassecho $RANDOM | md5sum |cut -c 1-6echo "$pass" | passwd --stdin "user$i"echo -e "账户&#xff1a;user$i\n 密码&#xff1a;$pass" >> /root/passwddone例…

Layui关于如何添加连接数据库的选项卡(三)

目录 1.实现效果&#xff1a; 2.思路&#xff1a; 3.PermissionDao类&#xff08;增加属性&#xff09; 4.主页&#xff1a;jsp 5.简洁风格修改选项卡的样式&#xff1a; 6.关于style中的属性设置使用 7.关于Element 组件介绍&#xff1a; 8. Layui 中的页面进行更新和…

如何解决git中拉取或提交代码出现的ssl证书问题?

问题描述 执行命令的时候&#xff0c;出现"…certificate problem…"报错&#xff0c;一般在执行"git push“ (推送分支) 或者 “git clone”(克隆仓库)时出现&#xff0c;原因时因为SSL安全验证问题&#xff0c;不能获取到本地的的证书。那么如何解决这个问题…

Linus再发飙:这就是一堆垃圾!

Linux 6.3 内核的合并窗口已开启&#xff0c;Linus Torvalds 也收到了大量的 PR&#xff0c;目前总体看来正在有序进行。但 Linus 对部分合并请求的日志信息非常不满&#xff1a;“我之前就已经说过&#xff0c;很显然现在我需要再重复一次&#xff0c;如果你懒得解释为什么会存…

【UE4 C++】根据指定路径生成静态网格体

在上一篇博客中&#xff08;【UE C】蓝图调用C函数&#xff09;&#xff0c;我们用C创建了一个蓝图函数库&#xff0c;本篇文章在这个蓝图函数库基础上增加一个方法&#xff0c;该方法只需输入一个文件目录路径&#xff0c;就可在场景中生成该目录下得所有静态网格体。&#xf…