ARM中斷機制 --外部中斷配置
阿新 • • 發佈:2018-11-08
很多情況下,要實現一個嵌入式程式,用到某一功能或者某一個硬體資源時,我經常拿廠家或者是其他人給提供的程式碼,參考其中的配置程式碼段部分,只去修改實現成我需要的功能就好。相信大家也和我有相似的經歷吧!?從工程的角度來說,這沒問題。但是理論上總感覺少了點什麼,今天以外部中斷的暫存器配置為例,進一步講解中斷源是如何進入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的優先順序門檻為最低 }
原本想是深入研究一下,然後再寫的。發現還真不簡單,怪不得說中斷是最難的也是最重要的一個知識點。筆者水平有限,就這樣吧。