微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM微处理器的编程模型之:异常中断处理

ARM微处理器的编程模型之:异常中断处理

时间:09-13 来源:互联网 点击:

ed Install_Handler (ed location, ed *vector)

{ unsigned vec, oldvec;

vec = ((unsigned)location - (unsigned)vector - 0x8) | 0xe59ff000;

oldvec = *vector;

*vector = vec;

return (oldvec);

}

3.4.7 FIQ和IRQ中断处理函数的设计

1.中断分支

ARM内核只有两个外部中断输入信号nFIQ和nIRQ。但对于一个系统来说,中断源可能多达几十个。为此,在系统集成的时候,一般都会有一个异常控制器来处理异常信号,如图3.8所示。

图3.8 中断系统

这时候用户程序可能存在多个IRQ/FIQ的中断处理函数。为了使从向量表开始的跳转始终能找到正确的处理函数入口,需要设置一套处理机制和方法。

多数情况下是由软件来处理异常分支的,因为软件可以通过读取中断控制器来获得中断源的信息,如图3.9所示。

有些芯片可能支持特殊的硬件分支功能,这需要查看具体的芯片说明。

因为软件的灵活性,可以设计出比图3.9更好的流程控制方法,如图3.10所示。

Int_vector_table是用户自己开辟的一块存储器空间,里面按次序存放异常处理函数的地址。IRQ_Handler()从中断控制器获取中断源信息,然后再从Int_vector_table中的对应地址单元得到异常处理函数的入口地址,完成一次异常响应的跳转。这种方法的好处是用户程序在运行过程中,能够很方便地动态改变异常服务内容。

图3.9 软件控制中断分支

图3.10 灵活的软件分支设计

进入异常处理程序后,用户可以完全按照自己的意愿来进行程序设计,包括调用Thumb状态的函数等。但对于绝大多数的系统来说,有两个步骤必须处理,一是现场保护,二是要把中断控制器中对应的中断状态标识清除,表明该中断请求已经得到响应,否则,中断函数退出以后,又会被再一次触发,从而进入周而复始的死循环。

2.ARM编译器对中断处理函数编写的扩展

考虑到中断处理函数在现场保护和返回地址的处理上与普通函数的不同之处,不能直接把普通函数体连接到异常向量表上,需要在上面加上一层封装,下面是一个例子。

IRQ_Handler ;中断相应函数

STMFD SP!,{r0-r12,lr} ;保护现场,一般只需要保护{r0-r3,LR}

BL IrqHandler ;进入普通处理函数,C或汇编均可

……

LDMFD sp!,{r0-r12,LR} ;恢复现场

SUBS pc,lr,#4 ;中断返回,注意返回地址

为了方便使用高级语言直接编写异常处理函数,ARM编译器对此做了特定的扩展,可以使用函数声明关键字_irq,这样编译出来的函数就可以满足异常响应对现场保护和恢复的需要,并且自动加入LR减4的处理,符合IQR和FIQ中断处理的要求。

下面的例子显示了使用_irq对中断处理函数产生的影响。

C语言源程序如下。

__irq void IRQHandler (void)

{

volatile unsigned int *base = (unsigned int *) 0x80000000;

if (*base == 1)

{

/*调用C语言中断处理函数*/

C_int_handler();

}

/*清楚中断标志*/

*(base+1) = 0;

}

使用armcc编译出的汇编代码如下。

IRQHandler PROC

STMFD sp!,{r0-r4,r12,lr}

MOV r4,#0x80000000

LDR r0,[r4,#0]

SUB sp,sp,#4

CMP r0,#1

BLEQ C_int_handler

MOV r0,#0

STR r0,[r4,#4]

ADD sp,sp,#4

LDMFD sp!,{r0-r4,r12,lr}

SUBS pc,lr,#4

ENDP

如果不使用_irq子程序声明关键字,编译出的汇编代码如下。

IRQHandler PROC

STMFD sp!,{r4,lr}

MOV r4,#0x80000000

LDR r0,[r4,#0]

CMP r0,#1

BLEQ C_int_handler

MOV r0,#0

STR r0,[r4,#4]

LDMFD sp!,{r4,pc}

ENDP

3.可重入中断设计

在缺省情况下,ARM中断是不可重入的。因为一旦进入异常响应状态,ARM自动关闭中断使能。如果在异常处理过程中,简单地打开中断使能而发生中断嵌套时,显然新的异常处理将破坏原来的中断现场而导致出错。但有时需要中断必须是可重入的,因此要通过程序设计来解决这个问题。其中有两个关键问题。

① 新中断使能之前,必须要保护好前一个中断的现场信息。比如LR_irq和SPSR_irq等,这一点比较容易做的。

② 中断处理过程中对BL进行保护。

在中断处理函数中发生函数调用BL是很常见的,假设有下面一种情况。

IRQ_Handler:

……

BL Foo

ADD

其中,

Foo:

STMFD SP!,{r0-r3,LR}

……

LDMFD SP!{r0-r3,PC}

上述程序,在IRQ处理函数IRQ_Handler()中调用了函数Foo()。若是在IRQ_Handler()里面中断可重入的话,可能发生问题,考察下面的情况:当新的中断请求恰好在“BL Foo”指令执行完成后发生。这时候LR_irq寄存器(因在IRQ模式下,所以是LR_irq)的值将调整为BL指令的下一条指令(ADD)地址,使其能从Foo()正确返回;但是因为这时候发生了中断请求,接下来要进行新中断的响应

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top