linux驱动学习(九)之中断

一、中断的实现

对于中断的请求,在linux内核中,有一套标准的接口函数,可以实现中断的响应和处理。

#include <linux/interrupt.h>//1 申请中断
static inline int __must_check request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev)1)unsigned int irq  ---->中断号,每个中断源有一个唯一中断号
2)irq_handler_t handler  --->中断请求发生后,被调用的中断服务函数 typedef irqreturn_t (*irq_handler_t)(int, void *); /*** enum irqreturn* @IRQ_NONE		interrupt was not from this device  中断发生异常时* @IRQ_HANDLED		interrupt was handled by this device 正常返回* @IRQ_WAKE_THREAD	handler requests to wake the handler thread*/
enum irqreturn {IRQ_NONE		= (0 << 0),IRQ_HANDLED		= (1 << 0),IRQ_WAKE_THREAD		= (1 << 1),
};typedef enum irqreturn irqreturn_t;3)unsigned long flags ---->中断的标志----->中断触发方式
4) const char *name --->中断的名称,是由用户自定义
5)void *dev ---->向中断服务程序传递的参数 返回值:成功:0失败:返回负数的错误码

查看开发板linux系统中的中断:

[root@GEC6818 /proc]#cat interrupts 

	   CPU0       CPU1       CPU2       CPU3       CPU4       CPU5       CPU6       CPU7       33:          0          0          0          0          0          0          0          0       GIC  pl08xdmac34:          0          0          0          0          0          0          0          0       GIC  pl08xdmac37:          0          0          0          0          0          0          0          0       GIC  rtc 1hz39:         18         14         13         10         22         14         14         29       GIC  nxp-uart48:          0          0          0          1          0          0          0          0       GIC  s3c2440-i2c.149:       3197        153       3935       3803       3735       3151       3387       3896       GIC  s3c2440-i2c.256:      22946      15098      13068      14422      15060      15512      15454      18817       GIC  Event Timer IRQ63:          0          0          0          0          0          0          0          0       GIC  nxp-wdt65:       1402        876        712        851        786        901        919        982       GIC  nxp-disp66:          0          0          0          0          0          0          0          0       GIC  nxp-disp68:          0          0          1          0          0          0          0          0       GIC  hdmi-int中断号       中断被处理的次数                                                                    中断控制器   中断名称

在linux内核中,如果中断号被使用或者被其他申请了,再申请就会出错:

[root@GEC6818 /6818_driver]#insmod led_drv.ko 
[ 1022.779000] gec6818_interrupt_init
[ 1022.779000] ------------[ cut here ]------------
[ 1022.782000] WARNING: at kernel/irq/manage.c:1370 request_threaded_irq+0x114/0x13c()
[ 1022.789000] Modules linked in: led_drv(O+)
[ 1022.793000] [<c001517c>] (unwind_backtrace+0x0/0x134) from [<c0044880>] (warn_slowpath_common+0x54/0x64)
[ 1022.803000] [<c0044880>] (warn_slowpath_common+0x54/0x64) from [<c004492c>] (warn_slowpath_null+0x1c/0x24)
[ 1022.813000] [<c004492c>] (warn_slowpath_null+0x1c/0x24) from [<c00b8fd8>] (request_threaded_irq+0x114/0x13c)
[ 1022.822000] [<c00b8fd8>] (request_threaded_irq+0x114/0x13c) from [<bf00203c>] (gec6818_interrupt_init+0x3c/0x50 [led_drv])
[ 1022.833000] [<bf00203c>] (gec6818_interrupt_init+0x3c/0x50 [led_drv]) from [<c0008710>] (do_one_initcall+0x11c/0x174)
[ 1022.844000] [<c0008710>] (do_one_initcall+0x11c/0x174) from [<c0097dc0>] (sys_init_module+0xaa4/0x1e14)
[ 1022.853000] [<c0097dc0>] (sys_init_module+0xaa4/0x1e14) from [<c000ec40>] (ret_fast_syscall+0x0/0x30)
[ 1022.863000] ---[ end trace d4f7d5ddfdae4527 ]---
insmod: can't insert 'led_drv.ko': invalid parameter  ---->不合法参数,request_irq的参数不对

成功输出:

[root@GEC6818 /6818_driver]#insmod led_drv.ko 
[ 2711.551000] gec6818_interrupt_init
[root@GEC6818 /6818_driver]#lsmod
led_drv 977 0 - Live 0xbf008000 (O)
[root@GEC6818 /6818_driver]#cat /proc/interrupts 
134:          0          0          0          0          0          0          0          0      GPIO  my_interrupt
134 --->中断号 IRQ_GPIO_A_START + 28 --->106 + 28 --->134
//2 释放中断
void free_irq(unsigned int, void *)
参数说明:unsigned int ---->要释放的中断的中断号void * ----> 中断服务程序的参数

二、中断号

unsigned int irq

中断号是跟中断源有关,每一个中断源有一个唯一中断号,中断源由外部与内部,中断源是跟硬件有关,每一个处理器平台,中断源不一样的。

1、硬件平台的中断源的定义

kernel\arch\arm\mach-s5p6818\include\mach\s5p6818_irq.h
/*
* Physical Interrupt Number 64 (0~63)
*/
#define IRQ_PHY_UART1					(6	+ 32) // pl01115_Uart_modem
#define IRQ_PHY_UART0					(7	+ 32) // UART0_MODULE
#define IRQ_PHY_UART2					(8	+ 32) // UART1_MODULE
#define IRQ_PHY_UART3					(9	+ 32) // pl01115_Uart_nodma0
#define IRQ_PHY_UART4					(10 + 32)	// pl01115_Uart_nodma1
#define IRQ_PHY_UART5					(11 + 32)	// pl01115_Uart_nodma2/** GPIO Interrupt Number 160 (106~265)*/
#define IRQ_GPIO_START			IRQ_PHY_MAX_COUNT
#define IRQ_GPIO_END			(IRQ_GPIO_START + 32 * 5)	// Group: A,B,C,D,E#define IRQ_GPIO_A_START		(IRQ_GPIO_START + PAD_GPIO_A)
#define IRQ_GPIO_B_START		(IRQ_GPIO_START + PAD_GPIO_B)
#define IRQ_GPIO_C_START		(IRQ_GPIO_START + PAD_GPIO_C)
#define IRQ_GPIO_D_START		(IRQ_GPIO_START + PAD_GPIO_D)
#define IRQ_GPIO_E_START		(IRQ_GPIO_START + PAD_GPIO_E)	关于中断号与GPIO:   KEY2->GPIOA28 按键       中断号                     GPIO口号        GPIO口
KEY2    IRQ_GPIO_A_START+28         PAD_GPIO_A+28   GPIOA28头文件:#include <cfg_type.h>

三、中断标志

unsigned long flags

注意:中断一旦安装成功(request_irq),默认是打开的

中断标志分为:外部中断和内部中断


1、外部中断标志

#define IRQF_TRIGGER_NONE        0x00000000
#define IRQF_TRIGGER_RISING      0x00000001
#define IRQF_TRIGGER_FALLING     0x00000002
#define IRQF_TRIGGER_HIGH        0x00000004
#define IRQF_TRIGGER_LOW         0x00000008双边沿触发:IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING    

2、内核内部中断

#define IRQF_DISABLED	0x00000020   //当响应当前中断的时候,关闭其他的中断
#define IRQF_SHARED		0x00000080  	 //当一个中断源,注册多次时,可以对应多个中断服务程序
#define IRQF_TIMER		(__IRQF_TIMER | IRQF_NO_SUSPEND | IRQF_NO_THREAD)  //当注册定时器中断时,使用该标志

四、中断服务程序

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

通常情况下,一个中断源对应一个中断服务程序(中断处理函数),也可以多个中断源对应一个中断服务程序。

irqreturn_t key_irq_handler(int irq,void* dev)
{}1 根据中断号来区分中断处理
2 通过中断请求传递的参数来区分中断处理
头文件:#include <linux/interrupt.h>

注意:对于嵌入式系统中,中断服务程序是一个原子操作,所谓的原子操作就是该过程被执行时,不能被打断。 在中断服务服务程序中,不能有阻塞的操作,如睡眠,copy_to_user,copy_from_user,锁等。

在linux内核中,使用睡眠函数要包含头文件:

#include <linux/delay.h>
static inline void ssleep(unsigned int seconds)  ---->秒级睡眠
void msleep(unsigned int msecs); ----->毫秒

五、中断与等待队列(wait_queue)

 1、等待队列

设置一个等待条件,如果条件满足,则进程继续往下执行;如果条件不满足,则进程就进入等待队列中。当条件满足时,中断会唤醒等待队列中的进程,进程再继续往下执行。等待队列也是一种同步方法。

2、等待队列的相关API接口函数

#include <linux/wait.h>
#include <linux/sched.h>//等待队列结构体:
typedef struct __wait_queue wait_queue_t;
struct __wait_queue 
{unsigned int flags;  //条件变量的标志#define WQ_FLAG_EXCLUSIVE	0x01void *private;wait_queue_func_t func;struct list_head task_list;
};1)定义一个等待队列 和等待的条件
static wait_queue_t gec6818_wait;
static in key_press_flag = 0;2)初始化等待队列
#define init_wait(wait)							\do {								\(wait)->private = current;				\(wait)->func = autoremove_wake_function;		\INIT_LIST_HEAD(&(wait)->task_list);			\(wait)->flags = 0;					\
} while (0)
static inline void INIT_LIST_HEAD(struct list_head *list)由此可得:
void init_wait(wait_queue_t* wait);
如 init_wait(&gec6818_wait);#define init_waitqueue_head(q)				\do {						\static struct lock_class_key __key;	\\__init_waitqueue_head((q), #q, &__key);	\
} while (0)得到原型:void init_waitqueue_head(wait_queue_head_t*);struct __wait_queue_head 
{spinlock_t lock;struct list_head task_list;
};
typedef struct __wait_queue_head wait_queue_head_t;
比如:wait_queue_head_t gec6818_wq_head;3)进入等待队列
#define wait_event_interruptible(wq, condition)				\({									\int __ret = 0;							\if (!(condition))						\__wait_event_interruptible(wq, condition, __ret);	\__ret;								\
})
struct __wait_queue_head {spinlock_t lock;struct list_head task_list;
};typedef struct __wait_queue_head wait_queue_head_t;
void wait_event_interruptible(wait_queue_head_t wait,int condition)4)唤醒队列
#define wake_up(x)			__wake_up(x, TASK_NORMAL, 1, NULL)void wake_up(wait_queue_head_t* head)

觉得有帮助的话,打赏一下呗。。

           

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

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

相关文章

flask南京市旅游景点信息可视化-计算机毕业设计源码02941

摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对南京市旅游景点信息可视化等问题&#xff0…

使用gtest做cpp的单元测试并可查看代码覆盖率

前言 由于工作需要&#xff0c;要使用googletest做单元测试&#xff0c;本文记录下搭建gtest单元测试环境&#xff0c;并查看代码覆盖率的方法&#xff0c;以备不时之需。 准备工作 编译gtest 克隆gtest源码&#xff1a; git clone https://github.com/google/googletest.g…

QUIC 和 TCP: 深入解析为什么 QUIC 更胜一筹

引言 在过去的三十年里&#xff0c;HTTP&#xff08;超文本传输协议&#xff09;一直是互联网的支柱。我们可以通过 HTTP 浏览网页、下载文件、流式传输电影等。这一协议随着时间的推移已经得到了重大改进。 HTTP 协议是一个应用层协议&#xff0c;它基于 TCP&#xff08;传输…

【git使用一】windows下git下载、安装和卸载

目录 &#xff08;1&#xff09;下载安装包 &#xff08;2&#xff09;安装git &#xff08;3&#xff09;安装验证 &#xff08;4&#xff09;卸载git &#xff08;1&#xff09;下载安装包 官网下载地址&#xff1a;Git 国内镜像下载地址&#xff1a;CNPM Binaries Mir…

Unity图集

概述 相信在同学们学习过程中&#xff0c;在UI的的使用时候一定经常听说过图集的概念。 Unity有UI的组件&#xff0c;有同学们好奇&#xff0c;那为什么还要使用图集呢&#xff1f; 这就需要提到一个性能优化的问题了&#xff0c;因为过多的UI图片&#xff0c;会大幅增加Dra…

【机器学习】LightGBM: 优化机器学习的高效梯度提升决策树

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 LightGBM: 优化机器学习的高效梯度提升决策树引言一、LightGBM概览二、核心技术…

buildroot编译出错you should not run configure as root

虚拟机版本&#xff1a;ubuntu-22.04.4 问题 buildroot在图形配置后&#xff0c;执行 sudo make开始编译出现以下错误configure: error: you should not run configure as root (set FOenvironment to bypass this check) 在网上看到说在/etc/profile文件中添加以下内容 exp…

火车头采集织梦发布模块插件下载及教程

火车头采集网页数据发布到织梦CMS&#xff08;DeDeCMS&#xff09;系统操作步骤如下&#xff1a; 1. 火车头采集织梦DeDeCMS发布模块下载安装 百度网盘&#xff1a;火车头采集织梦CMS发布插件下载地址 提取码&#xff1a;414h 2. 在火车头采集软件导入织梦De…

MAC系统下安装VUE

下载node.js 点击链接 选择图片中的稳定版本 安装node.js 打开终端&#xff0c;输入 node -v 和 npm -v 显示如上信息表示安装成功 安装vue脚手架&#x1f527; sudo npm install -g vue/cli查看vue版本 vue -V6. 启动项目 1 采用 图形页面方式 控制台输入&#xff…

MySQL 中 Varchar(50) 和 varchar(500) 区别是什么?

一. 问题描述 我们在设计表结构的时候&#xff0c;设计规范里面有一条如下规则: 对于可变长度的字段&#xff0c;在满足条件的前提下&#xff0c;尽可能使用较短的变长字段长度。 为什么这么规定&#xff1f;我在网上查了一下&#xff0c;主要基于两个方面 基于存储空间的考…

C# Winform 用户控件,扩展控件,自定义控件综合实例

Control类是Windows窗体控件的基类&#xff0c;它提供了在 Windows 窗体应用程序中进行可视显示所需的基础结构&#xff0c;可以通过继承来扩展熟悉的用户控件和现有控件的功能。本列介绍三种不同自定义控件以及怎么创建他们。 自定义控件分类 用户控件&#xff1a;基本控件的…

IT入门知识博客文章大纲第二部分《编程语言》(2/10)

目录 IT入门知识博客文章大纲第二部分《编程语言》 1.引言 2.编程语言概述 2.1 编程语言的发展历程 2.2 编程范式 3.常见的编程语言 3.1 Python 3.2 Java 3.3 C 3.4 JavaScript 3.5 Ruby 4.编程语言的选择 4.1 技术需求 4.2 团队技能 4.3 社区和生态系统 4.4 可…

Python也能“零延迟“通信吗?ZeroMQ带你开启高速模式!

目录 1、零基础入门ZeroMQ 🚀 1.1 ZeroMQ简介与安装 1.2 基础概念:Socket类型详解 1.3 实战演练:Hello World示例 2、深入浅出消息模式 🔌 2.1 请求-应答模式( REQ/REP ) 2.2 发布-订阅模式( PUB/SUB ) 2.3 推送-拉取模式( PUSH/PULL ) 3、Python实战ZeroM…

Aptos Builder Jam 亚洲首站|议程公布,无限畅想 Aptos 生态未来

作为一个新兴的 Layer1 公链&#xff0c;Aptos 自诞生之日起的理想便是 “A Layer 1 for everyone” 当 Web3 深陷熊市阴影之时&#xff0c;Aptos 奋力为开发者找到了全新的技术路径&#xff0c;正有 200 项目正在开发&#xff0c;并且已有大量 DeFi 项目落实部署工作&#xff…

shell文本三剑客 awk 和 grep

awk 前言 AWK是一种优良的文本处理工具。它不仅是 Linux中也是任何环境中现有的功能最强大的数据处理引擎之一。 Linux中最常用的文本处理工具有grep&#xff0c;sed&#xff0c;awk。行内将之称为文本三剑客&#xff0c;就功能量和效率来看&#xff0c;awk是当之无愧的文本三…

强化学习-tutorial

强化学习 当你发现收集有标注的数据困难&#xff0c;正确答案人类也不知道是什么的时候&#xff0c;往往是考虑使用RL的时候。尽管机器不知道答案是什么&#xff0c;但是机器会知道什么好&#xff0c;什么不好&#xff0c;通过与环境互动获得奖励。 过程 演算法解RL问题&…

【C++进阶】模板进阶与仿函数:C++编程中的泛型与函数式编程思想

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;C “ 登神长阶 ” &#x1f921;往期回顾&#x1f921;&#xff1a;栈和队列相关知识 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀模板进阶 &#x1f9e9;<&…

C语言概述与历史

引言 C语言是一门历史悠久且影响深远的编程语言。它不仅为后继的许多编程语言奠定了基础&#xff0c;同时因其高效性和灵活性在系统编程和嵌入式开发领域得到了广泛应用。本篇文章将全面介绍C语言的起源与发展、设计目标与理念&#xff0c;以及C语言的标准演化历程&#xff0c;…

MySQL Online DDL原理解读

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…

boost asio异步服务器(3)增加发送队列实现全双工通信

增加发送节点 构造发送节点&#xff0c;管理发送数据。发送节点的类如下。 这个发送节点用于保证发送和接收数据的有效性。 增加发送队列 前边实现的是一个简单的echo服务器&#xff0c;也就是服务器将收到的内容发送给对应的客户端。但是在实际的服务器设计中&#xff0c;服务…