1. 程式人生 > >ARM中斷機制 --外部中斷配置

ARM中斷機制 --外部中斷配置

很多情況下,要實現一個嵌入式程式,用到某一功能或者某一個硬體資源時,我經常拿廠家或者是其他人給提供的程式碼,參考其中的配置程式碼段部分,只去修改實現成我需要的功能就好。相信大家也和我有相似的經歷吧!?從工程的角度來說,這沒問題。但是理論上總感覺少了點什麼,今天以外部中斷的暫存器配置為例,進一步講解中斷源是如何進入CPU中,CPU又如何處理中斷訊號的,這一過程。單純學術的角度,具體涉及到哪些暫存器、填寫什麼值,就不細述了。這裡用的微控制器是FS4412多核ARM晶片。

 

 

中斷的實現過程(程式的角度)

中斷髮生後,硬體自動跳轉到異常向量表中對應異常型別的位置,然後進行處理。處理過程,先進行現場保護(資料進棧操作),然後根據處理中斷函式,根據中斷號進行特定的中斷處理,等中斷程式處理完後,還要恢復中斷前的現場(資料出棧操作)。

 

這裡可以參考我的另外一篇:組合語言 --實現軟中斷機制

 

 

對中斷源的處理過程(硬體的角度)

這個過程涉及到我們要講的中斷初始化配置,從圖中可以看到,一個外部中斷訊號需要經過這麼多步驟才能到達ARM核心。

首先,外部中斷訊號需經過GPIO管腳進入CPU內部,然後再內部經使能-->分發-->分發使能-->cpu介面-->介面使能和優先順序-->ARM核心  過五關 斬六將 終於到達ARM核心,然後產生中斷標誌位,再執行之前講到的中斷實現(程式實現)。

 


中斷初始化配置

微控制器有內建外設,GPIO屬於外圍功能模組,中斷控制器GIC屬於內部外設。由於中斷源從IO口進入到中斷控制器GIC,才能進入ARM核心。我們需要同時配置這兩塊資源。

#define  GPX1CON        (*(volatile unsigned int *)0x11000c20)
#define  EXT_INT41CON   (*(volatile  int *)0x11000E04)
#define  EXT_INT41_MASK (*(volatile  int *)0x11000F04)
#define ICDISER1_CPU0  (*(volatile  int *)0x10490104)
#define ICDIPTR14_CPU0 (*(volatile  int *)0x10490838)
#define ICDDCR (*(volatile  int *)0x10490000)
#define ICCICR_CPU0  (*(volatile  int *)0x10480000)
#define ICCPMR_CPU0  (*(volatile  int *)0x10480004)
#define EXT_INT41_PEND (*(volatile  int *)0x11000f44)
#define ICCIAR_CPU0  (*(volatile  int *)0x1048000C)
#define ICCEOIR_CPU0 (*(volatile  int *)0x10480010)
#define ICDICPR1_CPU0 (*(volatile  int *)0x10490284)



void interrupt_init(void)
{
	//-----外: 配置管腳的工作模式
	GPX1CON = (GPX1CON & ~(0xF<<4))|(0xF<<4);  //配置 GPX1_1為中斷模式
	
	EXT_INT41CON = (EXT_INT41CON & ~(0x7<<4))|(0x2<<4);  //設定GPX1_1的觸發方式為 下降沿觸 
 
	EXT_INT41_MASK = EXT_INT41_MASK & (~0x02);		//GPX1_1 中斷使能

	
	
	//-----內: 功能塊設定
	ICDISER1_CPU0 = ICDISER1_CPU0 | (1<<25);	//EINT9 (GPX1_1)  GIC中斷使能
	ICDIPTR14_CPU0 = 0x01010101;   //參考例子背景,用預設設定 
	ICDDCR = ICDDCR|1; //GIC 分發總使能
	ICCICR_CPU0 = 1;  // CPU0  中斷使能
	ICCPMR_CPU0 = 0XFF;   //設定CPU0的優先順序門檻為最低

}

 

 

原本想是深入研究一下,然後再寫的。發現還真不簡單,怪不得說中斷是最難的也是最重要的一個知識點。筆者水平有限,就這樣吧。