什么是中斷?
在處理器中,所謂中斷,是一個(gè)過(guò)程,即CPU在正在執(zhí)行程序過(guò)程中,遇到外部/內(nèi)部緊急事件需要處理,暫時(shí)中止當(dāng)前程序執(zhí)行轉(zhuǎn)而去
為事件服務(wù),待服務(wù)完畢,再返回到暫停處(斷點(diǎn))繼續(xù)執(zhí)行原來(lái)的程序。為事件服務(wù)的程序稱之為中斷服務(wù)程序或中斷處理程序。嚴(yán)格來(lái)說(shuō)上述過(guò)程是針對(duì)硬件中斷而言的,用軟件方法也可以引起中斷。硬件原因引起的中斷過(guò)程中是不可測(cè)的,隨機(jī)的,軟件中斷是可以人為控制的
斷點(diǎn):一個(gè)地址,程序在該處中斷,轉(zhuǎn)而取執(zhí)行中斷程序的地址。
中斷源:引起中斷的信號(hào)源。
異常優(yōu)先級(jí)的概念
同時(shí)出現(xiàn)兩個(gè)中斷源,就會(huì)出現(xiàn)先處理哪個(gè)中斷的問(wèn)題。出現(xiàn)這種問(wèn)題以后,這里就產(chǎn)生一個(gè)中斷優(yōu)先級(jí)的概念。
ARM處理器中有7種類型的異常,按照優(yōu)先級(jí)從高到低的排列順序如下:
1.復(fù)位異常(reset)
2.數(shù)據(jù)異常(data abort)
3.快速中斷異常(fiq)
4.外部中斷異常(irq)
5.預(yù)取異常(prefetch abort)
6.軟件中斷(swi)
7.未定義指令異常(undef)
中斷:
硬中斷 內(nèi)部中斷(不可),外部中斷(可屏蔽),外部中斷:外部中斷一般是指由計(jì)算機(jī)外設(shè)發(fā)出的中斷請(qǐng)求,如:鍵盤中斷、打印機(jī)中斷、定時(shí)器中斷等。外部中斷是可以屏蔽的中斷,也就是說(shuō),利用中斷控制器可以屏蔽這些外部設(shè)備的中斷請(qǐng)求。內(nèi)部中斷:內(nèi)部中斷是指因硬件出錯(cuò)(如突然掉電、奇偶校驗(yàn)錯(cuò)等)或運(yùn)算出錯(cuò)(除數(shù)為零、運(yùn)算溢出、單步中斷等)所引起的中斷。內(nèi)部中斷是不可屏蔽的中斷。
軟中斷(不可),軟件中斷其實(shí)并不是真正的中斷,它們只是可被調(diào)用執(zhí)行的一般程序
中斷響應(yīng)流程圖
通用中斷控制器generic interrupt control
中斷號(hào):每個(gè)中斷源都被分配了一個(gè)獨(dú)一無(wú)二的中斷號(hào)(0-1019)
中斷掩碼:在匯編語(yǔ)言中進(jìn)行中斷前,需要對(duì)相應(yīng)的中斷狀態(tài)字進(jìn)行授權(quán)允許或屏蔽相關(guān)中斷的操作。
GIC支持的三種中斷類型
軟件產(chǎn)生的中斷SGI,軟件生成的中斷寄存器(ICDSGIR)。 每個(gè)SGI都可以定位多個(gè)處理器。 在里面分銷商和有針對(duì)性的處理器中,SGI通過(guò)其中斷的組合來(lái)唯一標(biāo)識(shí)編號(hào),ID0-ID15和發(fā)出處理器的處理器源ID(CPUID0-CPUID7)SGI。(SGI號(hào) 0-15)
私有的外設(shè)中斷PPI,在特定模式下使用的中斷Interrupt numbers ID16-ID31 are used for interrupts that are private to a CPU interface and are banked in theDistributor。(PPI號(hào) 0-15)
共享的外設(shè)中斷SPI,外設(shè)產(chǎn)生的可以發(fā)送給一個(gè)或多個(gè)核心處理的中斷源。Interrupt numbers ID32-ID1019 are used for SPIs.(SPI號(hào) 0-987)
中斷源
GIC中斷控制器框圖
The main blocks of the GIC are:
AMBA slave interface AMBA從屬接口
Distributor 分配器
CPU interface CPU接口
Clock and reset 時(shí)鐘和重置
Enable and match signals 啟用和匹配信號(hào)
GIC主要功能模塊:分配器和CPU接口
分配器接收中斷,并向相應(yīng)的CPU接口提供最高優(yōu)先級(jí)的中斷。 一個(gè)
優(yōu)先級(jí)較低的中斷在成為最高優(yōu)先級(jí)時(shí)轉(zhuǎn)發(fā)到相應(yīng)的CPU接口
待處理中斷。
GIC支持160個(gè)中斷,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號(hào))
分配器框架圖
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接口的轉(zhuǎn)發(fā)。
啟用或禁用每個(gè)中斷。
設(shè)置每個(gè)中斷的優(yōu)先級(jí)。
設(shè)置每個(gè)中斷的目標(biāo)處理器列表。
將每個(gè)外設(shè)中斷設(shè)置為電平敏感或邊沿觸發(fā)。
如果GIC執(zhí)行安全擴(kuò)展,則將每個(gè)中斷設(shè)置為安全或不安全。
將SGI發(fā)送到一個(gè)或多個(gè)目標(biāo)處理器。
查看任意中斷的狀態(tài)
提供軟件方式設(shè)置或清除任意中斷的掛起狀態(tài)
中斷使用中斷號(hào)進(jìn)行標(biāo)識(shí),每個(gè)接口可以處理多達(dá)1020個(gè)中斷
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.
編程接口
通過(guò)CPU接口發(fā)出中斷請(qǐng)求的信號(hào)。
確認(rèn)中斷。
指示完成中斷的處理。
為處理器設(shè)置一個(gè)中斷優(yōu)先級(jí)掩碼。
為處理器定義搶占策略。
確定處理器的最高待處理中斷。
中斷狀態(tài)轉(zhuǎn)換圖
中斷狀態(tài)
inactive(無(wú)效) 中斷沒(méi)有發(fā)生
pending(待處理) 中斷發(fā)生,等待核心處理,待處理的中斷都作為通過(guò)CPU接口發(fā)送到核心處理的候選者。
active(正在處理) 中斷給了核心,目前正在進(jìn)行中斷處理
active and pending (處理和待處理)一個(gè)中斷源正在被核心處理而GIC又接收到來(lái)自同一中斷源的中斷觸發(fā)信號(hào)。
轉(zhuǎn)換A1或A2,添加掛起狀態(tài)
對(duì)于SGI:
在寫入指定處理器為目標(biāo)的ICDSGIR時(shí)發(fā)生轉(zhuǎn)換。
只有在指定SGI的安全配置(適用于CPU接口)對(duì)應(yīng)于ICDSGIR.SATT位值。如果GIC執(zhí)行安全擴(kuò)展和在Secure中寫入ICDSGIR。
對(duì)于SPI或PPI,如果出現(xiàn)以下情況,則發(fā)生轉(zhuǎn)換:
外設(shè)發(fā)出中斷信號(hào)或
軟件寫入ICDISPR。
轉(zhuǎn)換B1或B2,刪除掛起狀態(tài)
過(guò)渡不適用于SGI:
待處理的SGI應(yīng)該通過(guò)活動(dòng)狀態(tài)進(jìn)行轉(zhuǎn)換或重置以刪除其掛起狀態(tài)。
處于活動(dòng)狀態(tài)的待處理SGI應(yīng)該通過(guò)掛起狀態(tài)進(jìn)行轉(zhuǎn)換,或者進(jìn)行重置以刪除掛起狀態(tài)。
對(duì)于SPI或PPI,如果出現(xiàn)以下情況,則發(fā)生轉(zhuǎn)換:
電平敏感的中斷僅在輸入信號(hào)有效時(shí)才處于等待狀態(tài),斷言或由于觸發(fā)了一個(gè)邊沿觸發(fā)的中斷信號(hào),或者寫入一個(gè)中斷,中斷處于待處理狀態(tài)
ICDISPR。該軟件然后寫入相應(yīng)的ICDICPR。
過(guò)渡C.
如果中斷被啟用并且具有足夠的優(yōu)先級(jí)來(lái)向處理器發(fā)送信號(hào),則軟件轉(zhuǎn)換發(fā)生從ICCIAR讀取。
過(guò)渡D.
對(duì)于SGI,如果關(guān)聯(lián)的SGI被啟用并且分發(fā)器將其轉(zhuǎn)發(fā)到CPU接口,則發(fā)生轉(zhuǎn)換同時(shí)處理器讀取ICCIAR以確認(rèn)先前的SGI實(shí)例。是否
這種轉(zhuǎn)變的發(fā)生,取決于ICCIAR的閱讀時(shí)間與重新規(guī)定SGI的時(shí)間。
對(duì)于SPI或PPI:
轉(zhuǎn)換發(fā)生在
中斷使能。
從ICCIAR讀取軟件。該讀取將激活狀態(tài)添加到中斷。
- 中斷信號(hào)保持有效,用于電平敏感中斷。這是因?yàn)橥庠O(shè)沒(méi)有中斷中斷直到處理器服務(wù)中斷。
對(duì)于邊沿觸發(fā)中斷,是否發(fā)生此轉(zhuǎn)換取決于讀取的時(shí)序ICCIAR相對(duì)于檢測(cè)到重新中斷的中斷。否則會(huì)導(dǎo)致ICCIAR的讀取
過(guò)渡C,可能之后是過(guò)渡A2。轉(zhuǎn)換E1或E2,刪除活動(dòng)狀態(tài)
當(dāng)軟件寫入ICCEOIR時(shí)發(fā)生轉(zhuǎn)換。
外設(shè)和中斷控制器處理流程
按鍵狀態(tài)
低電平(按下去狀態(tài))
高電平(彈起來(lái)狀態(tài))
下降沿(高電平向低電平跳變的過(guò)程)
上升沿(低電平向高電平跳變的過(guò)程)
寄存器描述
ICCICR_CPUn 0x0000 CPU interface control register 0x0000_0000 CPU接口控制寄存器(CPU接口內(nèi)中斷送到相應(yīng)CPU)
ICCPMR_CPUn 0x0004 Interrupt priority mask register 0x0000_0000 中斷優(yōu)先級(jí)過(guò)濾寄存器(255所有中斷都被相應(yīng),0不相應(yīng)任何中斷)
ICDISERm_CPUn 0x0100 Interrupt set-enable register (SGI,PPI) 0x0000_FFFF 中斷使能寄存器(使能相應(yīng)中斷到分配器)
ICDIPTRm_CPUn 0x0800 Processor targets register (SGI[3:0]) 0x0101_0101 中斷目標(biāo)CPU配置寄存器(選擇CPU接口)
ICDDCR 0x0000 Distributor control register 0x0000_0000 分配器控制器(打開分配器)
ICCIAR_CPUn 0x000C Interrupt acknowledge register 0x0000_03FF 中斷響應(yīng)寄存器
ICCEOIR_CPUn 0x0010 End of interrupt register Undefined 中斷處理結(jié)束寄存器(清除CPU內(nèi)部相應(yīng)的中斷號(hào))
ICDICPRm_CPUn 0x0280 Interrupt pending-clear register (SGI,PPI) 0x0000_0000 中斷狀態(tài)清除寄存器(清除相應(yīng)的中斷標(biāo)志位)
按鍵的寄存器配置
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(配置按鍵的觸發(fā)方式)
EXT_INT41_MASK 0x0F04 External interrupt EXT_INT41 mask register 0x0000_00FF(按鍵使能中斷)
按鍵的觸發(fā)方式
具體寄存器
ICDSER根據(jù)中斷號(hào)選擇對(duì)應(yīng)的專門管理所有中斷使能寄存器使能中斷
ICDPTRm_CPUn,中斷號(hào)為57-32=25,選ICDIPTR14
根據(jù)GIC Interrupt Table查出EINT[9]中斷號(hào)為57,SP1號(hào)為57-32=25,根據(jù)下圖,八位控制CPU的接口,這里我們的CPU只有四核,每個(gè)寄存器控制四個(gè)中斷的CPU接口選擇,SPI號(hào)為25,在SPI[27:24],這里我們的CPU接口為0,八位的值為0x00000001(選擇哪個(gè)接口哪個(gè)接口置1),所以這里配置為ICDIPTR.ICDIPTR14= 0X1 《《 8
具體事例代碼
/*
* main.c
*
* Created on: 2017-12-4
* Author: Administrator
*/
#include“exynos_4412.h”
voiddo_irq()
{
unsignedint irq_num;//獲取中斷號(hào)
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;//清理相應(yīng)的中斷標(biāo)志位
break;
case58:
printf(“i’m key3 interrupter! interrupter id is %d\n”,irq_num);
GPF3.DAT= 0x1 《《 5;
EXT_INT41_PEND = 0x1 《《 2; // 清除相應(yīng)中斷源
ICDICPR.ICDICPR1= 1 《《 26;
break;
default:
printf(“interrupter not exist\n”);
break;
}
CPU0.ICCEOIR= (CPU0.ICCEOIR& ~(0x3ff)) | irq_num;//清理相應(yīng)的中斷號(hào)
}
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);//下降沿觸發(fā)
EXT_INT41_CON = EXT_INT41_CON & (~(0X3 《《 8)) | (0X2 《《 8);//下降沿觸發(fā)
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;//優(yōu)先級(jí)最低,所有中斷都會(huì)響應(yīng)
ICDISER.ICDISER1= (0X1 《《 25) | (0x1 《《 26);
ICDIPTR.ICDIPTR14= (0X1 《《 8) | (0x1 《《 16); //中斷送到相應(yīng)CPU
}
intmain()
{
peripheral_init();
gic_init();
while(1)
{
printf(“working!\n”);
GPF3.DAT= ~(0x3 《《 4);
mydelay_ms(800);
}
};
評(píng)論
查看更多