在具体的 ARM 芯片中会有很多的中断 类型,每一种类型的中断 用以上结构来表示:
struct irqdesc irq_desc[NR_IRQS]; /* NR_IRQS 根据不同的 MCU 会有所区别 */
在通过 request_irq () 函数注册中断 服务程序的时候,将会把中断 向量和中断 服务程序对应起来。
我们来看一下 request_irq 的源码:
int request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
unsigned long irq_flags, const char * devname, void *dev_id)
{
unsigned long retval;
struct irqaction *action;
if (irq >= NR_IRQS || !irq_desc[irq].valid || !handler ||
(irq_flags & SA_SHIRQ && !dev_id))
return -EINVAL;
action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
if (!action) /* 生成 action 结构 */
return -ENOMEM;
action->handler = handler;
action->flags = irq_flags;
action->mask = 0;
action->name = devname;
action->next = NULL;
action->dev_id = dev_id;
retval = setup_arm_irq(irq, action); /* 把中断 号 irq 和 action 对应起来 */
if (retval)
kfree(action);
return retval;
}
其中第一个参数 irq 就是中断 向量,第二个参数即是要注册的中断 服务程序。很多同仁可能疑惑的是,我们要注册的中断 向量号 是怎么确定的呢?这要根据具体芯片的中断 控制器,比如三星的 S3C2410 ,需要通过读取其中的中断 状态寄存器,来获得是哪个设备发生了中断 :
if defined(CONFIG_ARCH_S3C2410)
#include <asm/hardware.h>
.macro disable_fiq
.endm
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
mov r4, #INTBASE @ virtual address of IRQ registers
ldr /irqnr, [r4, #0x8] @ read INTMSK 中断 掩码寄存器
ldr /irqstat, [r4, #0x10] @ read INTPND 中断 寄存器
bics /irqstat, /irqstat, /irqnr
bics /irqstat, /irqstat, /irqnr
beq 1002f
mov /irqnr, #0
1001: tst /irqstat, #1
bne 1002f @ found IRQ
add /irqnr, /irqnr, #1
mov /irqstat, /irqstat, lsr #1
cmp /irqnr, #32
bcc 1001b
1002:
.endm
.macro irq_prio_table
.endm