天天看點

ARM中斷處理過程

以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