中断号和芯片中断引脚的关系

2009年8月17日 | 由 helight | 1300字 | 阅读大约需要3分钟 | 归档于 kernel | 标签 #kernel

一直以来搞不懂这个中断号的来历,总以为是中断控制器自己规定的一个号,但是最近在看了s3c2440的中断控制后才发现不是这么一回事.2440的中断处理只能处理32个中断,但是其在内核中出现的中断号却有51,58等.而且它的外部中断INT4~7共享一个中断控制寄存器的一位,INT8~23也是共享控制寄存器的一位.我就好奇了,它怎么区分这些中断呢?而且在内核代码中它又很清楚的区分了这些中断.如下面的代码(2.6.13).

"include/asm-arm/arch-s3c2410/irqs.h"
.....
/* interrupts generated from the external interrupts sources */
#define IRQ_EINT4      S3C2410_IRQ(32)     /* 48 */

#define IRQ_EINT5      S3C2410_IRQ(33)

#define IRQ_EINT6      S3C2410_IRQ(34)

#define IRQ_EINT7      S3C2410_IRQ(35)

#define IRQ_EINT8      S3C2410_IRQ(36)

#define IRQ_EINT9      S3C2410_IRQ(37)

#define IRQ_EINT10     S3C2410_IRQ(38)

#define IRQ_EINT11     S3C2410_IRQ(39)

#define IRQ_EINT12     S3C2410_IRQ(40)

#define IRQ_EINT13     S3C2410_IRQ(41)

#define IRQ_EINT14     S3C2410_IRQ(42)

#define IRQ_EINT15     S3C2410_IRQ(43)

#define IRQ_EINT16     S3C2410_IRQ(44)

....

在看了N久之后才发现了其中的缘由: 在初始化的时候,在相关的启动代码中将这些中断源和中断号进行了一一的映射,然后再初始化irq_desc.而在执行中断的时候就根据中断控制器的一些状态和控制寄存器来进行转换,将相应的中断源转换成中断号,再进行中断例程的执行.这里针对于2440的进行简单分析一下: 在"arch/arm/kernel/entry-armv.S” 的 irq_handler宏就是处理中断的,代码如下:

/*
* Interrupt handling.  Preserves r7, r8, r9
*/
.macro  irq_handler
1:      get_irqnr_and_base r0, r6, r5, lr  //而这里就是将中断源转换成相应中断号的一个宏,最后将中断号放到r0中
movne   r1, sp
@
@ routine called with r0 = irq number, r1 = struct pt_regs *
@
adrne   lr, 1b
bne     asm_do_IRQ
//执行一般中断,函数原型:"arch/arm/kernel/irq.c"
// asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
//可以看出这里需要的参数有中断号和CPU发生中断时需要保存的寄存器

#ifdef CONFIG_SMP

/*
* XXX
*
* this macro assumes that irqstat (r6) and base (r5) are
* preserved from get_irqnr_and_base above
*/
test_for_ipi r0, r6, r5, lr
movne   r0, sp
adrne   lr, 1b
bne     do_IPI    //执行CPU内部中断或是异常
#endif


.endm

而对于中断源到中断号的转换宏get_irqnr_and_base这里要分析一下: 在"include/asm/arch/entry-macro.S” 中定义:

.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
//irqnr: 是用来存放最后的中断号的,也就是上面传递过来的r0
//irqstat: 用来存放中断状态的,即上面的r6
//base: 这个在这宏当中没有使用
//tmp:这个是用来存放中断控制器基地址的,
//下面在获取个个控制寄存器值的时候都是在这个地址的基础之上加相应的值
mov     \tmp, #S3C24XX_VA_IRQ //获取中断控制器基地址(是虚地址)
ldr     \irqnr, [ \tmp, #0x14 ]         @ get irq no
30000:
teq     \irqnr, #4
teqne   \irqnr, #5
beq     1002f                           @ external irq reg
.....
//这里即是对EINT4~EINT23的中断号的映射,
//RQ_EINT4是一个基本号,就是这个号和前面的中断号是断开的,其间这些中断号是预留给其它一些总线下的设备使用的.
//而之后的中断号都是在这个号的基础上不断+1的,这里是其代码.
mov     \irqnr, #IRQ_EINT4              @ start extint nos
mov     \irqstat, \irqstat, lsr#4       @ ignore bottom 4 bits
10021:
movs    \irqstat, \irqstat, lsr#1
//这里是根据起中断状态再判断到底是那一个中断发生了
bcs     1004f
add     \irqnr, \irqnr, #1
cmp     \irqnr, #IRQ_EINT23
ble     10021b
.....

这里就完成了中断引脚和中断号的对应关系,哎,终于搞明白了!!!但是个个体系结构和中断控制器的映射方式应该是不一样的,这个只是真对于s3c2440来说的 这里就完成了中断