所谓中断是指CPU在执行过程中,出现某些突发时间急待处理,CPU必须暂停执行当前的程序,转去处理突发事件,处理完毕后CPU又返回原程序被中断的位置并继续执行。

中断分为(根据中断源来分):  内部中断(软件中断指令,溢出,除法错误等)【例如操作系统从用户态切换到内核态需借助CPU内部的软件中断】。

外部中断(中断源来自CPU外部,由外设提出请求)。

中断分为(根据是否可屏蔽):  可屏蔽中断   不可屏蔽中断

  中断分为 (根据中断入口跳转方法的不同): 向量中断:采用向量中断的CPU通常为不同的中断分配不同的中断号,不同中断号的中断有不同的入口地址。

非向量中断:多个中断共享一个地址。 (由软件判断中断标志来识别具体是哪个中断)。

非向量中断服务程序典型结构:

irq_handler()

{

...

int int_src=read_int_status();        //读硬件的中断相关寄存器

switch(int_src)                       //判断中断源

{

case DEV_A:

dev_a_handler();

break;

                            case DEV_B:

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 inline
unsigned 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]);

free_irq(IRQ_EINT11, &pins_desc[2]);

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设备驱动编程中的中断与定时器处理的更多相关文章

  1. 介绍linux设备驱动编程

    目前,Linux软件工程师大致可分为两个层次: (1)Linux应用软件工程师(Application Software Engineer):       主要利用C库函数和Linux API进行应用 ...

  2. Linux设备驱动编程之复杂设备驱动

    这里所说的复杂设备驱动涉及到PCI.USB.网络设备.块设备等(严格意义而言,这些设备在概念上并不并列,例如与块设备并列的是字符设备,而PCI.USB设备等都可能属于字符设备),这些设备的驱动中又涉及 ...

  3. Linux设备驱动编程---miscdevice杂类设备的使用方法

    miscdev简称杂类设备杂类设备就是对字符设备驱动做一个封装,方便简单使用杂类设备封装字符设备需要包含的头文件:#include <linux/miscdevice.h>(1)杂类设备的 ...

  4. Linux设备驱动中断机制

    [主要内容] Linux设备驱动编程中的中断与定时器处理 [正文] 一.基础知识 1.中断 所谓中断是指CPU在执行程序的过程中,出现了某些突发事件急待处理,CPU必须暂停执行当前的程序,转去处理突发 ...

  5. Hasen的linux设备驱动开发学习之旅--时钟

    /** * Author:hasen * 參考 :<linux设备驱动开发具体解释> * 简单介绍:android小菜鸟的linux * 设备驱动开发学习之旅 * 主题:时钟 * Date ...

  6. Linux设备驱动开发详解-Note(5)---Linux 内核及内核编程(1)

    Linux 内核及内核编程(1) 成于坚持,败于止步 Linux 2.6 内核的特点 Linux 2.6 相对于 Linux 2.4 有相当大的改进,主要体现在如下几个方面. 1.新的调度器 2.6 ...

  7. linux 设备驱动概述

    linux 设备驱动概述 目前,Linux软件工程师大致可分为两个层次: (1)Linux应用软件工程师(Application Software Engineer):       主要利用C库函数和 ...

  8. LINUX设备驱动模型之class

    转自 https://blog.csdn.net/qq_20678703/article/details/52754661 1.LINUX设备驱动模型中的bus.device.driver,.其中bu ...

  9. linux设备驱动第五篇:驱动中的并发与竟态

    综述 在上一篇介绍了linux驱动的调试方法,这一篇介绍一下在驱动编程中会遇到的并发和竟态以及如何处理并发和竞争. 首先什么是并发与竟态呢?并发(concurrency)指的是多个执行单元同时.并行被 ...

随机推荐

  1. ecshop会员中心增加订单搜索功能

    在user.php中的act=order_list中增加以下程序. $order_sn = isset($_REQUEST['order_sn'])?$_REQUEST['order_sn']:''; ...

  2. Python之路----文件操作

    文件操作 1.能调用方法的一定是对象,比如数值.字符串.列表.元组.字典,甚至文件也是对象,Python中一切皆为对象. str1 = 'hello' str2 = 'world' str3 = ' ...

  3. 用PLSQL Developer粘贴数据的时候报oracle variant conversion error for variable v0

    参考文章:http://bugcool.blog.51cto.com/2080571/664434 两个数据库表对着copy粘贴的时候,报这个错.只是我这边不是顺序不对,不知道为什么其中的一行换行了. ...

  4. Mac操作系统常用快捷键

    复制:cmd+c      粘贴:cmd+v      剪切:先cmd+c,再cmd+opt+v 显示桌面:cmd+F3      切换输入法:cmd+space 打开Spotlight:ctrl+s ...

  5. 一步步学习NHibernate(2)——配置NHibernate的环境

    请注明转载地址:http://www.cnblogs.com/arhat 第二章 环境搭建 在上一章中,我们知道了NHibernate是用来干什么的了,那么今天在本章中,我们开始搭建NHibernat ...

  6. 开发软件设计模型 visual studio UML

    http://www.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/ http://msdn.microsoft ...

  7. 聊聊iOS开发中耳机的那点事(监听耳机拔插、耳机线控)-b

    如果说一个项目出现的最重大的事故,那无疑就是开发人员使用了不可控的元素. 前言 iOS开发当中有关于视音频播放的开发不在少数,用户时常会使用到一种输出设备,那就是"耳机",这一篇博 ...

  8. linux挂载详解

    一 .linux文件结构 文件结构是文件存放在磁盘等存贮设备上的组织方法.主要体现在对文件和目录的组织上.目录提供了管理文件的一个方便而有效的途径. linux使用标准的目录结构,在安装的时候,安装程 ...

  9. 输出排名第k的法雷级数的值;

    #include<cstdio> #include<cstring> using namespace std; int k,n; void dfs(int a,int b,in ...

  10. 处理MySQL数据库出现大量Locked的一个案例 (转)

    本文转自:http://blog.itpub.net/7607759/viewspace-696781/ 做为一款轻量级数据库软件,MySQL在使用过程中遇到访问速度慢,或者无法响应这类的问题,解决方 ...