Linux设备驱动编程中的中断与定时器处理
所谓中断是指CPU在执行过程中,出现某些突发时间急待处理,CPU必须暂停执行当前的程序,转去处理突发事件,处理完毕后CPU又返回原程序被中断的位置并继续执行。
中断分为(根据中断源来分): 内部中断(软件中断指令,溢出,除法错误等)【例如操作系统从用户态切换到内核态需借助CPU内部的软件中断】。
外部中断(中断源来自CPU外部,由外设提出请求)。
中断分为(根据是否可屏蔽): 可屏蔽中断 不可屏蔽中断
非向量中断:多个中断共享一个地址。 (由软件判断中断标志来识别具体是哪个中断)。
非向量中断服务程序典型结构:
irq_handler()
{
...
int int_src=read_int_status(); //读硬件的中断相关寄存器
switch(int_src) //判断中断源
{
case DEV_A:
dev_a_handler();
break;
dev_b_handler();
break;
...
default:
break;
}
...
}
Linux内核中断
第一部分获取中断(开启硬件中断)
一、中断的申请注销:
1)中断的申请
int request_irq(unsigned int irq,irq_handler_t handler,unsigned long irqflags,const char *devname,void *dev_id);
2)中断的注销
void free_irq(unsigned int irq,void *dev_id)
3)中断处理函数
static irqreturn_t irq_handle(int irq,void *dev_id);
参数:irq:表示中断号,这个参数还保留由于历史遗留问题,往后可能越来越没用了。由于第二个参数信息更强大
dev__id:就是request_irq()中void *dev_id参数。
二、中断申请函数参数
int request_irq(unsigned int irq,irq_handler_t handler,unsigned long irqflags,const char *devname,void *dev_id)
1)参数:
irq:是要申请的硬件中断号。
handler:是向系统注册的中断处理函数,是一个回调函数,中断发生时,系统调用这个函数,dev_id参数将被传递给它。
irqflags:是中断处理的属性,
a)若设置了IRQF_DISABLED,则表示中断处理程序是快速处理程序,快速处理程序被调用时屏蔽所有中断,慢速处理程序不屏蔽;
b)若设置了 IRQF_SHARED,则表示多个设备共享中断;//在另一篇文章会提到
c)若设置了IRQF_SAMPLE_RANDOM,表示对系统熵有贡献,对系统获取随机数有好处。
Tip:(flag是可以通过或的方式同时使用的)
devname:设置中断名称,通常是设备驱动程序的名称 在cat /proc/interrupts中可以看到此名称。
dev_id:在中断共享时会用到,一般设置为这个设备的设备结构体或者不使用时为NULL。因为在共享中断中同一个中断线(或可以说同一个中断号)可 能挂载好几个设备,当使用void free_irq(unsigned int irq, void *dev_id)时,根据irq和dev_id可以找到中断线为irq上的标识为dev_id的某个具体设备。dev_id也经常在不是共享中断中的驱动 传递数据
2)返回值:
a)request_irq()返回0表示成功;
b)返回-EINVAL表示无效的参数,如果返回这个值,应该看看传递给request_irq()的参数是否正确;
c)返回-EBUSY表示中断已经被占用且不能共享;
d)返回ENOMEM表示内存不足。嵌入式系统由于内存资源有限,经常会发生这样的错误。
3)扩展---unsigned long irqflags值
在include\linux\interrupt.h中
/* * These correspond to the IORESOURCE_IRQ_* defines in * linux/ioport.h to select the interrupt line behaviour. When * requesting an interrupt without specifying a IRQF_TRIGGER, the * setting should be assumed to be "as already configured", which * may be as per machine or firmware initialisation. */#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#define IRQF_TRIGGER_MASK (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW | \ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)#define IRQF_TRIGGER_PROBE 0x00000010/* * These flags used only by the kernel as part of the * irq handling routines. * * IRQF_DISABLED - keep irqs disabled when calling the action handler * IRQF_SAMPLE_RANDOM - irq is used to feed the random generator * IRQF_SHARED - allow sharing the irq among several devices * IRQF_PROBE_SHARED - set by callers when they expect sharing mismatches to occur * IRQF_TIMER - Flag to mark this interrupt as timer interrupt * IRQF_PERCPU - Interrupt is per cpu * IRQF_NOBALANCING - Flag to exclude this interrupt from irq balancing * IRQF_IRQPOLL - Interrupt is used for polling (only the interrupt that is * registered first in an shared interrupt is considered for * performance reasons) */#define IRQF_DISABLED 0x00000020#define IRQF_SAMPLE_RANDOM 0x00000040#define IRQF_SHARED 0x00000080#define IRQF_PROBE_SHARED 0x00000100#define IRQF_TIMER 0x00000200#define IRQF_PERCPU 0x00000400#define IRQF_NOBALANCING 0x00000800#define IRQF_IRQPOLL 0x00001000 |
Tip:下面是老版本(2.4内核irqflags的值),不要在新版本使用。(2.6 内核及2.6以上内核都为新内核)
/* * Migration helpers. Scheduled for removal in 9/2007 * Do not use for new code !//不要的新版本使用,2.6 内核及2.6以上内核都为新内核 */static inlineunsigned long __deprecated deprecated_irq_flag(unsigned long flag){ return flag;}#define SA_INTERRUPT deprecated_irq_flag(IRQF_DISABLED)#define SA_SAMPLE_RANDOM deprecated_irq_flag(IRQF_SAMPLE_RANDOM)#define SA_SHIRQ deprecated_irq_flag(IRQF_SHARED)#define SA_PROBEIRQ deprecated_irq_flag(IRQF_PROBE_SHARED)#define SA_PERCPU deprecated_irq_flag(IRQF_PERCPU)#define SA_TRIGGER_LOW deprecated_irq_flag(IRQF_TRIGGER_LOW)#define SA_TRIGGER_HIGH deprecated_irq_flag(IRQF_TRIGGER_HIGH)#define SA_TRIGGER_FALLING deprecated_irq_flag(IRQF_TRIGGER_FALLING)#define SA_TRIGGER_RISING deprecated_irq_flag(IRQF_TRIGGER_RISING)#define SA_TRIGGER_MASK deprecated_irq_flag(IRQF_TRIGGER_MASK) |
三、使用模板
使用步骤:以外部中断为例
a)定义结构体,相当于定义(void *dev_id)中的(void *)
struct pin_desc //声明一个引脚描述的结构体pin_desc
{ unsigned int pin; //引脚值,参考数据手册及板子电路原理图
unsigned int key_val: //值自己随便定义;看自己的项目需要
//...
};
b)实例化结构体,相当于(void *dev_id)中的 dev_id
struct pin_desc pins_desc[3]=
{ //实例化结构体
{S3C2410_GPF0,0x01}, //S3C2410_GPFn在内核中定义好了
{S3C2410_GPF2,0x02},
{S3C2410_GPG3,0x03},
};
c)定义中断处理函数
static irqreturn_t irq_handle(int irq,void *dev_id)
{
struct pin_desc *pindesc=(struct pin_desc *)dev_id;
//...
return IRQ_RETVAL(IRQ_HANDLED); //返回IRQ_HANDLED表示中断已经处理
d)申请中断
|
3
|
request_irq(IRQ_EINT0, irq_handle, IRQ_TYPE_EDGE_BOTH, "s2", &pins_desc[0]);//IRQ_EINTn在内核中定义好了 request_irq(IRQ_EINT2, irq_handle, IRQ_TYPE_EDGE_BOTH, "s3", &pins_desc[1]); request_irq(IRQ_EINT11, irq_handle, IRQ_TYPE_EDGE_BOTH, "s4", &pins_desc[2]); |
e)释放内存
free_irq(IRQ_EINT0, &pins_desc[0]);free_irq(IRQ_EINT2, &pins_desc[1]);
|
Tip:可以直接将IRQ_EINTn也在pins_desc定义,然后
int i = 0; for(i = 0; i < 3; i++){ free_irq(pins_desc[i].irqnum, &pins_desc[i]); } |
有一个函数很常用,需要留意:gpio_to_irq();等到中断号。
Linux设备驱动编程中的中断与定时器处理的更多相关文章
- 介绍linux设备驱动编程
目前,Linux软件工程师大致可分为两个层次: (1)Linux应用软件工程师(Application Software Engineer): 主要利用C库函数和Linux API进行应用 ...
- Linux设备驱动编程之复杂设备驱动
这里所说的复杂设备驱动涉及到PCI.USB.网络设备.块设备等(严格意义而言,这些设备在概念上并不并列,例如与块设备并列的是字符设备,而PCI.USB设备等都可能属于字符设备),这些设备的驱动中又涉及 ...
- Linux设备驱动编程---miscdevice杂类设备的使用方法
miscdev简称杂类设备杂类设备就是对字符设备驱动做一个封装,方便简单使用杂类设备封装字符设备需要包含的头文件:#include <linux/miscdevice.h>(1)杂类设备的 ...
- Linux设备驱动中断机制
[主要内容] Linux设备驱动编程中的中断与定时器处理 [正文] 一.基础知识 1.中断 所谓中断是指CPU在执行程序的过程中,出现了某些突发事件急待处理,CPU必须暂停执行当前的程序,转去处理突发 ...
- Hasen的linux设备驱动开发学习之旅--时钟
/** * Author:hasen * 參考 :<linux设备驱动开发具体解释> * 简单介绍:android小菜鸟的linux * 设备驱动开发学习之旅 * 主题:时钟 * Date ...
- Linux设备驱动开发详解-Note(5)---Linux 内核及内核编程(1)
Linux 内核及内核编程(1) 成于坚持,败于止步 Linux 2.6 内核的特点 Linux 2.6 相对于 Linux 2.4 有相当大的改进,主要体现在如下几个方面. 1.新的调度器 2.6 ...
- linux 设备驱动概述
linux 设备驱动概述 目前,Linux软件工程师大致可分为两个层次: (1)Linux应用软件工程师(Application Software Engineer): 主要利用C库函数和 ...
- LINUX设备驱动模型之class
转自 https://blog.csdn.net/qq_20678703/article/details/52754661 1.LINUX设备驱动模型中的bus.device.driver,.其中bu ...
- linux设备驱动第五篇:驱动中的并发与竟态
综述 在上一篇介绍了linux驱动的调试方法,这一篇介绍一下在驱动编程中会遇到的并发和竟态以及如何处理并发和竞争. 首先什么是并发与竟态呢?并发(concurrency)指的是多个执行单元同时.并行被 ...
随机推荐
- Python入门一:基本数据类型
作为一个刚入门编程的大一狗,第一次写博客,希望能对自己学的知识进行巩固和提升,也希望记录自己成长的过程. 学习Python,一是因为暑假学的c++头疼,听说Python简单,那我就试试吧,二是因为Py ...
- #Leet Code# Gray Code
描述: 要求相邻数2进制差一位 先获得n-1的列表表示小于 2^(n-1) 的符合要求的列表,加上最高位的加成 2^(n-1) 就是大于等于 2^(n-1) 的符合要求的列表,后者翻转一下就能够与前者 ...
- Linux中的文件上传下载
1.部署ftp服务器 2.安装bypy python 客户端(还没试过,先记录一下) https://www.v2ex.com/t/124886
- 在Linux系详解Linux bash中的变量
(大讲台:国内首个it在线教育混合式自适应学习) 统中进行日常运维或者是编写脚本时,变量是再熟悉不过的了,但这些变量都有哪些类型,具体的用法又有哪些差异呢?本文整理分享给大家: 一.bash变量类型: ...
- 关于javac编译时出现“非法字符:\65279”的解决方法
一般用UE或记事本编辑过的UTF-8的文件头会加入BOM标识,该标识由3个char组成.在UTF-8的标准里该BOM标识是可有可无的,Sun 的javac 在编译带有BOM的UTF-8的格式的文件时会 ...
- LCA——倍增求解
LCA,即最近公共祖先,用于解决树上两点的最近公共祖先问题. ; lca(1,2)=3;(原谅我的绘画水平) LCA的求解有三种算法(我知道的)——tarjan,倍增,线段树(我只会两种),NOIp之 ...
- js中的ajax的运用
XMLHttpRequest对象 IE7+,FireFox,Chrome,Opera,Safari创建XHR对象: var xhr=new XMLHttpRequest(); 创建XHR对象的兼容性写 ...
- 解释型语言和编译型语言的不同以及Python如何运行
计划写关于Python中如何实现属性管理.函数(或类方法)管理.类管理的几篇成系列的文章. 而这篇文章写在这个系列之前,希望对后面几篇文章的理解有所帮助. 老实说,我也是在网上搜索了一些资料才写的这篇 ...
- python机器学习库
http://scikit-learn.org/stable/install.html
- StatsD!次世代系统监控的核心
在互联网业务蒸蒸日上的今时今日,系统架构日渐复杂,随着软件产品和工程团队的变革,许多开源的监控工具应运而生,其中有一些相当出名,比如 Zabbix.Nagios 还有 StatsD.也有一些问题被大家 ...