什么是中斷?
在處理器中,所謂中斷,是一個過程,即CPU在正在執行程序過程中,遇到外部/內部緊急事件需要處理,暫時中止當前程序執行轉而去
為事件服務,待服務完畢,再返回到暫停處(斷點)繼續執行原來的程序。為事件服務的程序稱之為中斷服務程序或中斷處理程序。嚴格來說上述過程是針對硬件中斷而言的,用軟件方法也可以引起中斷。硬件原因引起的中斷過程中是不可測的,隨機的,軟件中斷是可以人為控制的
斷點:一個地址,程序在該處中斷,轉而取執行中斷程序的地址。
中斷源:引起中斷的信號源。
異常優先級的概念
同時出現兩個中斷源,就會出現先處理哪個中斷的問題。出現這種問題以后,這里就產生一個中斷優先級的概念。
ARM處理器中有7種類型的異常,按照優先級從高到低的排列順序如下:
1.復位異常(reset)
2.數據異常(data abort)
3.快速中斷異常(fiq)
4.外部中斷異常(irq)
5.預取異常(prefetch abort)
6.軟件中斷(swi)
7.未定義指令異常(undef)
中斷:
硬中斷 內部中斷(不可),外部中斷(可屏蔽),外部中斷:外部中斷一般是指由計算機外設發出的中斷請求,如:鍵盤中斷、打印機中斷、定時器中斷等。外部中斷是可以屏蔽的中斷,也就是說,利用中斷控制器可以屏蔽這些外部設備的中斷請求。內部中斷:內部中斷是指因硬件出錯(如突然掉電、奇偶校驗錯等)或運算出錯(除數為零、運算溢出、單步中斷等)所引起的中斷。內部中斷是不可屏蔽的中斷。
軟中斷(不可),軟件中斷其實并不是真正的中斷,它們只是可被調用執行的一般程序
中斷響應流程圖
通用中斷控制器generic interrupt control
中斷號:每個中斷源都被分配了一個獨一無二的中斷號(0-1019)
中斷掩碼:在匯編語言中進行中斷前,需要對相應的中斷狀態字進行授權允許或屏蔽相關中斷的操作。
GIC支持的三種中斷類型
軟件產生的中斷SGI,軟件生成的中斷寄存器(ICDSGIR)。 每個SGI都可以定位多個處理器。 在里面分銷商和有針對性的處理器中,SGI通過其中斷的組合來唯一標識編號,ID0-ID15和發出處理器的處理器源ID(CPUID0-CPUID7)SGI。(SGI號 0-15)
私有的外設中斷PPI,在特定模式下使用的中斷Interrupt numbers ID16-ID31 are used for interrupts that are private to a CPU interface and are banked in theDistributor。(PPI號 0-15)
共享的外設中斷SPI,外設產生的可以發送給一個或多個核心處理的中斷源。Interrupt numbers ID32-ID1019 are used for SPIs.(SPI號 0-987)
中斷源
GIC中斷控制器框圖
The main blocks of the GIC are:
AMBA slave interface AMBA從屬接口
Distributor 分配器
CPU interface CPU接口
Clock and reset 時鐘和重置
Enable and match signals 啟用和匹配信號
GIC主要功能模塊:分配器和CPU接口
分配器接收中斷,并向相應的CPU接口提供最高優先級的中斷。 一個
優先級較低的中斷在成為最高優先級時轉發到相應的CPU接口
待處理中斷。
GIC支持160個中斷,Total 160 interrupts including Software Generated Interrupts (SGIs[15:0], ID[15:0]), Private Peripheral Interrupts(PPIs[15:0], ID[31:16]) and Shared Peripheral Interrupts (SPIs[127:0], ID[159:32]) are supported. For SPI, you can
service a maximal 32 * 4 = 128 interrupt requests(SPI號)
分配器框架圖
The Distributor provides a programming interface for:
Enabling the forwarding of interrupts to the CPU interfaces globally.
?Enabling or disabling each interrupt.
Setting the priority level of each interrupt.
Setting the target processor list of each interrupt.
Setting each peripheral interrupt to be level-sensitive or edge-triggered.
Setting each interrupt as either secure or Non-secure if the GIC implements the Security Extensions.
Sending an SGI to one or more target processors.
啟用全局中斷向CPU接口的轉發。
啟用或禁用每個中斷。
設置每個中斷的優先級。
設置每個中斷的目標處理器列表。
將每個外設中斷設置為電平敏感或邊沿觸發。
如果GIC執行安全擴展,則將每個中斷設置為安全或不安全。
將SGI發送到一個或多個目標處理器。
查看任意中斷的狀態
提供軟件方式設置或清除任意中斷的掛起狀態
中斷使用中斷號進行標識,每個接口可以處理多達1020個中斷
Interrupts from sources are identified using ID numbers. Each CPU interface can see up to 1020 interrupts. The
distributor supports up to 1244 interrupts because of banking of SPIs and PPIs.
CPU接口
Programming interface for:
Enabling the signaling of interrupt requests by the CPU interface.
Acknowledging an interrupt.
Indicating completion of the processing of an interrupt.
Setting an interrupt priority mask for the processor.
Defining the preemption policy for the processor.
Determining the highest priority pending interrupt for the processor.
編程接口
通過CPU接口發出中斷請求的信號。
確認中斷。
指示完成中斷的處理。
為處理器設置一個中斷優先級掩碼。
為處理器定義搶占策略。
確定處理器的最高待處理中斷。
中斷狀態轉換圖
中斷狀態
inactive(無效) 中斷沒有發生
pending(待處理) 中斷發生,等待核心處理,待處理的中斷都作為通過CPU接口發送到核心處理的候選者。
active(正在處理) 中斷給了核心,目前正在進行中斷處理
active and pending (處理和待處理)一個中斷源正在被核心處理而GIC又接收到來自同一中斷源的中斷觸發信號。
轉換A1或A2,添加掛起狀態
對于SGI:
在寫入指定處理器為目標的ICDSGIR時發生轉換。
只有在指定SGI的安全配置(適用于CPU接口)對應于ICDSGIR.SATT位值。如果GIC執行安全擴展和在Secure中寫入ICDSGIR。
對于SPI或PPI,如果出現以下情況,則發生轉換:
外設發出中斷信號或
軟件寫入ICDISPR。
轉換B1或B2,刪除掛起狀態
過渡不適用于SGI:
待處理的SGI應該通過活動狀態進行轉換或重置以刪除其掛起狀態。
處于活動狀態的待處理SGI應該通過掛起狀態進行轉換,或者進行重置以刪除掛起狀態。
對于SPI或PPI,如果出現以下情況,則發生轉換:
電平敏感的中斷僅在輸入信號有效時才處于等待狀態,斷言或由于觸發了一個邊沿觸發的中斷信號,或者寫入一個中斷,中斷處于待處理狀態
ICDISPR。該軟件然后寫入相應的ICDICPR。
過渡C.
如果中斷被啟用并且具有足夠的優先級來向處理器發送信號,則軟件轉換發生從ICCIAR讀取。
過渡D.
對于SGI,如果關聯的SGI被啟用并且分發器將其轉發到CPU接口,則發生轉換同時處理器讀取ICCIAR以確認先前的SGI實例。是否
這種轉變的發生,取決于ICCIAR的閱讀時間與重新規定SGI的時間。
對于SPI或PPI:
轉換發生在
中斷使能。
從ICCIAR讀取軟件。該讀取將激活狀態添加到中斷。
- 中斷信號保持有效,用于電平敏感中斷。這是因為外設沒有中斷中斷直到處理器服務中斷。
對于邊沿觸發中斷,是否發生此轉換取決于讀取的時序ICCIAR相對于檢測到重新中斷的中斷。否則會導致ICCIAR的讀取
過渡C,可能之后是過渡A2。轉換E1或E2,刪除活動狀態
當軟件寫入ICCEOIR時發生轉換。
外設和中斷控制器處理流程
按鍵狀態
低電平(按下去狀態)
高電平(彈起來狀態)
下降沿(高電平向低電平跳變的過程)
上升沿(低電平向高電平跳變的過程)
寄存器描述
ICCICR_CPUn 0x0000 CPU interface control register 0x0000_0000 CPU接口控制寄存器(CPU接口內中斷送到相應CPU)
ICCPMR_CPUn 0x0004 Interrupt priority mask register 0x0000_0000 中斷優先級過濾寄存器(255所有中斷都被相應,0不相應任何中斷)
ICDISERm_CPUn 0x0100 Interrupt set-enable register (SGI,PPI) 0x0000_FFFF 中斷使能寄存器(使能相應中斷到分配器)
ICDIPTRm_CPUn 0x0800 Processor targets register (SGI[3:0]) 0x0101_0101 中斷目標CPU配置寄存器(選擇CPU接口)
ICDDCR 0x0000 Distributor control register 0x0000_0000 分配器控制器(打開分配器)
ICCIAR_CPUn 0x000C Interrupt acknowledge register 0x0000_03FF 中斷響應寄存器
ICCEOIR_CPUn 0x0010 End of interrupt register Undefined 中斷處理結束寄存器(清除CPU內部相應的中斷號)
ICDICPRm_CPUn 0x0280 Interrupt pending-clear register (SGI,PPI) 0x0000_0000 中斷狀態清除寄存器(清除相應的中斷標志位)
按鍵的寄存器配置
EXT_INT41_PEND 0x0F44 External interrupt EXT_INT41 pending register 0x0000_0000(配置按鍵的中斷pending)
EXT_INT41_CON 0x0E04 External interrupt EXT_INT41 configuration register 0x0000_0000(配置按鍵的觸發方式)
EXT_INT41_MASK 0x0F04 External interrupt EXT_INT41 mask register 0x0000_00FF(按鍵使能中斷)
按鍵的觸發方式
具體寄存器
ICDSER根據中斷號選擇對應的專門管理所有中斷使能寄存器使能中斷
ICDPTRm_CPUn,中斷號為57-32=25,選ICDIPTR14
根據GIC Interrupt Table查出EINT[9]中斷號為57,SP1號為57-32=25,根據下圖,八位控制CPU的接口,這里我們的CPU只有四核,每個寄存器控制四個中斷的CPU接口選擇,SPI號為25,在SPI[27:24],這里我們的CPU接口為0,八位的值為0x00000001(選擇哪個接口哪個接口置1),所以這里配置為ICDIPTR.ICDIPTR14= 0X1 《《 8
具體事例代碼
/*
* main.c
*
* Created on: 2017-12-4
* Author: Administrator
*/
#include“exynos_4412.h”
voiddo_irq()
{
unsignedint irq_num;//獲取中斷號
irq_num = CPU0.ICCIAR& 0X3FF;
switch(irq_num)
{
case57:
printf(“i‘m key2 interrupter! interrupter id is %d\n”,irq_num);
GPF3.DAT= 0x1 《《 4;
EXT_INT41_PEND = 0X1 《《 1;//中斷重啟
ICDICPR.ICDICPR1= 0X1 《《 25;//清理相應的中斷標志位
break;
case58:
printf(“i’m key3 interrupter! interrupter id is %d\n”,irq_num);
GPF3.DAT= 0x1 《《 5;
EXT_INT41_PEND = 0x1 《《 2; // 清除相應中斷源
ICDICPR.ICDICPR1= 1 《《 26;
break;
default:
printf(“interrupter not exist\n”);
break;
}
CPU0.ICCEOIR= (CPU0.ICCEOIR& ~(0x3ff)) | irq_num;//清理相應的中斷號
}
voidmydelay_ms(inttime) {
inti, j;
while(time--) {
for(i = 0; i 《 5; i++)
for(j = 0; j 《 514; j++)
;
}
}
voidperipheral_init()
{
GPF3.CON= GPF3.CON& (~(0xf 《《 16)) | 0x1 《《 16;//燈
GPF3.CON= GPF3.CON& (~(0xf 《《 20)) | 0x1 《《 20;
GPX1.CON= GPX1.CON& (~(0xf 《《 4)) | 0xF 《《 4;//引腳位外部中斷
GPX1.CON= GPX1.CON& (~(0xf 《《 8)) | 0xF 《《 8;//引腳位外部中斷
EXT_INT41_CON = EXT_INT41_CON & (~(0X3 《《 4)) | (0X2 《《 4);//下降沿觸發
EXT_INT41_CON = EXT_INT41_CON & (~(0X3 《《 8)) | (0X2 《《 8);//下降沿觸發
EXT_INT41_MASK = EXT_INT41_MASK & (~(0X1 《《 1)); //使能中斷
EXT_INT41_MASK = EXT_INT41_MASK & (~(0X1 《《 2)); //使能中斷
}
voidgic_init()
{
ICDDCR =1;//使能分配器
CPU0.ICCICR= 0X1;//使能CPU接口
CPU0.ICCPMR= 0XFF;//優先級最低,所有中斷都會響應
ICDISER.ICDISER1= (0X1 《《 25) | (0x1 《《 26);
ICDIPTR.ICDIPTR14= (0X1 《《 8) | (0x1 《《 16); //中斷送到相應CPU
}
intmain()
{
peripheral_init();
gic_init();
while(1)
{
printf(“working!\n”);
GPF3.DAT= ~(0x3 《《 4);
mydelay_ms(800);
}
};
評論
查看更多