一直以來搞不懂這個中斷號的來曆,總以為是中斷控制器自己規定的一個號,但是最近在看了
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
,
1
b
- 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
,
1
b
- 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
1002
f
@
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
1004
f
- add
/
irqnr
, /
irqnr
, #
1
- cmp
/
irqnr
, #
IRQ_EINT23
- ble
10021
b
- .....
這裡就完成了中斷引腳和中斷號的對應關係,哎,終於搞明白了!!!但是個個體繫結構和中斷控制器的映射方式應該是不一樣的,這個只是真對於s3c2440來說的
這裡就完成了中斷