GPX1_1是外部中断9 EINT9
查询可知其中断ID是57
所以需要进行人为修正lr的地址
sub lr,lr,#4
//iqr异常处理程序
irq_handler:
//IRQ异常后LR保存的地址是被IRQ打断指令的下一条再下一条指令的地址,所以我们需要人为进行修正一下
sub LR,LR,#4
//因为irq模式下使用的R0-R12寄存器和user模式下的是同一组
//所以在处理异常之前需要将USER模式下的寄存器进行压栈保护现场
stmfd sp!,{r0-r12,LR}
//处理异常
bl do_irq
//异常返回
//1.将r0-r12寄存器中的值出栈,使其恢复到异常打断之前的值
//2.将SPSR寄存器的值返回到CPSR,使得cpu恢复到异常前的状态
//3.将LR寄存器的值给PC,程序返回
ldmfd sp!,{r0-r12,PC}^
#include "exynos_4412.h"
//异常处理程序
void do_irq(void)
{
unsigned int Irqnum=0;
//从中断控制器中获取当前中断的中断号,只取后10位
Irqnum=CPU0.ICCIAR & (0X3FF);
switch(Irqnum)
{
case 0:
//0号中断处理程序//
break;
//...//
case 57:
printf("key pressed\n");
//清楚gpio控制器的中断挂起位
EXT_INT41_PEND=(1<<1);
//将当前的中断号写回到中断控制器,以这种方式来告知中断控制器CPU当前的中断已经处理完成,可以发送其他中断
CPU0.ICCEOIR=CPU0.ICCEOIR & (~(0X3FF)) | (57);
break;
//...//
case 159:
//159处理中断程序//
break;
default:
break;
}
}
void delay(unsigned int time)
{
while(time--);
}
int main()
{
//外设层次---外部设备能产生一个中断信号并且发送给中断控制器
//将GPX1_1设置为中断功能//
GPX1.CON=GPX1.CON | (0xF << 4);
//设置GPX_1中断触发模式---下降沿触发//
EXT_INT41_CON=EXT_INT41_CON & (~(0x7<<4)) |(0x2<<4);
//使能GPX1_1---开启中断模式//
EXT_INT41_MASK=EXT_INT41_MASK & (~(1<<1));
//中断控制器层次---让中断控制器接收外设发来的中断信号并且进行管理,然后转发给合适的CPU进行处理
//全局使能中断控制器使其能够接受外部设备产生的中断信号并且转发给CPU
ICDDCR=ICDDCR | 1;
//在中断控制器中使能57号中断,使中断控制器把57号中断转发给CPU接口
ICDISER.ICDISER1=ICDISER.ICDISER1 | (1<<25);
//将57号中断选择CPU0处理
ICDIPTR.ICDIPTR14=ICDIPTR.ICDIPTR14 & (~(0XFF<<8)) | (0X01<<8);
//将中断控制器和CPU0之间的接口使能,使得中断控制器转发的信号能够到达CPU0
CPU0.ICCICR=CPU0.ICCICR | 1;
GPX2.CON=GPX2.CON&(~(0XF<<28))|(0X1<<28);
while(1)
{
//点亮LED2//
GPX2.DAT=GPX2.DAT|(1<<7);
//delay//
delay(1000000);
//熄灭LED2//
GPX2.DAT=GPX2.DAT&(~(1<<7));
//DELAY//
delay(1000000);
}
return 0;
}
作业:通过使用中断的方式检测Key3按键的状态,实现按一次按键,LED2点亮,再次按下,LED2熄灭。
#include "exynos_4412.h"
int flag=0;
//异常处理程序
void do_irq(void)
{
unsigned int Irqnum=0;
//从中断控制器中获取当前中断的中断号,只取后10位
Irqnum=CPU0.ICCIAR & (0X3FF);
switch(Irqnum)
{
case 0:
//0号中断处理程序//
break;
//...//
case 57:
printf("key pressed\n");
//清楚gpio控制器的中断挂起位
EXT_INT41_PEND=(1<<1);
//将当前的中断号写回到中断控制器,以这种方式来告知中断控制器CPU当前的中断已经处理完成,可以发送其他中断
CPU0.ICCEOIR=CPU0.ICCEOIR & (~(0X3FF)) | (58);
break;
//...//
case 58:
flag=~flag;
EXT_INT41_PEND=(1<<2);
//将当前的中断号写回到中断控制器,以这种方式来告知中断控制器CPU当前的中断已经处理完成,可以发送其他中断
CPU0.ICCEOIR=CPU0.ICCEOIR & (~(0X3FF)) | (58);
delay(1000);
break;
case 159:
//159处理中断程序//
break;
default:
break;
}
}
void delay(unsigned int time)
{
while(time--);
}
int main()
{
//外设层次---外部设备能产生一个中断信号并且发送给中断控制器
//将GPX1_2设置为中断功能//
GPX1.CON=GPX1.CON | (0xF << 8);
//设置GPX_1中断触发模式---下降沿触发//
EXT_INT41_CON=EXT_INT41_CON & (~(0x7<<8)) |(0x2<<8);
//使能GPX1_1---开启中断模式//
EXT_INT41_MASK=EXT_INT41_MASK & (~(1<<2));
//中断控制器层次---让中断控制器接收外设发来的中断信号并且进行管理,然后转发给合适的CPU进行处理
//全局使能中断控制器使其能够接受外部设备产生的中断信号并且转发给CPU
ICDDCR=ICDDCR | 1;
//在中断控制器中使能58号中断,使中断控制器把58号中断转发给CPU接口
ICDISER.ICDISER1=ICDISER.ICDISER1 | (1<<26);
//将58号中断选择CPU0处理
ICDIPTR.ICDIPTR14=ICDIPTR.ICDIPTR14 & (~(0XFF<<16)) | (0X01<<16);
//将中断控制器和CPU0之间的接口使能,使得中断控制器转发的信号能够到达CPU0
CPU0.ICCICR=CPU0.ICCICR | 1;
GPX2.CON=GPX2.CON&(~(0XF<<28))|(0X1<<28);
while(1)
{
//点亮LED2//
// GPX2.DAT=GPX2.DAT|(1<<7);
//delay//
// delay(1000000);
//熄灭LED2//
// GPX2.DAT=GPX2.DAT&(~(1<<7));
//DELAY//
// delay(1000000);
if(flag)
GPX2.DAT=GPX2.DAT|(1<<7);
else
GPX2.DAT=GPX2.DAT&(~(1<<7));
}
return 0;
}