s3c2440有60箇中斷源(其中15個爲子中斷源)。函數
31個32位的通用寄存器,6個程序狀態寄存器。有6種工做模式(系統/用戶模式,快中斷模式,管理模式,數據訪問停止模式,中斷模式,未定指令停止模式)。每種模式都有16個通用寄存器和1(或2)個程序狀態寄存器。spa
R15(pc)是程序計數器,R14(lr)是鏈接寄存器,在異常時自動保存pc備份,r13(sp)是棧指針寄存器。指針
CPSR是當狀程序狀態寄存器。其[7:0]爲控制位,[7]爲中斷禁止位,[6]爲快中斷禁止位,[5]爲CPU狀態位,[4:0]爲工做模式位。,it
程序狀態寄存器(PSR)的F位[6]設爲1,禁用快速中斷(FRQ)。class
程序狀態寄存器(PSR)的I位[7]設爲1,禁用普通中斷(IRQ)。psr
SPSR程序狀態保存寄存器,用於在異常時保存CPSR,從異常返回時恢復CPSR。請求
中斷的處理過程:程序
1,中斷控制器聚集中斷信號告訴CPU;數據
2,CPU自動保存當前運行的環境,調用中斷服務程序ISR進行處理(lr=pc+4或+8,即當前指令地址的一下條;cpsr複製到spsr;pc值等於異常向量表中的地址,即轉去執行異常向量表中的指令);異常
3,ISR經過讀中斷控制器相關寄存器,識別哪一個中斷髮生了,進行相應處理;
4,清除中斷;
5,恢復被中斷的程序的運行環境(pc=lr-4或-8,spsr複製回cpsr),繼續執行。
s3c2440中斷控制器中有五個控制寄存器:中斷源等待寄存器(SRCPND),中斷模式寄存器(INTMOD),屏蔽寄存器(INTMSK),優先級寄存器(PRIORITY),中斷等待寄存器(INTPND)。
SRCPND寄存器各位對應不一樣的中斷,其中外部中斷EINT4-7共用bit4,EINT8-23共用bin5。各位初始值爲0,當中斷髮生時,對應位值改成1。
INTMOD寄存器各位用於標記該位對應的中斷是模式,0爲IRQ,1爲FRQ。只容許有一箇中斷設爲FRQ。初始值都爲0。
INIMSK寄存器各位標記該位對應中斷是否可用,0表示有效,1表示禁止。初始值都爲1,即禁止全部中斷。
PRIORITY寄存器用於設置6箇中斷優先權仲裁模塊的工做方式,主要用來設定各中斷優先策略。
INTPND寄存器的32位同一時刻最多隻容許有一個值爲1,這一位是有相就的中斷請求發生,且該中斷未被屏蔽,並且該中斷請求經過了優先仲裁。這個中斷請求將被送到CPU,CPU將跳轉到中斷服務程序執行。中斷服務程序能夠讀取INTPND或INTOFFSET寄存器(當INTPND中某位標記中斷請求發生了,INTOFFSET寄存器中的值爲0-31,標記INTPND的哪一位被置爲1了)的值,以肯定哪一個中斷髮生了。
有的幾個中斷共有一個SRCPND的中斷位,好比INT_AC97和INT_WDT共用INT_WDT_AC97中斷位。這種子中斷共15個。子中斷髮生時,先在INTSRCPND寄存器相應位置1,若是INTSUBMSK寄存器相應位未屏蔽(即該位爲0),則該中斷送到SRCPND寄存器。
23個外部中斷:
EINTINT0-2三個寄存器用於設置23個外部中斷的觸發方式和過濾器是否有效。觸發方式有低電平、高電平、降低沿、上升沿、電平高低變化。
EINTFLT0-3三個寄存器用於設置外部中斷引腳的過濾參數。
EINTMASK寄存器用於設置23個外部中斷的屏蔽狀況,默認是禁用中斷的。
EINTPEND寄存器記錄着23個外部中斷哪個發生了。發生中斷的對應位置1。初始值爲0。但清除中斷位標記時要寫入1。
進入和退出IRQ、保存和恢復環境代碼:
HandleIRQ:
sub lr, lr, #4 @ 計算返回地址
stmdb sp!, { r0-r12,lr } @ 保存使用到的寄存器
@ 注意,此時的sp是中斷模式的sp
@ 初始值是上面設置的4096
ldr lr, =int_return @ 設置調用IRQ_Handle函數後的返回地址
ldr pc, =IRQ_Handle @ 調用中斷分發函數,在interrupt.c中
int_return:
ldmia sp!, { r0-r12,pc }^ @ 中斷返回, ^表示將spsr的值複製到cpsr
中斷服務代碼示例:
/*interrupt registes*/
#define SRCPND (*(volatile unsigned long *)0x4A000000)
#define INTMOD (*(volatile unsigned long *)0x4A000004)
#define INTMSK (*(volatile unsigned long *)0x4A000008)
#define PRIORITY (*(volatile unsigned long *)0x4A00000c)
#define INTPND (*(volatile unsigned long *)0x4A000010)
#define INTOFFSET (*(volatile unsigned long *)0x4A000014)
#define SUBSRCPND (*(volatile unsigned long *)0x4A000018)
#define INTSUBMSK (*(volatile unsigned long *)0x4A00001c)
/*external interrupt registers*/
#define EINTMASK (*(volatile unsigned long *)0x560000a4)
#define EINTPEND (*(volatile unsigned long *)0x560000a8)
#define BIT_ALLMSK (0xffffffff)
//聲明50箇中斷服務函數指針
void (*isr_handle_array[50])(void);
//虛擬中斷服務
void Dummy_isr(void)
{
while(1);
}
//初始化中斷
void init_irq(void)
{
int i = 0;
for (i = 0; i < sizeof(isr_handle_array) / sizeof(isr_handle_array[0]); i++)
{
isr_handle_array[i] = Dummy_isr;
}
INTMOD = 0x0; // 全部中斷都設爲IRQ模式
INTMSK = BIT_ALLMSK; // 先屏蔽全部中斷
}
//中斷處理
void IRQ_Handle(void)
{
unsigned long oft = INTOFFSET;
//清中斷
if (oft == 4)
EINTPEND = 1<<7; //EINT4-7合用IRQ4,注意EINTPEND[3:0]保留未用,向這些位寫入1可能致使未知結果
SRCPND = 1<<oft;
INTPND = INTPND;
/* 調用中斷服務程序 */ isr_handle_array[oft]();}