linux共享中断处理程序,Linux中断处理系统的架构与共享中断

一、裸机程序中的中断编程与有操作系统下的中断编程的区别

当硬件发生中断时,CPU硬件会自动执行4个操作,从而无条件跳转到异常向量处(参见ARM体系结构与编程中关于异常和中断的内容)

异常向量处放置了1条跳转指令,跳转到中断异常处理程序。编写裸机程序需要想办法将这条指令放置到异常向量处,而操作系统已经帮我们做了

编写裸机程序当然需要编写中断异常处理程序去完成诸如环境保护(CPU寄存器入栈)、获取中断号、中断异常结束返回之类的操作,而操作系统已经帮我们全部都做了(啊,伟大的操作系统!)。然后调用中断处理程序(也就是通常所说的ISR)。

不同硬件的中断处理程序当然肯定不同,所以要求操作系统把这个也帮你写了,实在是太过分了。所以,编写ISR就是驱动编写者的责任了!当然,裸机程序的编写者肯定也要编写ISR

编写ISR,对于裸机程序编写者而言百无禁忌,想怎么搞就怎么搞。但对于有操作系统的情况下则要受到一些限制(当然不能无法无天,否则还要操作系统这个领导来干嘛?),例如:不能睡眠,要用虚地址访问硬件等

特别说明:操作系统在启动过程中会初始化中断子系统,这会在操作系统内部将所有中断的逻辑上的中断号(整数)与物理的中断线进行关联。因此当驱动调用request_irq告知操作系统将中断号与中断处理程序进行关联时,操作系统就能够将物理的中断线与中断处理程序进行关联,从而当某个物理中断产生时,操作系统有能力知道应该回调哪一个中断处理程序。

一、Linux中断处理系统的架构(详情参阅《嵌入式linux应用开发完全手册》P401-P403)

3种结构:irq_desc、irq_chip、irqaction

发生中断时,CPU执行中断异常向量vector_irq的代码

vector_irq最终会调用中断处理的总入口函数asm_do_IRQ

asm_do_IRQ会根据中断号为下标来调用irq_desc数组中对应元素中的handle_irq函数

handle_irq会使用chip成员中的函数来设置硬件,例如清除中断等

handle_irq逐个调用action链表中注册的处理函数

中断处理系统的初始化就是构造irq_desc数组元素中的handle_irq、 chip等成员

用户注册中断就是构造action链表;释放中断就是从action链表中去除不需要的项

二、关于共享中断的说明

共享同一中断号的ISR,通过request_irq中的同一个中断号注册到系统中的同一个中断链表中,而dev_id则用于区分该中断链表中不同的ISR,因此注册时dev_id不能相同,也不能为NULL

共享中断的所有注册,其第3个参数都必须指明IRQF_SHARED,以表示是注册共享中断

中断发生时,系统会顺次调用中断链表中所有的ISR。因此ISR一定要根据自己是否真的发生了中断,来返回IRQ_HANDLED或IRQ_NONE

释放中断free_irq的第2个参数dev_id,正是用来查找中断链表中要被释放的中断

三、共享中断实例

dummyisr.c如下:

11 static irqreturn_t dummy_isr(int irq, void *dev_id)

12 {

13 static int

haveint = 0;

14 if (haveint ==

0) {

15 printk(KERN_NOTICE "dummy_isr will return IRQ_NONE");

16 haveint = 1;

17 return IRQ_RETVAL(IRQ_NONE);

18 } else {

19 printk(KERN_NOTICE "dummy_isr will return IRQ_HANDLED");

20 haveint = 0;

21 return IRQ_RETVAL(IRQ_HANDLED);

22 }

23 }

24

25 struct cdev dummy_cdev;

26 static int __init my_init(void)

27 {

28 int err;

29 err =

request_irq(IRQ_EINT19, dummy_isr,

IRQF_TRIGGER_FALLING | IRQF_SHARED, "dummy_isr",

(void

*)&dummy_cdev);

30 if (err)

{

31 printk(KERN_WARNING "request_irq IRQ_EINT19 for dummy_isr failed,

error number is %d\n", err);

32 } else {

33 printk(KERN_NOTICE "register dummy_isr succeed\n");

34 }

35 return 0;

36 }

37 static void __exit my_fini(void)

38 {

39 free_irq(IRQ_EINT19, (void *)&dummy_cdev);

40 printk(KERN_NOTICE "unregister dummy_isr succeed\n");

41 }

s3c24xx_buttons_v2.5.c如下:

63 {IRQ_EINT19, IRQF_TRIGGER_FALLING

| IRQF_SHARED,

"KEY1"},

175 for (i = 0;

i < BUTTON_NUM; i++) {

177 err = request_irq(buttons_dev.button_irqs[i].irqno,

buttons_interrupt,

178 buttons_dev.button_irqs[i].flags,

buttons_dev.button_irqs[i].name,

179 (void

*)&buttons_dev);

s3c24xx_buttons_v2.5.c与dummyisr.c注册了共享中断IRQ_EINT19,且均遵循了二中的1、2两点。(请务必注意在dummyisr中request_irq时除了要使用IRQF_SHARED标志外,还要使用IRQF_TRIGGER_FALLING标志,因为在button驱动中采用了该标志,二者必须一致,否则在注册第2个中断时总是不能成功,会出现如下错误。

# insmod s3c24xx_buttons.ko

buttons initialized

# ./button_test &

# open success

输入回车

# insmod dummyisr.ko

request_irq IRQ_EINT19 for dummy_isr failed, error number is

-16

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值