Linux内核驱动开发-001字符设备开发-内核中断驱动独立按键

1驱动程序

/*************************************************************************> File Name: key_enit.c> Author: yas> Mail: rage_yas@hotmail.com> Created Time: 2024年04月22日 星期一 20时20分42秒************************************************************************/#if 1
/*=========================The key_enit driver=========================*//*==========头文件包含==========*/
#include <linux/init.h>
#include <linux/module.h>
#include <asm/uaccess.h>
#include <linux/irqreturn.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <mach/irqs.h>
#include <linux/fs.h>
#include <asm/io.h>/*==========函数声明==========*/static int __init key_driver_init(void);static int key_driver_open(struct inode *node, struct file *fp);
static ssize_t key_driver_read(struct file *fp, char __user *user_buffer, size_t len, loff_t *offset);
static ssize_t key_driver_write(struct file *fp, const char __user *user_buffer, size_t len, loff_t *offset);
static int key_driver_close(struct inode *node, struct file *fp);void disable_irq_r(void);
void free_irq_r(void);
static void __exit key_driver_exit(void);/*==========全局变量==========*//*保存键值*/
u8 key = 0;/*字符设备文件操作结构体*/
static struct file_operations fops =
{.owner = THIS_MODULE,.open = key_driver_open,.read = key_driver_read,.write = key_driver_write,.release = key_driver_close
};/*杂项设备结构体*/
static struct miscdevice key_dev = 
{.minor = MISC_DYNAMIC_MINOR,.name = "key_r",.fops = &fops,
};/*******************************************************************************
* 函 数 名	: key_interrupt
* 函数功能	: 处理中断任务
* 输    入  : 
*           irq : 中断号
*           *p  :中断处理函数传参,一般传【NULL】
* 输    出  :
*   irqreturn_t :表示中断由该设备处理,是一个枚举类型
*******************************************************************************/
irqreturn_t key_interrupt(int irq, void *p)
{printk("key_interrupt\n");if(irq == IRQ_EINT8){key = 1;}else if(irq == IRQ_EINT11){key = 2;}return IRQ_HANDLED;
}/*******************************************************************************
* 函 数 名	: key_driver_init
* 函数功能	: 
* 输    入  : 							
* 输    出  :
*******************************************************************************/
static int __init key_driver_init(void)
{int ret;/* 1 注册杂项设备*/ret = misc_register(&key_dev);if(ret <  0){printk("misc_register is failed\n");goto misc_register_err;}/* 2 注册中断-【中断号】-【中断处理函数指针】-【中断产生的条件和系统处理中断时的行为(这里处理中断时不响应其他中断)】-【给中断名命名】-【中断服务函数传参-NULL】*/ret = request_irq(IRQ_EINT8, key_interrupt, IRQF_TRIGGER_FALLING | IRQF_DISABLED, "key1", NULL);//中断名查看:【/proc/interrupts】if(ret < 0){printk("request_irq is failed\n");goto request_irq_err;}return 0;request_irq_err:misc_deregister(&key_dev);
misc_register_err:return -1;
}/*******************************************************************************
* 函 数 名	: key_driver_open
* 函数功能	: 
* 输    入  : 							
* 输    出  :
*******************************************************************************/
static int key_driver_open(struct inode *node, struct file *fp)
{return 0;
}/*******************************************************************************
* 函 数 名	: key_driver_read
* 函数功能	: 
* 输    入  : 							
* 输    出  :
*******************************************************************************/
static ssize_t key_driver_read(struct file *fp, char __user *user_buffer, size_t len, loff_t *offset)
{copy_to_user(user_buffer, &key, 4);key = 0;//下降沿触发,没有按键按下时清0return sizeof(key);
}/*******************************************************************************
* 函 数 名	: key_driver_write
* 函数功能	: 
* 输    入  : 							
* 输    出  :
*******************************************************************************/
static ssize_t key_driver_write(struct file *fp, const char __user *user_buffer, size_t len, loff_t *offset)
{return 0;
}/*******************************************************************************
* 函 数 名	: key_driver_close
* 函数功能	: 
* 输    入  : 							
* 输    出  :
*******************************************************************************/
static int key_driver_close(struct inode *node, struct file *fp)
{return 0;
}/*******************************************************************************
* 函 数 名	: disable_irq_r
* 函数功能	: 禁止中断
* 输    入  : 							
* 输    出  :
*******************************************************************************/
void disable_irq_r(void)
{/*禁止中断,如果中断正在执行,则等待中断执行结束后再禁止它*/disable_irq(IRQ_EINT8);
}/*******************************************************************************
* 函 数 名	: free_irq_r
* 函数功能	: 
* 输    入  : 							
* 输    出  :
*******************************************************************************/
void free_irq_r(void)
{/*注销中断*/free_irq(IRQ_EINT8, NULL);
}
/*******************************************************************************
* 函 数 名	: key_interrupt
* 函数功能	: 
* 输    入  : 							
* 输    出  :
*******************************************************************************/
static void __exit key_driver_exit(void)
{disable_irq_r();//禁止中断free_irq_r();//注销中断misc_deregister(&key_dev);//
}module_init(key_driver_init);
module_exit(key_driver_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("XXX");
/*=========================The key_enit driver=========================*/
#endif/*=========================The key_enit driver=========================
* 总结:
* 1 中断原理:
*   注册中断,通过函数传参的方式将中断的重要信息(中断号-中断服务函数-中断触发方式)传给内核,
*从而达到调用内核中断的目的。
*   我觉得这与裸机驱动最大不同的是,作为开发者,我不需要直接接触硬件,我只需要*知道: 用什么工具(哪个中断)做什么事情(中断服务函数),就OK了;抛开外部中断这个具体的项目,我想这是一名内核驱动工程师应当具备的最基本的意识!
*
* 2 按键中断基本流程:
* 在字符设备驱动的基本架构下->采用杂项驱动方式:
*   驱动初始化(注册杂项设备->注册中断->配置中断)->中断响应流程(硬件的工作)
*   驱动卸载(禁止中断->注销中断->注销杂项设备)
*
*
* 3 问题:
* (1)问题1:
*   问题描述: 
*       运行应用程序时,应用程序不间地断读取按键状态,即使是没有按键按下
*   问题溯源:
*       应用程序中【read】函数是非阻塞的
*   解决方式:
*       方式1 :驱动层用一个【while】死循环来等待按键按下触发中断,不足之处是
*死循环等待中断触发的方式会造成CPU资源的浪费方式2 :在驱动层使用等待队列以及poll机制
* */

2应用程序

/*************************************************************************> File Name: main.c> Author: yas> Mail: rage_yas@hotmail.com> Created Time: 2024年04月21日 星期日 15时56分47秒************************************************************************/#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>int main(void)
{  
#if 1
/*====================key-r====================*/    int fd=0;int n=0;fd=open("dev/key_r",O_RDWR);//这里路径一定要对,尤其是手动创建设备结点的时候if(fd<0){printf("opening is failed\n");return -1;}while(1){read(fd,&n,4);printf("%d\n",n);sleep(1);}return 0;
/*========================================*/    
#endif
}

3关于内核中断

/*=========================The key_enit driver=========================
* 总结:
* 1 中断原理:
*   注册中断,通过函数传参的方式将中断的重要信息(中断号-中断服务函数-中断触发方式)传给内核,
*从而达到调用内核中断的目的。
*   我觉得这与裸机驱动最大不同的是,作为开发者,我不需要直接接触硬件,我只需要*知道: 用什么工具(哪个中断)做什么事情(中断服务函数),就OK了;抛开外部中断这个具体的项目,我想这是一名内核驱动工程师应当具备的最基本的意识!
*
* 2 按键中断基本流程:
* 在字符设备驱动的基本架构下->采用杂项驱动方式:
*   驱动初始化(注册杂项设备->注册中断->配置中断)->中断响应流程(硬件的工作)
*   驱动卸载(禁止中断->注销中断->注销杂项设备)
*
*
* 3 问题:
* (1)问题1:
*   问题描述: 
*       运行应用程序时,应用程序不间地断读取按键状态,即使是没有按键按下
*   问题溯源:
*       应用程序中【read】函数是非阻塞的
*   解决方式:
*       方式1 :驱动层用一个【while】死循环来等待按键按下触发中断,不足之处是
*死循环等待中断触发的方式会造成CPU资源的浪费方式2 :在驱动层使用等待队列以及poll机制
* */

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

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

相关文章

使用JS代理 实现大对象的功能拆解

序言 在Android开发中&#xff0c;可以通过webView的addJavascriptInterface方法注入一个对象到网页中。但是随着开发的需求越来越多。这个对象身上的方法也越来越多。这个对象对应的java类&#xff0c;体积越来越大&#xff0c;不利于维护。为了在不影响之前代码的基础上。把…

【C++干货基地】深度理解C++中的高效内存管理方式 new delete

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引入 哈喽各位铁汁们好啊&#xff0c;我是博主鸽芷咕《C干货基地》是由我的襄阳家乡零食基地有感而发&#xff0c;不知道各位的…

Golang基础5-指针、结构体、方法、接口

指针 和c/c类似&#xff0c;但是go语言中指针不能进行偏移和运算&#xff0c;安全指针 &&#xff08;取地址) *(根据地址取值) nil(空指针&#xff09; make和new之前对比&#xff1a;make用于初始化slice&#xff0c;map&#xff0c;channel这样的引用类型 而new用于类…

Metasploit Framework(MSF)从入门到实战(一)

MSF的简介 目前最流行、最强大、最具扩展性的渗透测试平台软件 基于Metasploit进行渗透测试和漏洞分析的流程和方法 2003年由HD More发布第一版&#xff0c;2007年用ruby语言重写 架集成了渗透测试标准 (PETS&#xff09; 思想 一定程度上统一了渗透测试和漏洞研究的工作环…

针孔相机模型原理坐标系辨析内参标定流程内参变换

针孔相机的内参标定 针孔相机原理真空相机模型图片的伸缩和裁剪变换 内参标定———非线性优化张正定标定详细原理(含公式推导)通过多张棋盘格照片完成相机的内参标定流程(C代码)其他工具箱 相机分为短焦镜头和长焦镜头&#xff0c;短焦镜头看到的视野更广阔&#xff0c;同样距…

Debian常用命令

Debian是一种常见的Linux发行版&#xff0c;以下是一些常用的Debian命令&#xff1a; 1. apt-get&#xff1a;用于安装、升级和删除软件包。例如&#xff1a;apt-get install package_name。 2. dpkg&#xff1a;用于管理Debian软件包。例如&#xff1a;dpkg -i package_name…

白平衡简介

文章目录 白平衡的概念白平衡的调节常见的白平衡模式 白平衡的概念 白平衡是指摄影、摄像和显示技术中的一项重要概念&#xff0c;用于调节图像中的白色或中性灰色的色彩&#xff0c;使其看起来在不同光源条件下都是准确的白色或灰色。白平衡的主要目的是确保图像的色彩准确性…

C语言 | Leetcode C语言题解之第49题字母异位词分组

题目&#xff1a; 题解&#xff1a; /*1.将字符串原串与副本进行绑定成一个节点2.对字符串副本进行按ascii码表进行从小到大排序3.按照字符串进行比较排序4.合并 */ typedef struct Node{char*s;char*s_vice;int len; }Node;void sortShellChar(char*s,int len){for(int dista…

TS类型断言

类型断言&#xff08;Type Assertions&#xff09;在 TypeScript 中确实是一种在表达式级别上临时指定类型的机制&#xff0c;它允许开发者在编译时覆盖编译器的类型推断结果。类型断言有两种语法形式&#xff1a; “尖括号”语法&#xff1a; let someValue: any this is a s…

查找总价格为目标值的两个商品 ---- 双指针

题目链接 题目: 分析: 解法一: 暴力解法, 将每两个的和都算出来, 判断是否为目标值解法二: 数组中的数是按升序排序的, 我们可以定义左右指针 如果和小于目标值, 则应该让和变大, 所以左指针右移如果和大于目标值, 则应该让和变小, 所以右指针左移 思路: 定义left 0, righ…

python学习29:python中的字典dict

python中的字典dict 1.字典的定义&#xff1a; 同样是使用{},不过存储的元素是一个个的&#xff1a;键值对&#xff0c;如下语法&#xff1a; """ 字典的定义&#xff1a; #定义字典字面量&#xff1a;{key:value,key:value,....,key:value} #定义字典变量&am…

每天一个数据分析题(二百九十)——直方图与条形图

关于直方图与条形图的描述&#xff0c;下列说法正确的是&#xff08;&#xff09; A. 直方图用于展示分类型数据的分布情况 B. 直方图用来展示数值型数据的分布情况 C. 条形图只能用于展示顺序型数据的分布情况 D. 条形图只能用于展示分类型数据的分布情况 题目来源于CDA模…

绝地求生【商城更新】WIA联名上架//专属商店下架

大家好&#xff0c;我是闲游盒. 本周商城将在4.24&#xff08;周三&#xff09;更新&#xff0c;商城内容更新如下&#xff1a; 上架物品 ▲W.I.A联名皮肤大礼包 小礼包如下&#xff1a; 包含3套衣服以及MINI、DBS的联名皮肤&#xff0c;3个头饰还挺有特色的&#xff0c;你喜欢…

链栈算法库构建

学习贺利坚老师, 链栈 , 构建链栈算法库 数据结构之自建算法库——链栈_领会链栈结构和掌握链栈中的各种基本算法-CSDN博客文章浏览阅读3.9k次&#xff0c;点赞3次&#xff0c;收藏8次。本文针对数据结构基础系列网络课程(3)&#xff1a;栈和队列中第4课时栈的链式存储结构及其…

安全开发实战(3)--存活探测与端口扫描

目录 安全开发专栏 前言 存活探测 端口扫描 方式一: 1.3.1 One 1.3.2 Two 1.3.3 批量监测 方式二: 1.3.1 One 1.3.2 Two 1.3.3 Three 1.3.4 扫描ip地址,提取出开放端口和协议 ​编辑 1.3.5 批量扫描(最终完成版) 总结 安全开发专栏 安全开发实战​http://t.csd…

数据安全风险评估流程

数据安全风险评估是一个系统性的过程&#xff0c;旨在识别、评估和管理数据安全风险。以下是数据安全风险评估的一般流程及其内容&#xff1a; 确定评估范围&#xff1a;确定评估的范围和目标&#xff0c;包括评估的数据资产、系统、流程和相关方。 收集信息&#xff1a;收集有…

spring mvc \ spring boot \ spring cloud

spring mvc 主要是用作IOC 容器 框架还是传统三层架构 1.容器 依赖注入 CDI 传统web是由beanmanager管理bean的依赖和注入&#xff0c;beanfactory管理bean的创建&#xff0c;以消息进行驱动(HttpSessionListener等) 由框架自行管理 2.IOC 控制反转 bean的创建由开发人员…

leveldb中THREAD_ANNOTATION_ATTRIBUTE__宏的作用

THREAD_ANNOTATION_ATTRIBUTE__ 宏在 LevelDB 或类似的 C 项目中用于指定线程安全相关的源码注解&#xff08;Source Code Annotation&#xff09;&#xff0c;这些注解有助于清晰地表达程序中函数、变量、类型等元素在多线程环境中的行为特征和并发保证。这样的注解不仅有助于…

【zabbix7】新版本尝鲜之connector

zabbix历史版本中&#xff0c;会使用python脚本&#xff0c;把zabbix的告警发送到kafka进行二次处理&#xff0c;或者使用filebeat把zabbix的Export的njson指标数据发送到kafka进行二次处理&#xff0c;然而在zabbix7中新增了新功能connector简化了操作并且可以根据tag进行区分…

【算法刷题day36】Leetcode:435. 无重叠区间、763.划分字母区间、56. 合并区间

文章目录 Leetcode 435. 无重叠区间解题思路代码总结 Leetcode 763.划分字母区间解题思路代码总结 Leetcode 56. 合并区间解题思路代码总结 草稿图网站 java的Deque Leetcode 435. 无重叠区间 题目&#xff1a;435. 无重叠区间 解析&#xff1a;代码随想录解析 解题思路 先按…