【Linux驱动】Linux中断(二)—— 按键中断驱动

前一篇已经在设备树的 gpio-led 节点中引入了中断信息,接下来将通过API来获取设备树中的中断信息。gpio-led 节点具体内容如下:

gpio-key0 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_gpio_keys>;            // pinctrl子系统配置电气属性key-gpio = <&gpio1 18 GPIO_ACTIVE_HIGH>;     // gpio子系统进行引脚初始化interrupt-parent = <&gpio1>;                 // 中断类型为 gpio1interrupts = <18 IRQ_TYPE_EDGE_FALLING>;     // 中断引脚为 GPIO1_IO18,触发方式为下降沿status = "okay";
};

一、中断 API

1、获取中断信息

获取设备树中 interrupts 属性的信息有两种方式,一种是针对 gpio 的方式,另一种是比较通用的方式。最终获取到的都是中断号,这里的中断号和裸机开发时的中断号不一样,裸机开发我们是根据参考文档来获取中断号

而下面通过 API 获取到的中断号是经过映射的,类似于虚拟内存和物理内存的映射,这样做的目的是保护原中断号。这也是为什么后续获取到的中断号会与裸机开发时使用的中断号不一致。

gpio_to_irq

gpio_to_irq 是仅用于获取 gpio 中断相关信息,要求对应节点的父类中断控制器为 gpio,即 interrupt-parent 属性引用的是 gpio 控制器。该接口的声明在 <asm/gpio.h>,接口原型如下: 

#define gpio_to_irq	__gpio_to_irq
/*** @ param gpio  表示根据gpio设备树节点获取到的 gpio 编号* @ return      成功返回中断号,失败返回负值*/
int __gpio_to_irq(unsigned gpio);

irq_of_parse_and_map

irq_of_parse_and_map 是比较通用的中断信息获取方式,不仅仅适用于 gpio,也适用于其他外设中断。该接口的声明在 <linux/of_irq.h>,接口原型如下:

/*** @ param dev   设备树节点* @ param index interrupts属性索引* @ return      成功返回中断号,失败返回负值*/
unsigned int irq_of_parse_and_map(struct device_node *dev,int index);

注意:interrupts属性中可以包含多个中断信息,需要index来获取当前驱动所需的中断信息

 

2、注册中断

注册中断时主要告诉内核以下内容:

  • 中断号: 映射后的中断号
  • 触发方式:如何触发中断
  • 中断服务函数:中断触发后如何处理
  • 中断服务函数参数

注册中断使用的 API 为 request_irq,函数原型的声明在 <linux/interrupt.h>

/*** @param irq       映射后的中断号* @param handler   中断服务函数* @param flags     触发方式* @param name      中断名* @param dev       给中断服务函数传递的参数* @return          成功返回0,失败返回负值*/
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,const char *name, void *dev);

中断服务函数声明:

typedef irqreturn_t (*irq_handler_t)(int, void *);

触发方式 flags(linux/irq.h)

中断名 name:

        设置以后可以在/proc/interrupts 文件中看到对应的中断名字,以此来判断中断是否注册成功

3、释放中断

注册中断后,如果模块被卸载,需要释放中断,释放中断 free_irq 的接口原型声明在 <linux/interrupt.h>

/*** @param irq       映射后的中断号* @param dev       给中断服务函数传递的参数*/
void free_irq(unsigned int irq, void * dev);

二、驱动完善

1、驱动入口函数

驱动入口函数主要是获取中断号,并申请中断,其他的诸如申请设备号、自动创建驱动节点等操作将不再赘述。下面使用变量 status 来代表某个外设的状态,按键按下时中断触发,此时反转设备状态。

struct chrdev_t 
{// ...struct device_node* gpioNode;			/* 设备树节点 */uint32_t 			gpioNum;			/* gpio 引脚编号 */uint32_t 			irqNum;				/* 中断号 */uint32_t            status;				/* 设备状态 */
};
static struct chrdev_t chrdev;/* 驱动入口函数 */
static int __init kerneltimer_init(void)
{uint32_t ret = 0;/* 获取key0设备树节点 */chrdev.gpioNode = of_find_node_by_path("/gpio-key0");if(chrdev.gpioNode == NULL){	printk("node cannot be found!\n");return -1;}// 获取 gpio 编号chrdev.gpioNum = of_get_named_gpio(chrdev.gpioNode, "key-gpio", 0);if (chrdev.gpioNum < 0){printk("gpio property fetch failed!\n");return -1;}// 配置 gpio 为输入ret = gpio_direction_input(chrdev.gpioNum);if (ret < 0){printk("gpio set failed!\n");return -1;}#if 1// 根据gpio编号获取中断信息chrdev.irqNum = gpio_to_irq(chrdev.gpioNum);if (chrdev.irqNum < 0){printk("irq number fetch failed!\n");return -1;}
#else// 根据节点获取中断号chrdev.irqNum = irq_of_parse_and_map(chrdev.gpioNode, 0);if (chrdev.irqNum < 0){printk("irq number fetch failed!\n");return -1;}
#endifprintk("中断号: %u\n", chrdev.irqNum);// 设备初始状态为 0chrdev.status = 0;// 注册中断ret = request_irq(chrdev.irqNum, key0_handler, IRQ_TYPE_EDGE_FALLING, "key0-int", &chrdev);if (ret < 0){printk("irq subscribe failed!\n");return -1;}// ... 
}

2、中断服务函数

上面在介绍注册中断 API 时已经提及了中断服务函数的声明,第一个参数为 中断号,第二个参数为注册时传递给中断服务函数的参数

static irqreturn_t key0_handler(int irq, void * dev)
{struct chrdev_t* pdev = (struct chrdev_t*)dev;// 状态反转pdev->status = !pdev->status;return IRQ_RETVAL(IRQ_HANDLED);
}

3、read 操作函数

static ssize_t chrdev_read(struct file *pfile, char __user * pbuf, size_t size, loff_t * poff)
{// 在 open 函数中 pfile->private_data = &chrdev;struct chrdev_t* pdev = pfile->private_data;unsigned long ret = 0;// 将设备状态返回给应用层ret = copy_to_user(pbuf, &pdev->status, sizeof(pdev->status));if (ret != 0){printk("kernel send data failed!\n");return -1;}return sizeof(pdev->status);
}

4、驱动退出函数

驱动退出函数需要释放中断

static void __exit kerneltimer_exit(void)
{// ... /* 注销中断 */free_irq(chrdev.irqNum, &chrdev);
}

三、测试

在应用程序中每隔 1s 调用 read 函数来获取设备状态

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>#define delayms(x)        usleep(x * 1000)void printHelp()
{printf("usage: ./xxxApp <driver_path>\n");
}int main(int argc, char* argv[])
{if (argc != 2){printHelp();return -1;}char* driver_path = argv[1];       // 位置0 保存的是 ./chrdevbaseAppint state = 0;int ret = 0;int fd = 0;fd = open(driver_path, O_RDONLY);if (fd < 0){perror("open file failed");return -2;}while (1){ret = read(fd, &state, sizeof(state));if (ret < 0){printf("read data error\n");break;}printf("中断触发状态:%d\n", state);delayms(1000);}close(fd);return 0;
}

裸机开发时,GPIO1_IO18 对应的中断号为99,现在因为经过一层映射,屏蔽了真正的中断号,使用了虚拟中断号,所以这里的中断号为 47 

应用程序的测试结果如下,按下按键时触发中断,此时状态反转,但因为没有做消抖处理,灵敏性不高,接下来的一步需要在上述驱动的基础上进行改进,进行按键消抖。 

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

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

相关文章

linux性能优化

文章目录 性能优化图CPU进程和cpu原理性能指标 性能优化图 CPU 进程和cpu原理 进程与线程&#xff1a; 进程是程序的执行实例&#xff0c;有自己的地址空间和系统资源。线程是进程内的执行单元&#xff0c;共享进程的资源。在多核系统中&#xff0c;使用多线程可以更好地利用多…

【JS逆向】某乐网登陆密码加密逆向分析探索!

一个网站的登陆密码加密逆向解密分析&#xff0c;没有混淆&#xff0c;加密代码还是比较好找的&#xff0c;只需要多花点耐心&#xff0c;多尝试&#xff0c;就能找到关键的加密代码片段。 网址&#xff1a; aHR0cHMlM0EvL29hdXRoLmQuY24vYXV0aC9nb0xvZ2luLmh0bWw 登陆密码加密…

炼石免改造加密亮相2023商密大会,参编密评行业报告发布

2023年8月9-11日&#xff0c;2023商用密码大会在河南省郑州国际会展中心圆满召开&#xff0c;是我国商密领域规格最高、规模最大、影响最广的全国性商用密码盛会&#xff0c;也是《密码法》和新修订的《商用密码管理条例》正式实施以来的第一次全国性的盛会。大会以“密码赋能美…

excel 插件:Rainbow Analyst Crack

一个插件中包含四种 EXCEL 审核工具检测并修复隐藏的电子表格错误 不要满足于更少&#xff0c;四种领先的电子表格审计工具合二为一 Rainbow Analyst&#xff08;因其对颜色编码的独特强大使用而得名&#xff09;结合了世界级电子表格审核功能的多个领域&#xff1a; Excel™ …

关于如何设计出优秀的 URL

Kyle Aster 在 2010 年就写过为什么认真设计 URL 很重要&#xff1a; URL 是通用的&#xff0c;它们适用于 Firefox, Chrome, Safari, Internet Explorer, cURL, wget, 以及 iPhone&#xff0c;Android, 甚至便签。它们是网络的唯一通用语法&#xff0c;不要把这当作理所当然。…

LCR 145. 判断对称二叉树

解题思路&#xff1a; class Solution {public boolean checkSymmetricTree(TreeNode root) {return root null || recur(root.left, root.right);}boolean recur(TreeNode L, TreeNode R) {if(L null && R null) return true;if(L null || R null || L.val ! R.v…

Java 深入理解 AQS 和 CAS 原理

AQS 介绍 AQS 全称是 Abstract Queued Synchronizer&#xff0c;一般翻译为同步器。它是一套实现多线程同步功能的框架&#xff0c;由大名鼎鼎的 Doug Lea 操刀设计并开发实现的。AQS 在源码中被广泛使用&#xff0c;尤其是在 JUC&#xff08;Java Util Concurrent&#xff09;…

天融信Topgate搭建

一、下载防火墙 首先下载防火墙&#xff0c;在虚拟机中打开。 二、网卡配置 防火墙设备上有5块网卡&#xff0c;分别对应接口eth1~5 这里要手动添加&#xff0c;还有需要注意vmnet1&#xff0c;他的必须是192.168.1.0&#xff0c;并且为DHCP 其它vlan无需设置DHCP 自定义网…

跨站脚本攻击漏洞XSS绕过22种方式总结

XSS漏洞简介 跨站脚本攻击在目前这个时间节点还是属于一个排位比较高的漏洞&#xff0c;在OWASP TOP10 2021中隶属于注入型漏洞&#xff0c;高居TOP3的排位&#xff0c;可见这个漏洞的普遍性。跨站脚本攻击的学习中我们主要需要明白的是跨站的含义&#xff0c;以及XSS的核心。…

企业数据存储监控

随着组织及其网络基础架构的不断扩展&#xff0c;存储将不可避免地成为一项挑战&#xff0c;随着存储需求的增长&#xff0c;调配更多存储资源的需求也会随之增长。为基础架构配置了更多存储资源后&#xff0c;它们需要不间断地运行&#xff0c;并且应该免受威胁。从本质上讲&a…

Syn_SegNet:用于常规 3T MRI 中超高场 7T MRI 合成和海马亚场分割的联合深度神经网络

Syn_SegNet: A Joint Deep Neural Network for Ultrahigh-Field 7T MRI Synthesis and Hippocampal Subfield Segmentation in Routine 3T MRI Syn_SegNet&#xff1a;用于常规 3T MRI 中超高场 7T MRI 合成和海马亚场分割的联合深度神经网络背景贡献实验为了确定哪个模态分割最…

list1.Sort((m, n) => m.Id - n.Id); id是double类型的为什么回报错

问题产生的地方 原因 对于 double 类型的属性&#xff0c;不能直接使用减法运算符进行比较。减法运算符只能用于数值类型&#xff0c;而 double 是浮点数类型。 要在 double 属性上进行排序&#xff0c;可以使用 CompareTo 方法或者使用自定义的比较器。 更改 要在 double 属性…

K8s 源码剖析及debug实战之 Kube-Scheduler(五):优选算法详解

文章目录 0. 引言1. 回顾2. PrioritizeNodes3. 有哪些优选算法4. selectHost5. 总结6. 参考 0. 引言 欢迎关注本专栏&#xff0c;本专栏主要从 K8s 源码出发&#xff0c;深入理解 K8s 一些组件底层的代码逻辑&#xff0c;同时借助 debug Minikube 来进一步了解 K8s 底层的代码…

鸿蒙应用中图片的显示(Image组件)

目录 1、加载图片资源 1.1、存档图类型数据源 a.本地资源 b.网络资源 c.Resource资源 d.媒体库file://data/storage e.base64 1.2、多媒体像素图片 2、显示矢量图 3、添加属性 3.1、设置图片缩放类型 3.2、设置图片重复样式 3.3、设置图片渲染模式 3.4、设置图…

Go语言基本数据类型

Go语言基本数据类型 1.整型2.浮点型3.复数4.布尔型5.字符串窥探字符串类型字符串内建函数UTF-8编码字符串处理相关的四个包字符串和数字的转换 6.常量 1.整型 Go语言同时提供了有符号和无符号类型的整数运算。这里有int8、int16、int32和int64四种截然不同大小的有符号整数类型…

基于springboot公租房申请管理系统

开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven…

柯桥小语种学习,留学韩语 生活日常口语 语法

① N이다/A/V/았ㄹ/을지도 모르다 说不定 이미 도착했을 지도 모르니까 전화해 봐요 说不定已经到了&#xff0c;打电话试试 주말에 세일이 있을지도 모르니까 주말에 가 보자 周末说不定会搞活动&#xff0c;我们周末去吧 ② ㄴ/은/는/았었는/ㄹ/을지 모르다 不知道 처음이…

【webstorm中通过附加方式打开一个项目,这个项目本身有git,但是却看不到git的解决方法】

1、如图所示 设置-》版本控制-》未注册的根&#xff0c;选中后&#xff0c;再点加号&#xff0c;就可以了 2、如图所示 版本控制-》直接点加号-》选中项目路径&#xff0c;vcs选择git&#xff0c;点击确定就可以了

prometheus grafana mysql监控配置使用

文章目录 前传bitnami/mysqld-exporter:0.15.1镜像出现了问题.my.cnf可以用这个"prom/mysqld-exporter:v0.15.0"镜像重要的事情mysql监控效果外传 前传 prometheus grafana的安装使用&#xff1a;https://nanxiang.blog.csdn.net/article/details/135384541 本文说…

【电商项目实战】沙箱支付模拟支付功能

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《电商项目实战》。&#x1f3af;&#x1f3af; &am…