S5PV210中断配置

案例:假设按键连接的引脚是GPH2_0,要想在按键按下去的时候以中断的方式,执行一个函数isr().


中断配置操作步骤:

1.首先选择这个引脚相应配置寄存器,GPH2CON,将所在引脚的位设置为外部中断模式,这里就是赋值为0xf,应用的是外部中断16.

2.选择相应的触发方式,因为外部中断16<32,所以在中断向量1的范围内,选择配置中断寄存器EXT_INT_0_CON,这里选择下降沿触发。

3.引脚设置为中断了,中断控制器也要进行相应设置,设置完成之前所有中断都应该是禁止的,排除干扰初始化的因素,这里VIC0INTENCLEAR写1,禁止所有中断

4..引脚自己有了中断功能和方式了,但是还不够,这时候中断向量控制器还不知道,他要知道你选择的是那个中断才可以操作。VIC0INTSELECT这个来选择是IRQ还是FIQ,每一位对应相应中断源,这里选择IRQ,把16位写1就可以了。

5..要设置发生中断后的跳转函数,发送中断后,程序肯定不能在原来地方继续运行了,要发送跳转,因为一个VIC有很多中断源,所以可以采用一个办法,发生中断后先让程序调到某个函数,然后再在这个函数进行判断是哪个中断发生了,在主函数判断代码闲的繁琐。

为了实现这个目的,首先设置入口地址,根据手册可知入口地址是0xD0037400,要让程序先跳转到这个地方,然后在继续根据发生了哪个中断再跳转一次。这里可以用IRQ_handle在汇编里面构建一个全局描述符,用这个为入口地址赋值。平常运行main函数,中断发生跳到IRQ_handle地方,也就是进入到中断入口了。IRQ_handle这个仅仅是一个标号,程序走到这个标号后继续执行的时候应该执行irq_hander,然后再在这个函数里进行执行真正的中断函数。

6.中断发送后VIC0ADDRESS这个寄存器保存中断的函数地址,所以初始化的时候要清零。

7.EXT_INT_2_MASK,这个控制着中断允不允许,默认是不开的,这个时候要把这个开关打开,

8.打开走了上面一个开关还不行,还要打开总中断的开关,使能中断控制器。

9.真正的中断处理函数isr因为是对应这中断16,所以中断16里面保存的应该是isr的地址。当中断发生时候,如上面提到的,先执行到irq_hander函数,进来后,VIC0ADDRESS这个寄存器的值当前发送中断的函数地址,这里就是isr函数的地址。

10.进入中断后,要清除中断标志位,EXT_INT_2_PEND。不然下次就进不来了,也要清空VIC0ADDRESS的值,不然出不去了。就是这么些步骤,有理有据,不多也不用少。


代码如下:

.global _start
.global IRQ_handle

_start:		
	ldr sp, =0x40000000	 		@设置栈,以便调用c函数
	mov r0, #0x53				@进入SVC模式,开中断(把I位设为0)
	msr CPSR_cxsf, r0	
	
	bl main						@调用main函数

IRQ_handle:
	ldr sp, =0xD0037F80
	sub lr, lr, #4				@计算返回地址
	stmfd sp!, {r0-r12, lr}		@保存现场
	bl	irq_handler				@跳转到中断处理函数
	ldmfd sp!, {r0-r12, pc}^	@恢复现场

上面汇编部分可以看出,设置了两次栈,进行了两次函数调用。

void isr(void)
{
	VIC0ADDRESS = 0;		 //清空中断向量地址
	EXT_INT_2_PEND = 0xff;	 //清除中断标志
}
void ext_int_init(void)
{
    /*发生中断后要跳转到的地址,这里应该存放的是中断的函数的地址*/
	pExceptionIRQ  = (unsigned long)IRQ_handle;	//设置中断跳转地址
	/*中断使能寄存器全部禁止。32为寄存器*/
	VIC0INTENCLEAR = 0xffffffff;                //禁止所有中断
	/*设置为0表示IRQ中断,否则FIQ(快速中断请求)*/
	VIC0INTSELECT &= ~(1<<16);					//将外部中断16设为IRQ模式
	/*先把地址清零*/
	VIC0ADDRESS = 0;                            //清除需要处理的中断的中断处理函数的地址

	EXT_INT_2_CON &= ~(7<<0);					//把外部中断16设为下降沿触发
	EXT_INT_2_CON |= 1<<1;

	EXT_INT_2_MASK &= ~(1<<0);					//清除外部中断16的屏蔽,使能中断

	VIC0INTENABLE  |= 1<<16; 					//使能中断控制器
	/*isr是真正的中断处理函数的地址*/
	VIC0VECTADDR16 = (unsigned int )isr;		//设置中断服务程序地址
}

int main(void)
{
	ext_int_init();		    //初始化中断
	char flag=0;//可以来哥这个作为中断的发送与否在主函数里面判断
	//这里可以添加各种初始化
	while (1)
	{
		if(flag == 1)     //如果有进入中断,则LED会闪烁
		{
			//中断后执行的代码,也可以放在这里面;
		}
	}
	return 0;
}






你可能感兴趣的:(嵌入式,s5pv210,中断配置)