s3c2440中断总结+按键中断

本文详细解析中断处理机制,包括IRQ中断分析、按键中断程序实现及初始化步骤,涉及中断源配置、中断触发方式设置等关键技术点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、启动代码之IRQ中断分析。



举例:timer4中断调用过程

1、当timer4发生中断,INTOFFSET寄存器的值变为中断源INT_TIMER4对应的值,即 14。

      同时,程序将跳转到irq中断向量地址(0x18)处去执行,该处的指令为   b HandlerIRQ

2、在启动代码中有如下一段宏定义

$HandlerLabel HANDLER $HandleLabel
$HandlerLabel
sub sp,sp,#4 ;decrement sp(to store jump address)
stmfd sp!,{r0} ;PUSH the work register to stack(lr does not push because it return to original address)
ldr     r0,=$HandleLabel ;load the address of HandleXXX to r0
ldr     r0,[r0] ;load the contents(service routine start address) of HandleXXX
str     r0,[sp,#4]  ;store the contents(ISR) of HandleXXX to stack
ldmfd   sp!,{r0,pc}     ;POP the work register and pc(jump to ISR)
MEND


所以启动代码中以下的语句将展开为对应得代码段。其作用是将pc指针指向HandleIRQ

//HandlerFIQ      HANDLER HandleFIQ

HandlerIRQ      HANDLER HandleIRQ
替换为-----》

HandlerIRQ
sub sp,sp,#4
stmfd sp!,{r0}
ldr     r0,=HandleIRQ
ldr     r0,[r0]
str     r0,[sp,#4]       
ldmfd   sp!,{r0,pc}     

//HandlerUndef    HANDLER HandleUndef
//HandlerSWI      HANDLER HandleSWI
//HandlerDabort   HANDLER HandleDabort
//HandlerPabort   HANDLER HandlePabort

3、在执行启动代码时,如下一段代码已经将 IsrIRQ   标签加载到 HandleIRQ       的地址中,所以上一步pc指针指向HandleIRQ,即是跳转到 IsrIRQ  标签处执行。

ldr r0,=HandleIRQ       ;
ldr r1,=IsrIRQ ;
str r1,[r0]

4、

IsrIRQ
sub sp,sp,#4       ;reserved for PC
stmfd sp!,{r8-r9}
ldr r9,=INTOFFSET
ldr r9,[r9] ;若为timer4中断,该值为14
ldr r8,=HandleEINT0 ;外部中断的起始地址
add r8,r8,r9,lsl #2 ;(起始地址 + 偏移量*4) 即拓展向量保存对应中断处理函数的地址
ldr r8,[r8]
str r8,[sp,#8]
ldmfd sp!,{r8-r9,pc} ;将pc指向中断处理函数

5、我们在初始化中断的函数中,

  pISR_TIMER4 = (unsigned)timer4_handle;

pISR_TIMER4 在内存中的地址与上面所说的起始地址 +偏移量*4)是一致的。

  这样,每一个中断源就和我们设置的中断处理函数一一对应了。

二、中断申请


     60中断源,其中独立的中断和含有子中断的中断共32个。它们是位或共存。

1 配置中断控制寄存器  SUB子  SRC源  PND--PENDING 挂起

  1SRCPND---申请中断   每一位对应一个总(独立)的中断源

      手动写1---自动清0---有中断产生的那位就自动置 -----在中断函数中,又要重新手动写1

  2MASK  ----相当于一个开关

  3MODE  ---IRQ FIQ   FIQ最多只能有一个,只有非常紧急的中断 才需要配置成FIQ

  4)  INTPND---中断挂起寄存器

        手动写1---自动清0经过仲裁-响应中断的那位就自动置1  -----在中断函数中又要重新手动写1,而且是在清SRCPND之后才清。

  5priority 设置中断优先级

Note:使用中断时应先开启cpsr的中断控制位 

/***********************************************
Function  name  :   irq_cpsr_enable
Description     :   开启cpsr寄存器的外部中断使能位
Input parameter :   none
Return          :   none	 	
Others		    :                     	                    
*************************************************/
void irq_cpsr_enable(void)
{
		//开启总中断
	__asm{ 
    	MRS R0,CPSR 
     	BIC R0, R0, #(1 << 7) 
     	MSR CPSR_c, R0             
 	 }
}


三、按键中断程序

/***********************************************
Function  name  :   key_irq
Description     :   key 中断处理函数
Input parameter :   none
Return          :   none	 	
Others		    :                    	                    
*************************************************/
static void __irq key_irq(void)
{
	//led_contrl(LED4,LEDON);
	unsigned temp;
	temp = rEINTPEND;
	//key1
	if(temp & (1 << 8))
	{
		led_turn(LED1);
		uart_printf("key1 intterupt\n");
	}
	//key2
	else if(temp & (1 << 11))
	{
		led_turn(LED2);
		uart_printf("key2 intterupt\n");
	}
	//key3
	else if(temp & (1 << 13))
	{
		led_turn(LED3);
		uart_printf("key3 intterupt\n");
	}
	//key4
	else if(temp & (1 << 14))
	{
		led_turn(LED4);
		uart_printf("key4 intterupt\n");
	}
	//key5
	else if(temp & (1 << 15))
	{
		led_contrl(LED3,LEDOFF);
		uart_printf("key5 intterupt\n");
	}
	//key6
	else if(temp & (1 << 19))
	{
		led_contrl(LED4,LEDOFF);
		uart_printf("key6 intterupt\n");
		quit = 1;
	}
	
	//清中断
	rSRCPND |= 0x1<<5;
	rINTPND |= 0x1<<5;
	rEINTPEND |= (1<<8)|(1<<11)|(1<<13)|(1<<14)|(1<<15)|(1<<19);
}

/***********************************************
Function  name  :   key_irq_init
Description     :   按键中断初始化
Input parameter :   none
Return          :   none	 	
Others		    :   中断方式                  	                    
*************************************************/
void key_irq_init(void)
{	
	//设置中断模式为IRQ模式
	rINTMOD = 0x0;
	
	//配置GPG0,3,5,6,7,11为中断模式
	rGPGCON &= ~((0x3<<22)|(0x3<<14)|(0x3<<12)|(0x3<<10)|(0x3<<6)|(0x3<<0));
	rGPGCON |= (0x2<<22)|(0x2<<14)|(0x2<<12)|(0x2<<10)|(0x2<<6)|(0x2<<0);
	
	//设置中断触发方式为下降沿触发
	rEXTINT1 &= ~((0xf<<28)|(0xf<<24)|(0xf<<20)|(0xf<<12)|(0xf<<0));
	rEXTINT1 |= ((0xa<<28)|(0xa<<24)|(0xa<<20)|(0xa<<12)|(0xa<<0));
	rEXTINT2 &= ~(0xf<<12);
	rEXTINT2 |= (0xa<<12);
	
	//清中断标志位
	rEINTPEND |= (1<<8)|(1<<11)|(1<<13)|(1<<14)|(1<<15)|(1<<19);
	
	//取消中断屏蔽 外部中断8~23
	rINTMSK &= ~(0x1 << 5);
	rEINTMASK &= ~((1<<8)|(1<<11)|(1<<13)|(1<<14)|(1<<15)|(1<<19));
	
	//设置中断处理函数
	pISR_EINT8_23 = (unsigned)key_irq;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值