Crotex A9 中断流程
0赞示例: 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)拷贝 CPSR 到 SPSR_<mode>
(2)设置适当的 CPSR 位:
(2-1)--改变处理器状态进入 ARM 态
(2-2)--改变处理器模式进入相应的异常模式
(2-3)--设置中断禁止位禁止相应中断 (如果需要)
(3)保存返回地址到 LR_<mode>
(4)设置 PC 为相应的异常向量
2--中断服务程序 --- start.S 汇编
start.S
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 }

