Linux中断

前言:

一.问:CPU为什么有中断机制? (本质:外设的处理速度要远远慢于CPU的处理速度)


明确:计算机系统除了CPU,还有各种外设;

明确:外设的处理速度要远远慢于CPU的处理速度;

以CPU读取串口为例,假如没有中断机制,CPU为了避免串口数据的丢失,只能采用轮询方式(CPU原地空转),
等待串口数据的到来;采用这种方式,CPU只能做一件事情,大大降低了CPU的利用率;
如果采用中断机制,CPU如果发现串口数据不可用(数据没有到来),CPU去做别的事情,一旦串口来数,
串口给CPU发送一个中断信号 (嗨,CPU,我数据准备就绪,请来处理),CPU一旦接受到了中断信号,CPU停止手头的工
作转去处理串口数据,处理完毕,接着执行原先被打断的工作,此时CPU至少2件事情,大大提高了CPU的利用率!


问: CPU和外设的中断信号的硬件处理过程
明确:外设产生的中断电信号不会直接到达CPU,首先要经过中断控制器,经过中断控制器的处理以后,最终中断控制器决定是否再给CPU产生一个中断电信号;

中断控制器所作的内容:
1.能够使能或者屏蔽某个外设中断信号;
2.能够指定外设中断的优先级;
3.能够获取中断的状态;

注意:以上操作都是中断硬件操作,没有软件参与;
一旦CPU接受到了中断信号,CPU开始处理中断,此时会进入软件处理中断的过程;

问:中断的软件处理过程

如下图所示:


问:中断的编程实现步骤
答:

1.编写建立异常向量表的代码
2.编写保护现场的代码
3.编写中断处理程序
4.编写恢复现场的代码

切记:不管是裸板程序还是基于某个操作系统,中断编程四个步骤固定不变;

问:linux系统中断编程步骤
linux系统已将中断编程的第1,2,4三个步骤已经帮你实现,对于驱动开发者只需完成第3步即可,完成中断处理函数即可!

明确:中断的处理过程都是在内核中完成,中断编程的四步骤代码都在内核中!

Linux中断编程

问:如何在linux内核中编写一个硬件中断对应的中断处理函数呢?
答:
如果要向内核添加某个外设中断的中断处理函数,只需要利用以下两个函数即可完成工作:
*************************************************

static inline int __must_check request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
const char *name, void *dev)


函数功能:
1.首先向内核申请硬件中断资源,CPU的硬件中断对于内核来说是一种宝贵的资源,
如果要使用,必须向内核中去申请

2.一旦硬件中断资源申请成功,最后注册这个硬件对应的中断处理
函数到内核,将来这个硬件中断一般被触发,内核就会执行对应的中断处理
函数

参数说明:
irq:传递硬件中断在内核中的一个软件编号,这个软件编号统称中断号,一
个硬件中断有唯一的一个中断号,
例如:
XEINT0(CPU的第一个硬件中断管脚) ,
它对应的内核中断号为IRQ_EINT(0) ,
XEINT1(CPU的第二个硬件中断管脚) ,
它对应的内核中断号为IRQ_EINT(1)

handler:中断处理函数,将来硬件中断处理,内核执行此函数

flags:中断标志,常见的中断标志如下:
如果此中断为外部中断(中断线能看到),中断标志如用以下即可:
IRQF_TRIGGER_FALLING; //下降沿触发
IRQF_TRIGGER_RISING; //上升沿触发
IRQF_TRIGGER_LOW; //低电平触发
IRQF_TRIGGER_HIGH; //高电平触发
以上属性给中断控制器使用;
如果此中断为内部中断,中断标志给0

name:中断名称,将来出现在 cat /proc/interrupts

dev:给中断处理函数传递的参数,如果不传递参数给NULL
 *************************************************
void free_irq(unsigned int irq, void *dev);
作用:
如果中断资源不使用,记得要释放和删除中断处理函数
irq:硬件中断对应的中断号
dev:给中断处理函数传递的参数,
切记,此参数一定要和注册中断时传递的参数要一样!否则内核崩溃!

中断处理函数的原型:
*************************************************
irqreturn_t 中断处理函数名(int irq, void *dev)
{
...
return IRQ_HANDLED; //中断处理完毕
或者
return IRQ_NONE; //中断不做处理
}

irq:保存硬件中断对应的中断号
dev:保存注册中断时传递来的参数

案例:

编写XEINT0中断驱动程序
#include <linux/init.h>
#include <linux/module.h>
#include <linux/irq.h>
#include <linux/interrupt.h>

//中断处理函数
static irqreturn_t button_isr(int irq, void *dev)
{
    printk("%s\n", __func__);
    return IRQ_HANDLED;
}

static int btn_init(void)
{
    //申请中断和注册中断处理函数
    request_irq(IRQ_EINT(0),
                button_isr,
        IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,
                "KEY_UP",
                NULL);
    return 0;
}

static void btn_exit(void)
{
    //释放中断
    free_irq(IRQ_EINT(0), NULL);
}
module_init(btn_init);
module_exit(btn_exit);
MODULE_LICENSE("GPL");
***去除官方的按键驱动
cd /opt/kernel
make menuconfig
Device Drivers->
Input device support --->
[*] Keyboards --->
[*]S3C gpio keypad support //去掉
make zImage
cp arch/arm/boot/zImage /tftpboot
重启开发板

ARM执行:
1.insmod btn_drv.ko
2.操作按键,观察打印信息      

  


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章