驱动开发(四):Linux内核中断

 驱动开发系列文章:
                驱动开发(一):驱动代码的基本框架    
                驱动开发(二):创建字符设备驱动
                驱动开发(三):内核层控制硬件层  

                驱动开发(四):Linux内核中断

目录

简介

中断原理

函数实现

注册中断

注销中断 

按键中断实验

驱动代码 

常见问题

解决方法

关于按键的抖动


简介

Linux内核中断是一种控制传递机制,用于处理硬件设备的事件和异常。当硬件设备发生特定事件时,例如数据传输完成、错误发生或设备准备就绪,它会向CPU发送中断信号,以引起CPU的注意。

Linux内核中断分为两种类型:外部中断和内部中断。外部中断由外部硬件设备触发,如键盘按键、鼠标点击或网络数据包到达。内部中断由CPU内部产生,如除法错误、缺页异常或系统调用。

中断处理程序是用来响应和处理中断的函数。当中断发生时,CPU会暂时停止当前正在执行的任务,并跳转到相应的中断处理程序执行。中断处理程序根据中断的类型和优先级,执行相应的操作以处理中断事件。

Linux内核提供了一个中断向量表(Interrupt Vector Table),其中包含了所有中断的处理程序的入口地址。当中断发生时,CPU会根据中断号在中断向量表中查找相应的处理程序的地址,并将控制权转移给这个地址。

在Linux内核中,中断有优先级,较高优先级的中断可以打断正在运行的较低优先级中断,这被称为中断抢占。Linux内核通过中断处理程序的优先级和抢占策略来管理中断的响应和处理。

中断是Linux内核实现设备驱动和处理硬件事件的重要机制。它能够提高系统的并发性和响应性,有效地处理多种硬件设备的事件和异常。

中断原理

Linux内核中断的原理主要涉及硬件、中断控制器和中断处理程序的协作工作。

  1. 硬件触发中断:当硬件设备发生特定事件时,例如数据传输完成、错误发生或设备准备就绪,它会向CPU发送中断信号。这个中断信号会被送到中断控制器。

  2. 中断控制器:中断控制器是硬件设备负责管理和传递中断信号的组件。它负责接收中断信号,确定中断的类型和优先级,并通过中断向量表将控制权传递给相应的中断处理程序。

  3. 中断处理程序:中断处理程序是用来响应和处理中断的函数。当中断发生时,CPU会跳转到相应的中断处理程序的入口地址执行。中断处理程序根据中断的类型和优先级,执行相应的操作以处理中断事件。

  4. 中断处理过程:当中断发生时,CPU会先保存当前的执行环境(包括寄存器状态、程序计数器等),然后根据中断号在中断向量表中查找相应的中断处理程序的入口地址。中断处理程序会执行特定的操作,处理中断事件。处理完成后,CPU会恢复之前保存的执行环境,并继续执行被中断的任务。

  5. 中断抢占:在Linux内核中,中断有优先级,较高优先级的中断可以打断正在运行的较低优先级中断,这被称为中断抢占。中断抢占能够保证紧急事件的优先处理,并提高系统的并发性和响应性。

总结来说,Linux内核中断的原理是通过硬件设备触发中断信号,中断控制器将中断信号传递给CPU,CPU根据中断号在中断向量表中查找对应的中断处理程序,并执行特定的操作来处理中断事件。中断抢占能够保证紧急事件的优先处理,并提高系统的并发性和响应性。

先找到IRQ的标签,然后跳转,跳转时这个名字是写死的(handle_irq),在handle_irq里定义一个数组,irq_desc[],数组的每一个成员变量里存了结构体,irq_xxx。在结构体里面有个函数指针,这个指针指向了我们函数的名字。数组的下标和中断号有关系,这里是中断号,但是是软中断号。

软中断号是linux内核给分配的中断号,是内核为了兼容各种芯片,而设计的。这里兼容是通过映射实现的,我们不同的板子根据映射关系,使用中断号得到软中断号。

函数实现

注册中断

int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,const char *name, void *dev)
功能:注册中断
参数:@irq : 软中断号  gpio的软中断号   软中断号 = gpio_to_irq(gpio号);gpio号 = m*32+n         m:哪一组  A B C D E      0 1 2 3 4	  n:组内的序号例如:GPIOA28的gpio号 = 0*32+28 = 40@handler: 中断的处理函数irqreturn_t (*irq_handler_t)(int irqno, void *dev);IRQ_NONE        //中断没有处理完成IRQ_HANDLED     //中断正常处理完成@flags :中断的触发方式#define IRQF_DISABLED		0x00000020 //快速中断#define IRQF_SHARED		0x00000080     //共享中断#define IRQF_TRIGGER_RISING	0x00000001//上升沿#define IRQF_TRIGGER_FALLING	0x00000002//下降沿#define IRQF_TRIGGER_HIGH	0x00000004//高电平#define IRQF_TRIGGER_LOW	0x00000008//低电平@name :名字   cat /proc/interrupts@dev  :向中断处理函数中传递参数 ,如果不想传写个NULL就行返回值:成功0,失败返回错误码
快速中断(在处理函数里面写了他,就先处理这个中断)

共享中断(中断的接口较少,但是器件都想要中断,那管脚需要外接两个,寄存器里面有中断状态标志位,看中断状态标志位有没有置位。一个口不可以链接两个按键,按键没办法区分)

注销中断 

oid free_irq(unsigned int irq, void *dev_id)
功能:注销中断
参数:@irq :软中断号@dev_id:向中断处理函数中传递的参数 ,如果上面写的NULL,这里就写NULL

按键中断实验

1、  查看实物,找到按键丝印)

2、  去地板原理图网络标号----->芯片引脚)

GPIOB8--------->gpio号=40

GPIOB16--------->gpio号=48

驱动代码 

#include <linux/init.h>
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>#define GPIONO(m, n) m * 32 + n  //计算gpio号
#define GPIO_B8 (GPIONO(1, 8))   
#define GPIO_B16 (GPIONO(1, 16))
int gpiono[] = {GPIO_B8, GPIO_B16};    //数组内存入两个按键的软中断号
char *name[]={"gpio_it_8","gpio_it_16"};     //随便定义,用于区分int ret,i;//中断处理函数
irqreturn_t handler(int irqno, void *dev)
{if(irqno == gpio_to_irq(GPIO_B8)){printk(KERN_ERR "+++++++++++++\n");}if(irqno == gpio_to_irq(GPIO_B16)){printk(KERN_ERR "-------------\n");}return IRQ_HANDLED;
}static int __init hello_init(void)
{
//循环注册中断  gpio_to_irq()for (i = 0; i < sizeof(gpiono) / sizeof(int); i++){ret = request_irq(gpio_to_irq(gpiono[i]), handler, IRQF_TRIGGER_FALLING,name[i], NULL);if (ret != 0){printk(KERN_ERR "%s request irq err\n",name[i]);return ret;}}return 0;
}
static void __exit hello_exit(void)
{
//循环注销中断for (i = 0; i < sizeof(gpiono) / sizeof(int); i++){free_irq(gpio_to_irq(gpiono[i]), NULL);}
}module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

常见问题

驱动安装时报错:

insmod: can't insert 'farsight_irq.ko': Device or resource busy

解决方法

1、在开发板执行
cat /proc/interrupts

146: GPIO nxp-keypad

154: GPIO nxp-keypad

说明中断号已经被占用了,要在内核中将占用中断号的驱动删掉

2、在虚拟机中,内核顶层目录上执行 grep "nxp-keypad" * -nR

显示

arch/arm/mach-s5p6818/include/mach/devices.h:48:#define DEV_NAME_KEYPAD "nxp-keypad"

3、执行 grep "DEV_NAME_KEYPAD" * -nR

drivers/input/keyboard/nxp_io_key.c:324: .name = DEV_NAME_KEYPAD,

找到驱动文件的名字是nxp_io_key.c

4、cd drivers/input/keyboard/

5、vi Makefile 

6、找到由nxp_io_key.o生成的目标文件KEYBOARD_NXP_KEY

7、make menuconfig

8、make uImage 重新编译内核

9、cp arch/arm/boot/uImage ~/tftpboot 将内核放到TFTP下

关于按键的抖动

明明只按了一次按键,却打印了多条信息

所有的机械元件都会有抖动问题

主要原因不是手抖,而是硬件自身的抖动(输入的机械元件才会有抖动)

最好是使用定时器的方式消抖

定时器消抖的原理:

主程序触发中断-》在按键中断服务程序里开启定时器-》在定时器中断里实现按键中断操作

好处:避免在中断里面使用延时函数,增加CPU的执行效率

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

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

相关文章

自然资源-测绘地信专业术语,值得收藏!

自然资源-测绘地信专业术语&#xff0c;值得收藏&#xff01; 1、1954年北京坐标系 1954年我国决定采用的国家大地坐标系&#xff0c;实质上是由原苏联普尔科沃为原点的1942年坐标系的延伸。 2、1956年黄海高程系统 根据青岛验潮站1950年一1956年的验潮资料计算确定的平均海面…

java:一个springfox swagger2的简单例子

# 示例程序 【pom.xml】 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.3.12.RELEASE</version> </dependency> <dependency><groupId>…

视图-什么是(VIEW)?怎么创建(CREATE VIEW)?怎么删除(DROP)?怎么用(SELECT/INSERT/UPDATE/DELETE)?

一、引言 之前对数据库的操作都是针对基本关系表&#xff0c;操作都是在数据库的全局逻辑模式上进行的&#xff0c;而在实际的数据库系统中&#xff0c;可能用户只关心或只被允许使用数据库中的某些基本关系表或基本关系表中的某些属性列&#xff0c;这些数据构成了数据库的外…

vue(v-if,v-else-if-else-show)

基本应用 例子 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTE-8"> <meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-w…

实战篇(一):软体2D模拟详解

import java.util.ArrayList; import com.thomasdiewald.pixelflow.java.DwPixelFlow; import com.thomasdiewald.pixelflow.java

LabView_波形控件

波形图表 将一定数量的数据点存储在缓冲区&#xff0c;并通过这种方式存储并显示这些数据点。当缓冲区被填满后&#xff0c;波形图表将会用新的数据点覆盖缓冲区中存在时间最久的数据点。 当数据点可用时&#xff0c;波形图表将显示已有的数据点外加最新接收到的数据点 。 您可…

nodejs安装及环境配置常见报错解决

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境,它允许 JavaScript 代码在服务器端运行。Node.js 的出现极大地扩展了 JavaScript 的应用场景,使其不仅仅局限于前端开发,还能够处理服务器端逻辑、数据库操作、网络编程等任务。以下是 Node.js 的一些主要功能详…

NVIDIA Triton系列02-功能与架构简介

NVIDIA Triton系列02-功能与架构简介 B站&#xff1a;肆十二-的个人空间-肆十二-个人主页-哔哩哔哩视频 (bilibili.com) 博客&#xff1a;肆十二-CSDN博客 问答&#xff1a;(10 封私信 / 72 条消息) 肆十二 - 知乎 (zhihu.com) 前面文章介绍微软 Teams 会议系统、微信软件与腾讯…

使用file.transferTo()做Java文件复制,目标文件存在时,是抛异常还是覆盖写入?

背景 最近在做一个项目&#xff0c;在服务端涉及到文件的复制操作&#xff0c;于是想到了 Java 中 FileInputStream 类的 transferTo() 方法。这里简单记录一下用法&#xff0c;另外&#xff0c;如果目标文件已经存在&#xff0c;该如何处理这种情况呢&#xff1f;是出现异常还…

儿童编程语言

儿童编程是指为儿童设计的编程教育活动&#xff0c;旨在通过有趣、互动的方式教授儿童编程的基本概念和技能。随着科技的发展&#xff0c;编程教育越来越受到重视&#xff0c;因为它不仅能够培养儿童的逻辑思维、问题解决能力和创造力&#xff0c;还能为他们未来的学习和职业发…

C语言怎样复制图形?

一、问题 C语⾔中如何实现把屏幕某⼀处的图形复制到另⼀处&#xff1f; 二、解答 复制图形要⽤到以下3个函数&#xff1a; void far getimage(int xl,nt yl, int x2,int y2, void far *mapbuf); void far putimge(int x,int,y,void *mapbuf, int op); unsined far imagesiz…

Thinkphp一文鸡富贵鸡玫瑰庄园富农场仿皮皮果理财农场源码

Thinkphp一文鸡富贵鸡玫瑰庄园富农场仿皮皮果理财农场源码&#xff0c;喜欢的朋友可以下载研究 一文鸡富贵鸡玫瑰庄园富农场仿皮皮果理财农场源码

Django初学者指南

文章目录 Django初学者指南1 Django简介1.1 Django的历史1.2 使用Django的知名网站1.4 Django的主要特点1.5 Django的工作原理 2 Django 使用2.1 Django 支持的 Python 版本2.2 Django 版本 3 Django 开发 Web 程序3.1 安装Django3.2 创建Django项目3.3 运行开发服务器3.4 创建…

数据结构02 队列及其应用【C++实现】

目录 队列及其特点 利用数组模拟队列的基本操作 创建队列 空队条件 元素入队 元素出队 模拟超市收银问题 队列操作 初始化 入队操作 出队操作 取出队首元素 STL模板中队列的基本使用 训练&#xff1a;约瑟夫问题 参考程序 队列及其特点 队列是一种特殊的线性表&am…

求导,积分

求导公式&#xff1a; 复合函数求导法则&#xff1a;两个函数导函数的乘积. 例如&#xff1a;f(x)2x1,f(x)2,g(x)x^24x4,g(x)2x4 那么复合函数&#xff1a; g(f(x))(2x1)^24(2x1)4 把&#xff08;2x1&#xff09;看做整体,则g2(2x1)4 然后再求&#xff08;2x1&#xff09;的导函…

Stable Diffusion vs DALL·E3

大模型技术论文不断&#xff0c;每个月总会新增上千篇。本专栏精选论文重点解读&#xff0c;主题还是围绕着行业实践和工程量产。若在某个环节出现卡点&#xff0c;可以回到大模型必备腔调或者LLM背后的基础模型新阅读。而最新科技&#xff08;Mamba,xLSTM,KAN&#xff09;则提…

网络编程(五)IO模型

文章目录 一、 阻塞IO&#xff08;一&#xff09;阻塞IO模式&#xff08;二&#xff09;示例 二、非阻塞IO&#xff08;一&#xff09;特点&#xff08;二&#xff09;fcntl&#xff08;三&#xff09;示例 三、IO多路复用&#xff08;一&#xff09;实现原理&#xff08;二&am…

基于System-Verilog的流水灯设计与仿真

文章目录 一、system Verilog1.语言基本介绍2.过程赋值和连续赋值 二、编写testbench仿真1.流水灯testbench2.2位全加器3.实验结果 一、system Verilog 1.语言基本介绍 像 Verilog 和 VHDL 之类的硬件描述语言 (HDL) 主要用于描述硬件行为&#xff0c;以便将其转换为由组合门…

【实用技巧】Unity中的3D物理系统:刚体——使用技巧

在使用Unity的3D物理系统中的刚体&#xff08;Rigidbody&#xff09;时&#xff0c;有一些技巧可以帮助你更有效地实现物理效果和优化性能。以下是一些使用刚体的技巧&#xff1a; 合理使用Is Kinematic属性&#xff1a; 对于那些不需要物理计算的对象&#xff0c;比如玩家控制…

海底管缆先敷后埋与边敷边埋有什么区别?

海缆铺设有两种方式&#xff1a;“边敷边埋”和“先敷后埋”。 “边敷边埋”冲埋式埋设犁施工法———通过埋设犁(水力开沟机)泵送高压水&#xff0c;在海底冲出一条沟槽的同时&#xff0c;将海缆平铺下去,然后利用在潮汐作用下海床面自行回填(必要时采取压盖保护施工)。主要施…