歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

嵌入式學習之ARM中斷編程

一、中斷控制寄存器

ARM微處理器支持7種工作模式,分別為:

1. 用戶模式(Usr)            用於正常執行程序

2. 快速中斷模式(FIQ)    用於高速數據傳輸

3. 外部中斷模式(IRQ)  用於通常的中斷處理

4. 管理模式(SVC)          操作系統使用的保護模式(高權限),復位和軟件中斷進入

5. 數據訪問終止模式(abt)  當數據或指令預取終止時進入該模式,可用於虛擬內存及存儲保護

6. 系統模式(sys)            運行均有特權的操作系統任務

7. 未定義指令終止模式(und)  用於支持硬件協處理器的軟件仿真(浮點、微量運算)

通過軟件編程可以實現各個模式之間進行切換,各個模式所占的寄存器如下圖所示:

每種中斷模式除了共同的寄存器R0~R15這16個寄存器之外,還包括CPSR即當前程序狀態寄存器(current programe status register),CPSR中的各個位用於指明當前程序所處的中斷狀態和模式,寄存器的各位作用如下:

M0~M4用於表示程序當前工作的中斷模式,對應於如下各個工作模式:

T位用於指定當前CPU是出去Thumb(16位)還是處於ARM(32位)狀態;

N位:N=1表示運算的結果為負數;N=0 表示運算的結果為正數或零;

Z 位:Z=1 表示運算的結果為零;Z=0表示運算的結果為非零;

C位:進位、借位標記位:當運算結果產生了進位時(無符號數溢出),C=1,否則C=0。

二、中斷控制編程:

通過對中斷控制寄存器中的各位進行編程控制可以實現中斷,各控制位參見http://www.linuxidc.com/Linux/2013-06/86133.htm,下面主要介紹他們的編程實現。

void init_irq( )
{
    // S2,S3對應的2根引腳設為中斷引腳 EINT0,ENT2
    GPFCON &= ~(GPF0_msk | GPF2_msk);
    GPFCON |= GPF0_eint | GPF2_eint;

    // S4對應的引腳設為中斷引腳EINT11
    GPGCON &= ~GPG3_msk;
    GPGCON |= GPG3_eint;
   
    // 對於EINT11,需要在EINTMASK寄存器中使能它
    EINTMASK &= ~(1<<11);
       
    /*
    * 設定優先級:
    * ARB_SEL0 = 00b, ARB_MODE0 = 0: REQ1 > REQ3,即EINT0 > EINT2
    * 仲裁器1、6無需設置
    * 最終:
    * EINT0 > EINT2 > EINT11即K2 > K3 > K4
    */
    PRIORITY = (PRIORITY & ((~0x01) | (0x3<<7))) | (0x0 << 7) ;

    // EINT0、EINT2、EINT8_23使能
    INTMSK  &= (~(1<<0)) & (~(1<<2)) & (~(1<<5));
}

 

void int_init(void)
{
    rSRCPND = rSRCPND;                         // clear all interrupt
    rINTPND = rINTPND;                         // clear all interrupt
   
 // nIntMode='3';
 rGPFCON = (rGPFCON & 0xffcc) | (1<<5) | (1<<1);      // PF0/2 = EINT0/2
    rGPGCON = (rGPGCON & 0xff3fff3f) | (1<<23) | (1<<7);    // PG3/11 = EINT11/19
 
 pISR_EINT0=(UINT32T)isrEINT0;//int0_int;       //isrEINT0;
 pISR_EINT8_23=(UINT32T)isrEINT11_19;//int11_int;     //isrEINT11_19;

 rEINTPEND = 0xffffff;
 rSRCPND = BIT_EINT0 | BIT_EINT8_23;         //to clear the previous pending states
 rINTPND = BIT_EINT0 | BIT_EINT8_23;
   
 rEXTINT0 = (rEXTINT0 & ~((7<<8)  | (0x7<<0))) | 0x2<<8 | 0x2<<0;  // EINT0/2=falling edge triggered
 rEXTINT1 = (rEXTINT1 & ~(7<<12)) | 0x2<<12;       //EINT11=falling edge triggered

 rEINTMASK &= ~(1<<11);
 rINTMSK  &= ~(BIT_EINT0 | BIT_EINT8_23);
}

Copyright © Linux教程網 All Rights Reserved