/** 代碼演示 - key_irq.c **/void do_gpioa_irq(void) { uart_puts("/n/r do_gpioa_irq /n/r"); GPIOA_DET |= (1<<28);}void key_irq_init(void) { GPIOA_INTENB &= ~(1<<28); // 先做中斷源級屏蔽 //GPIO 配置 // 1、GPIO配置為輸入 // 2、禁止內部上、下拉電阻 // 3、GPIO檢測使能 // 4、GPIO檢測下降沿事件 // 5、GPIO中斷使能 // FUNC 0 // 輸入口,禁止內部上下拉電阻 GPIOA_ALTFN1 &= ~(3<<(24)); GPIOA_OUTEN &= ~(1<<28); //清除檢測標志位 GPIOA_DET |= (1<<28); //檢測下降沿事件,使能檢測 GPIOA_DETMODE1 = (GPIOA_DETMODE1 & ~(3<<24)) | (2<<24); GPIOA_DETMODEEX &= ~(1<<28); GPIOA_DETENB |= (1<<28); GPIOA_INTENB |= (1<<28); // 最后中斷源級使能}/** ------------------------------------------------------ **/1.3 中斷控制器 GIC - (省長)【特點】 1)中斷源可以配置為group0或者group1; 2)group0中的中斷可以配置為IRQ/FIQ的形式向目標處理器報告; 3)grout1中的中斷只能以IRQ的形式向目標處理器報告;【支持4種類型的中斷】 SGI * 16 :軟件產生的中斷信號,cpu和cpu之間的通信。 PPI * 6 :私有外圍設備中斷 PPI * 1 :私有內部設備中斷 SPI * 128 :'共享的外部設備中斷(按鍵就屬于SPI)【中斷狀態】 inactive:非中斷未決和中斷進行。 pending:中斷未決。中斷已產生,等待cpu處理階段。 active:中斷進行。中斷已產生,并正在執行相應的中斷服務過程中。【中斷被處理的模式】 1-N model / N-N model【中斷優先級】了解【中斷編號】interrupt IDs ID0~ID15:SGI ID16~ID31:PPI ID32~ID1019:SPI // 按鍵可用的編號在此范圍內【中斷源】---> P472. GPIOA中斷對應的interrupt ID是 32 + 53 == 85【關于特殊功能寄存器的設置,分兩部分】 distributor<分配器> + CPU interface<接口> = '中斷控制器(GIC)' 1)以GICD_xxxx開頭的寄存器,對distributor配置; 2)以GICC_xxxx開頭的寄存器,對CPU interface配置。" GICD_CTRL // 歸為group的中斷信號是否可向interface GICD_CTRL - 0xc0009000 - [ 0 ] 0=屏蔽,1=使能 " GICD_IGROUPR // 決定中斷歸為group0還是group1 GICD_IGROUPR2 - 0xc0009088 - [ 21 ] 0=group0" GICD_ITARGETSR21 //配置中斷產生后分配給那個核(cpu0,cou1...) GICD_ITARGETSR21 配置中斷產生后分發給哪個核(cpu0 cpu1 ...cpu7) [15:8] 00000001 ID=85的中斷發送到CPU0 GICD_ipRORITYR21 [15:8] 0x0a ID=85的中斷優先級為10 GICD_ICPENDERR2 READ: 1, 中斷產生了未得到處理 PENDING (未決/掛起) WRITE, 1 導致對應的bit 清0 GPIOA ID = 85 [21] 向其中寫入1,將其清0 GICD_ISENABLER2 [21] 0/1 屏蔽/使能 ID=85的中斷信號 GICC_CTRL [0], 0/1 禁止/使能上報group0組的中斷信號給CPUn [1], 0/1 禁止/使能上報group1組的中斷信號給CPUn [3], 0/1 group0的中斷按照IRQ/FIQ方式上報 GICC_PMR 中斷優先級閾值設置 優先級高于閾值的中斷信號才有可能上報給CPU [7:0] 【對應的代碼】interrupt.c int interrupt_init (void){ } 該函數在main.c1.4 ARM core設置 CPSR [I] 0,響應上報的IRQ信號 1,屏蔽上報的IRQ信號 start.s enable_interrupts 該函數在main.c中被調用
2、異常的處理流程 增加start.s 而且調整shell.lds IRQ異常產生,硬件會自動做4件事 1)備份CPSR 到spsr_<irq> 2) 修改CPSR [4:0] 10010 [5] T=0 [6] F=1 [7] I=1 3) 保存返回地址到LR_<irq> LR_<irq> = PC -4 4) 給PC寄存器賦值 PC = vector_base + 0x18 = 0x48000000 + 0x18 start.s 1)異常向量表 b reset ldr ... ldr ... 2)reset: 重新設置異常向量表首地址 棧空間設置 bl main ( ) { 中斷源 中斷控制 arm初始化 //按鍵就出異常并且異常可以傳遞ARM CORE while(1) { } } 當有人按下key1鍵 ,IRQ異常報告給ARM CORE ARM CORE 1)備份cpsr 2)修改CPSR 3)保存返回地址到LR 4)PC = 0X48000018 軟件代碼執行 ldr pc, _irq irq: 保護現場 stmfd sp!, {r0-r12, lr} 執行按鍵處理動作 bl do_irq 恢復現場 ldmfd sp!, {r0-r12, r15}^ r15= lr ^: cpsr = spsr_<irq> do_irq() { /*確認哪個觸發的IRQ*/ GPIOA28 interrupt id = 85 判斷是否為GPIOA28觸發的中斷? { do_gpioa_irq() { /*重要的事:清除中斷源的中斷標志位*/ } 清除gpioa28在中斷控制器中的pending位 } }練習: 梳理按鍵異常是如何產生的?流程 異常的軟硬件響應過程? 能不能向其中再增加一個按鍵?
新聞熱點
疑難解答