以s3c2440 ARM9核為例:
一:s3c2440 ARM處理器特性:
1、S3C2440支援60個中斷源,含子中斷源;
2、ARM9采用五級流水線方式;
3、支援外部中斷和内部中斷;
二、s3c2440 支援的寄存器:
2.1 外部中斷寄存器
24個外部中斷占用GPF0-GPF7(EINT0-EINT7),GPG0-GPG15(EINT8-EINT23)。用這些腳做中斷輸入,則必須配置引腳為中斷,并且不要上拉。具體可參考datesheet資料手冊。
寄存器:
EXTINT0-EXTINT2:分别設定EINT0—EINT7、EINT8—EINT15、EINT16—EINT23的觸發方式(高電平觸發、低電平觸發、下降沿觸發、上升沿觸發)。
EINTFLT0-EINTFLT3:控制濾波時鐘和濾波寬度。
EINTPEND:這個是中斷挂起寄存器,清除時要寫1,後面還有幾個是寫1清除。當一個外部中斷(EINT4-EINT23)發生後,那麼相應的位會被置1。為什麼沒有EINT0-EINT3,因為它們分别由SRCPND寄存器的後4位控制。
EINTMASK:這個簡單,是屏蔽中斷用的,也就是說位為1時,此次中斷無效。
2.2 内部中斷寄存器
内部中斷有8個寄存器。
SUBSRCPND:當一個中斷發生後,那麼相應的位會被置1,表示一個中斷發生了。
INTSUBMSK:與上一個是一樣的,中斷屏蔽寄存器。
SRCPND:當一個中斷發生後,那麼相應的位會被置1,表示一個或一類中斷發生了。
INTMSK:用來屏蔽SRCPND寄存器所辨別的中斷。但隻能屏蔽IRQ中斷,不能屏蔽FIQ中斷。
INTMOD:當INTMOD中某位被設定為1時,它對應的中斷被設為FIQ,CPU将進入快速中斷模式。
PRIORITY:用于設定IRQ中斷的優先級。具體使用方法可參考晶片手冊。
INTPND:中斷優先級仲裁器選出優先級最高中斷後,這個中斷在INTPND寄存器中的相應位被置1,随後,CPU進入中斷模式處理它。同一時間内,此寄存器隻有一位被置1。
INTOFFSET:用來表示INTPND寄存器中哪位被置1了,即記錄INTPND中位[x]為1的位x的值。清除INTPND、SRCPND時自動清除。
三、中斷處理流程
1、中斷控制器彙集各類外設發出的中斷信号,然後通知CPU。
2、CPU儲存目前程式的運作環境,然後調用中斷服務程式(ISR),來進行中斷。
3、在ISR中通過讀取外設的相關的寄存器來識别中斷的類型,并進行相應的處理。
4、清除中斷:通過讀寫相關中斷控制寄存器和外設相關寄存器來實作。(注意消除中斷是必要的)
5、恢複被中斷程式的執行環境,繼續執行被中斷的程式。
四、代碼:
main.c
1 int main()
2 {
3 ................
4 //其他部分初始化
5 button_init();
6 init_irq();
7 while(1);
8 return 0;
9 }
interrupt.c
1 /*interrupt registes*/
2 #define SRCPND (volatile unsigned long *)0x4A000000
3 #define INTMOD (volatile unsigned long *)0x4A000004
4 #define INTMSK (volatile unsigned long *)0x4A000008
5 #define PRIORITY (volatile unsigned long *)0x4A00000c
6 #define INTPND (volatile unsigned long *)0x4A000010
7 #define INTOFFSET (volatile unsigned long *)0x4A000014
8 #define SUBSRCPND (volatile unsigned long *)0x4A000018
9 #define INTSUBMSK (volatile unsigned long *)0x4A00001c
10
11 #define EINTMASK (volatile unsigned long *)0x560000a4
12 #define EINTPEND (volatile unsigned long *)0x560000a8
13
14 void init_irq()
15 {
16
17 // 對于EINT4,需要在EINTMASK寄存器中使能它
18 *(EINTMASK) &= ~(1<<4);
19
20
21 // EINT0、EINT1、EINT2、EINT4_7使能
22 *(INTMSK) &= (~(1<<0)) & (~(1<<1)) & (~(1<<2)) & (~(1<<4));
23
24 __asm__(
25 /*開中斷*/
26 "mrs r0,cpsr\n"
27 "bic r0, r0, #0x80\n"
28 "msr cpsr_c, r0\n"
29 :
30 :
31 );
32 }
33
34 void handle_int()
35 {
36 /*讀取産生中斷的源*/
37 unsigned long value = *(INTOFFSET);
38
39 switch(value)
40 {
41 case 0: //EINT0~K4
42 led_on();
43 break;
44
45 case 1: //EINT1~K1
46 led_off();
47 break;
48
49 case 2: //EINT2~K3
50 led_on();
51 break;
52
53 case 4: //EINT4~K2
54 led_off();
55 break;
56
57 default:
58 break;
59 }
60
61 /* 中斷清除 */
62 if(value == 4)
63 *(EINTPEND) = (1 << 4);
64 *(SRCPND) = 1 << value;
65 *(INTPND) = 1 << value;
66 }
start.S
1 irq:
2 sub lr, lr, #4
3 stmfd sp!, {r0-r12, lr} /* 保護現場 */
4 bl handle_int
5 ldmfd sp!, {r0-r12, pc}^ /* 恢複現場,^表示把spsr恢複到cpsr */
五:部分代碼解釋:
sub lr, lr, #4
可參考部落格:http://www.cnblogs.com/yu-chen/p/6281690.html