中断处理流程

以s3c2440为例讲述,中断处理流程:

1.开中断。产生外部中断。流程如下按键----->中断控制器------->cpu(总开关)

* 按键:

需要设置GPIO为中断模式,上升沿还是下降沿触发。

* 中断控制器:

中断处理流程_第1张图片

* cpu:

中断处理流程_第2张图片

2.中断处理

* 跳转到中断向量表。如果从nandflash启动,代码已经重定位到sdram,此时候是绝对跳转,会跳转的真正的0地址(sram)。

中断向量表如下:

中断处理流程_第3张图片

*    硬件操作
     a. lr_irq保存有被中断模式中的下一条即将执行的指令的地址
     b. SPSR_irq保存有被中断模式的CPSR
     c. CPSR中的M4-M0被设置为10010, 进入到irq模式
     d. 跳到0x18的地方执行程序 

*软件操作

a. 设置sp_irq栈,这个是irq模式的sp,sp_user不用了,两个是独立的sp,所以需要重新设置。

b.保存现场
    /* 在irq异常处理函数中有可能会修改r0-r12, 所以先保存 */
    /* lr-4是异常处理完后的返回地址, 也要保存 */ 方便最后pc =lr,可以从异常模式跳转到用户模式

c.处理irq异常 

跳转到中断处理函数

d.恢复现场。

代码如下:

中断向量表:

.text
.global _start

_start:
	b reset          /* vector 0 : reset */
	ldr pc, und_addr /* vector 4 : und */
	ldr pc, swi_addr /* vector 8 : swi */
	b halt			 /* vector 0x0c : prefetch aboot */
	b halt			 /* vector 0x10 : data abort */
	b halt			 /* vector 0x14 : reserved */
	ldr pc, irq_addr /* vector 0x18 : irq */
	b halt			 /* vector 0x1c : fiq */

und_addr:
	.word do_und

swi_addr:
	.word do_swi

irq_addr:
	.word do_irq

中断处理及跳转:

.align 4

do_irq:
	/* 执行到这里之前:
	 * 1. lr_irq保存有被中断模式中的下一条即将执行的指令的地址
	 * 2. SPSR_irq保存有被中断模式的CPSR
	 * 3. CPSR中的M4-M0被设置为10010, 进入到irq模式
	 * 4. 跳到0x18的地方执行程序 
	 */

	/* sp_irq未设置, 先设置它 */
	ldr sp, =0x33d00000

	/* 保存现场 */
	/* 在irq异常处理函数中有可能会修改r0-r12, 所以先保存 */
	/* lr-4是异常处理完后的返回地址, 也要保存 */
	sub lr, lr, #4
	stmdb sp!, {r0-r12, lr}  
	
	/* 处理irq异常 */
	bl handle_irq_c
	
	/* 恢复现场 */
	ldmia sp!, {r0-r12, pc}^  /* ^会把spsr_irq的值恢复到cpsr里 */

中断处理函数:

void handle_irq_c(void)
{
	/* 分辨中断源 */
	int bit = INTOFFSET;

	/* 调用对应的处理函数 */
	irq_array[bit](bit); //函数指针数组,
	
	/* 清中断 : 从源头开始清 */
	SRCPND = (1<

 

 

 

你可能感兴趣的:(linux,驱动)