zoukankan      html  css  js  c++  java
  • 内核驱动:中断机制

    A9处理器:EXYNOS4412

    中断:硬件产生(总是需要硬件电路上的一根中断线):USB线是有VCC、GND、D+、D-四根线组成,所以是不能产生中断的;

    中断产生的一般过程:中断源产生中断------>中断控制器(根据中断优先级)------>ARM处理器

    对于4412处理器来说,搞清中断源和中断号的对应关系是一个很复杂的工作具体可参考arch/arm/mach-exynos/include/mach/irqs.h头文件

    ARM平台查找中断号:

    1.芯片内部外设:利用设备的名字在irqs.h中查找中断号;

    2.芯片外部外设:设备的中断连接到4412的GPIO引脚,找到GPIO引脚的GPIO号,然后调用函数gpio_to_irq();

    中断函数的注册:

    1.需要包含头文件<mach/irqs.h>,如果要找4412内部设备的中断号,只能看文件<mach/irqs.h>

    =======================================================

    linux的中断处理机制

    GPIO产生中断,将中断给GPIO控制器,GPIO控制器再将中断交给GIC处理,最后GIC交与cpu做处理:如下图:

    mask:设备上级组织(GIC或者GPIO控制器)一般在中断到达的过程中屏蔽中断;同时,CPU也可以通过控制CPSR寄存器来屏蔽来自GIC的所有中断; 

    中断处理机制

      当中断产生后,内核会保护当前进程的执行现场,并进入异常处理,通过异常像量表找到产生中断的中断号,并由中断号,在内核中找到中断号为100的irq_desc:主要用于描述中断信息,并执行中断处理函数(需要用户有注册行为)。用户在处理中断的过程中,首先要先写好中断处理函数,封装到iqaction并由iqaction想内核进行注册,从而是handler函数有效;

    ps:

    1.linux内核在启动时分配了一个irq_desc的数组,数组中共有NR_IRQS个成员。每个irq_desc中记录对应中断的各类信息,比如中断的处理函数,中断的发生次数等。irq_desc 结构体定义在<linux/irqdesc.h中>

    2.irqaction定义在<linux/interrupt.h>每个irqaction用于封装一个中断处理函数。结构体由驱动人员负责分配。irqaction中包含中断号,中断处理函数指针,中断的执行标志,中断名等。

    3.中断处理函数的返回值为 irq_handler_t类型;定义在<linux/interrupt.h>,如下:

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

    中断处理函数。由驱动负责实现,记录在irqaction中。

    irqreturn_t只有两个值,IRQ_NONE/IRQ_HANDLED。如果中断不是由本设备引起的,则返回IRQ_NONE,否则返回IRQ_HANDLED。
    函数参数irq为中断号,void *为传递给中断处理函数的参数,对应irqaction->dev_id。

    中断处理函数的编写与注册

    驱动人员在设计中断处理函数时,要遵循的要求是:
    (1)可嵌套不可重入
    (2)不能睡眠
    (3)如果硬件有中断的状态寄存器,软件要负责清除中断的标志位。一般来说,如果不清除标志位,设备无法再次产生中断

    (4)中断处理函数的注册和注销

    0.前提

      需要包含的头文件

      #include <linux/interrupt.h>
      #include <mach/irqs.h> //片内外设
      #include <linux/gpio.h> //片外外设
      #include <mach/gpio.h>

    1.确定中断号

      正如刚才如上所述:如果是外部IO中断,那么我们可以通过GPIO号获取中断号:

      eg:#define KEY_IRQ     gpio_to_irq(gpio号);

    2.中断处理函数编写

      中断处理函数的格式:

      eg:

      //参数1:int irq :中断号

      //参数2:void * dev_id :为传递给中断处理函数的参数

      //返回值:IRQ_NONE:中断不是由本设备引起的

                       IRQ_HANDLED:中断是由本设备引起的

      static irqreturn_t  key_service(int irq, void *dev_id)

      {
      //根据硬件要求完成相应工作
      ...
      return IRQ_HANDLED 或 IRQ_NONE;
      }

    3.注册中断处理函数(必须检查返回值)

      u32 flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING;//定义中断的标志:下降沿/上升沿/低电平/高电平触发中断

      int ret;
      ret = request_irq(  KEY_IRQ, /* 中断号 */
                 key_service, /* 中断处理函数 */
                 flags, /* 中断的标志 */
                  "xxx", /* 中断处理函数的名字 */
                  dev_id);/* dev_id为传给中断处理函数的参数,一般会设置为私有结构体的指针,非共享>中断可以为NULL */

      if (ret) {
        printk("Cannot register interrupt handler ");
        return -1;
       }

    4.注销中断处理函数 

      free_irq(irq, dev_id); //参数为中断号和dev_id。 dev_id一定要和request_irq中的最后一个参数一致

    5.屏蔽中断

      1.可以人为关闭(mask)/打开某个中断:
        disable_irq(int irq);
        enable_irq(int irq);
        这两个函数是可以嵌套的,也就是说,如果对一个中断disable了3次,需要调用enable函数3次才能打开对该中断的屏蔽;

      2.还可以屏蔽本cpu的中断:
        local_irq_disable();
        local_irq_enable();

  • 相关阅读:
    [Linux Sets] hosts, wlan and other net-rele
    [Source] 温柔的图片
    [CATARC_2017] 第三周 & 残四周
    [CATARC_2017] 第二周
    ubuntu 安装
    知规矩者混天下言。
    python+selenium的web自动化测试之二(Jenkins自动执行)
    python+selenium的web自动化测试之一(手工执行)
    Python 入门小实例笔记
    Web安全测试工具 Burp Suit 使用简介
  • 原文地址:https://www.cnblogs.com/muzihuan/p/5223839.html
Copyright © 2011-2022 走看看