Cortex A9 按鍵中斷(SPI)流程
示例: KEY2 中斷控制點亮 LED2
【0】檢測按鍵k2,按鍵k2按下一次,燈LED2閃一次。
【1】查看原理圖,連接引腳和控制邏輯
(1)按鍵k2 連接在GPX1_1引腳
(2)控制邏輯
k2 按下 ---- K2閉合 ---- GPX1_1 低電壓
k2 常態 ---- K2打開 ---- GPX1_1 高電壓
【2】查看相應的芯片手冊
【2-1】循環檢測GPX1_1引腳輸入的電平,為低電壓時,按鍵按下
(1)配置GPX1_1引腳功能為輸入,設置內部上拉下拉禁止。
GPX1.CON = GPX1.CON &(~(0xf<<4)) ;
(2)循環檢測 :
1 while(1) 2 { 3 if(!(GPX1.DAT & (0x1<<1))) // 返回為真,按鍵按下 4 { 5 msdelay(10); 6 if(!(GPX1.DAT & (0x1<<1))) //二次檢測,去抖 7 { 8 GPX2.DAT |= 0x1 << 7; //Turn on LED2 9 mydelay_ms(500); 10 GPX2.DAT &= ~(0x1<<7); //Turn off LED2 11 mydelay_ms(500); 12 13 while(!(GPX1.DAT & (0x1<<1))); 14 } 15 } 16 }
【2-2】中斷方法檢測按鍵
將K2按下時,GPX1_1引腳獲得的電平,作為異常事件。使能異常處理,k2每按下一次,響應一次異常處理。SPI 傳遞流程如下示:
(1)外設一級 --- GPIO控制器
0-- 將GPX1_1引腳的上拉和下拉禁止
GPX1PUD[3:2]= 0b00;
1-- 將GPX1_1引腳功能設置為中斷功能 WAKEUP_INT1[1] --- EXT_INT41[1]
GPX1CON[7:4] = 0xf
2-- EXT_INT41CON 配置觸發電平
當前配置成下降沿觸發:
EXT_INT41CON[6:4] = 0x2
3-- EXT_INT41_FLTCON0 配置中斷引腳濾波
默認就是打開的,不需要配置
4--EXT_INT41_MASK 中斷使能寄存器
使能INT41[1]
EXT_INT41_MASK[1] = 0b0
5--EXT_INT41_PEND 中斷狀態寄存器
當GPX1_1引腳接收到中斷信號,中斷發生,中斷狀態寄存器EXT_INT41_PEND 相應位會自動置1
注意:中斷處理完成的時候,需要清除相應狀態位。置1清0.
EXT_INT41_PEND[1] =0b1
(2)中斷控制器
0--找到外設中斷名稱和GIC中斷控制器對應的名稱
查看芯片手冊(本例:Exynos_4412 -- 9.2表)
WAKEUP_INT1[1] --- EXT_INT41[1] --- INT[9] --- SPI[25]/ID[57]
1--使能cpu0的spi25/id57
ICDISER.ICDISER1 |= (0x1 << 25); //57/32 =1...25 取整數(那個寄存器) 和余數(哪位)
2--全局使能cpu0中斷處理
CPU0.ICCICR |= 0x1;
3--優先級屏蔽寄存器,設置cpu0能處理所有的中斷。
CPU0.ICCPMR = 0xFF;
4--GIC使能
ICDDCR =1;
5--設置SPI[25]/ID[57]由那個cpu處理,當前設置為cpu0的irq中斷
ICDIPTR.ICDIPTR14 |= 0x01<<8; //SPI25 interrupts are sent to processor 0 //57/4 = 14..1 14號寄存器的[15:8]
(3)ARM內核(cpu0)
1--四大步三小步 --- 硬件

1 .text 2 .global _start 3 _start: 4 b reset 5 ldr pc,_undefined_instruction 6 ldr pc,_software_interrupt 7 ldr pc,_prefetch_abort 8 ldr pc,_data_abort 9 ldr pc,_not_used 10 ldr pc,_irq 11 ldr pc,_fiq 12 13 _undefined_instruction: .word _undefined_instruction 14 _software_interrupt: .word _software_interrupt 15 _prefetch_abort: .word _prefetch_abort 16 _data_abort: .word _data_abort 17 _not_used: .word _not_used 18 _irq: .word irq_handler 19 _fiq: .word _fiq 20 21 22 reset: 23 24 ldr r0,=0x40008000 25 mcr p15,0,r0,c12,c0,0 @ Vector Base Address Register 26 27 mrs r0,cpsr 28 bic r0,r0,#0x1f 29 orr r0,r0,#0xd3 30 msr cpsr,r0 @ Enable svc mode of cpu 31 32 mov r0, #0xfffffff 33 mcr p15, 0, r0, c1, c0, 2 @ Defines access permissions for each coprocessor 34 @ Privileged and User mode access 35 36 /* 37 * Invalidate L1 I/D 38 */ 39 mov r0, #0 @ set up for MCR 40 mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs 41 mcr p15, 0, r0, c7, c5, 0 @ invalidate icache 42 43 44 @Set the FPEXC EN bit to enable the FPU: 45 MOV r3, #0x40000000 46 fmxr FPEXC, r3 47 48 /* 49 * disable MMU stuff and caches 50 */ 51 mrc p15, 0, r0, c1, c0, 0 52 bic r0, r0, #0x00002000 @ clear bits 13 (--V-) 53 bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM) 54 orr r0, r0, #0x00001000 @ set bit 12 (---I) Icache 55 orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align 56 orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB 57 mcr p15, 0, r0, c1, c0, 0 58 59 /* LED Test Code */ 60 61 ldr r0, =0x114001E0 62 ldr r1, [r0] 63 bic r1, r1, #0xf0000 64 orr r1, r1, #0x10000 65 str r1, [r0] 66 67 ldr r0, =0x114001E8 68 ldr r1, [r0] 69 bic r1, r1, #0x300 70 str r1, [r0] 71 72 ldr r0, =0x114001E4 73 ldr r1, [r0] 74 orr r1, r1, #0x10 75 str r1, [r0] 76 77 init_stack: 78 ldr r0,stacktop /*get stack top pointer*/ 79 80 /********svc mode stack********/ 81 mov sp,r0 82 sub r0,#128*4 /*512 byte for irq mode of stack*/ 83 /****irq mode stack**/ 84 msr cpsr,#0xd2 85 mov sp,r0 86 sub r0,#128*4 /*512 byte for irq mode of stack*/ 87 /***fiq mode stack***/ 88 msr cpsr,#0xd1 89 mov sp,r0 90 sub r0,#0 91 /***abort mode stack***/ 92 msr cpsr,#0xd7 93 mov sp,r0 94 sub r0,#0 95 /***undefine mode stack***/ 96 msr cpsr,#0xdb 97 mov sp,r0 98 sub r0,#0 99 /*** sys mode and usr mode stack ***/ 100 msr cpsr,#0x10 101 mov sp,r0 /*1024 byte for user mode of stack*/ 102 103 b main 104 105 .align 4 106 107 /**** swi_interrupt handler ****/ 108 109 110 /**** irq_handler ****/ 111 irq_handler: 112 113 sub lr,lr,#4 114 stmfd sp!,{r0-r12,lr} 115 .weak do_irq 116 bl do_irq 117 ldmfd sp!,{r0-r12,pc}^ 118 119 stacktop: .word stack+4*512 120 .data 121 122 stack: .space 4*512
3--中斷處理程序 --- do_irq函數 c語言(函數原型void name(void))
(1) 讀取正在處理的中斷ID寄存器(ICCIAR)
irq_num = (CPU0.ICCIAR & 0x1FF);
(2)根據irq_num,分支處理中斷
(3)清除中斷狀態位
(3-1)i.外設級,EXT_INT41_PEND |= 0x1 << 1;
(3-2)ii.GIC級,ICDICPR.ICDICPR1 |= 0x1 << 25;
(3-3)iii.CPU0級 CPU0.ICCEOIR = (CPU0.ICCEOIR & ~(0x1FF)) | irq_num;
C代碼:
1 #include "exynos_4412.h" 2 3 void mydelay_ms(int ms) 4 { 5 int i, j; 6 while(ms--) 7 { 8 for (i = 0; i < 5; i++) 9 for (j = 0; j < 514; j++); 10 } 11 } 12 13 void do_irq(void ) 14 { 15 int irq_num; 16 irq_num = (CPU0.ICCIAR & 0x1FF); 17 switch (irq_num) { 18 19 case 57: // 20 //Clear Pend 21 EXT_INT41_PEND |= 0x1 << 1; 22 ICDICPR.ICDICPR1 |= 0x1 << 25; 23 24 //Turn on LED2 25 GPX2.DAT |= 0x1 << 7; 26 mydelay_ms(500); 27 28 //Turn off LED2 29 GPX2.DAT &= ~(0x1 << 7); 30 mydelay_ms(500); 31 32 33 break; 34 } 35 36 // End of interrupt 37 CPU0.ICCEOIR = (CPU0.ICCEOIR & ~(0x1FF)) | irq_num; 38 39 } 40 41 42 int main(void) 43 { 44 GPX2.CON = (GPX2.CON & ~(0xf << 28)) | 1 << 28; //GPX2_7:output, LED2 45 46 //Key_2 Interrupt GPX1_1 47 GPX1.PUD = GPX1.PUD & ~(0x3 << 2); // Disables Pull-up/Pull-down 48 GPX1.CON = (GPX1.CON & ~(0xF << 4)) | (0xF << 4); //GPX1_1: WAKEUP_INT1[1](EXT_INT41[1]) 49 EXT_INT41_CON = (EXT_INT41_CON & ~(0x7 << 4)) | 0x2 << 4; 50 EXT_INT41_MASK = (EXT_INT41_MASK & ~(0x1 << 1)); // Bit: 0 = Enables interrupt 51 52 //* GIC interrupt controller: 53 54 // Enables the corresponding interrupt SPI25-- Key_2 55 ICDISER.ICDISER1 |= (0x1 << 25); 56 CPU0.ICCICR |= 0x1; //Global enable for signaling of interrupts 57 CPU0.ICCPMR = 0xFF; //The priority mask level.Priority filter. threshold 58 ICDDCR = 1; //Bit0: GIC global enable 59 60 ICDIPTR.ICDIPTR14 |= 0x01<<8; //SPI25 interrupts are sent to processor 0 61 62 63 while (1); 64 65 return 0; 66 }