您的位置 首页 电子

ARM处理器架构反常/中止处理

中断是我们嵌入式开发很常用到的一种资源和编程手段。这篇文章重点分析arm的中断处理流程。首先,中断是异常的一种。当发生一种异常时,处…

中止是咱们嵌入式开发很常用到的一种资源和编程手法。这篇文章要点剖析arm中止处理流程。

首要,中止是反常的一种。当产生一种反常时,处理器会进入不同的作业形式。ARM的反常和相应的形式之间的对应联系见下表:

当一个反常导致形式的改动时,ARM核主动地:

1、把cpsr保存到相应形式下的spsr

2、把pc保存到相应形式下的lr

3、设置cpsr为相应反常形式

4、设置pc为相应反常处理程序的进口地址

关于IRQ或许FIQ而言,还多一项改变:禁用相关的中止IRQ或FIQ,制止同类型的其他中止被触发。(这也是主动完成的,因而正常情况下,ARM中止不行嵌套)

从反常中止处理程序退出时,需求咱们在程序顶用软件完成下面两个操作:

1、从spsr_mode中康复数据到cpsr中

2、从lr_mode中康复内容到pc中,返回到反常中止的指令的下一条政令处履行.

2440默许的有一个反常向量表,即产生某一个反常后,会依据反常向量表设置pc为相应的处理函数进口地址。

地址

反常称号

指令

0x00

复位反常

B RestHandler

0x04

未定义指令反常

B HandlerUndef

0x08

软件中止反常

B HandlerSWI

0x0C

指令预取反常

B HandlerPabort

0x10

数据预取反常

B HandlerDabort

0x14

保存

0x18

IRQ中止反常

B HandlerIRQ

0x1C

FIQ中止反常

B HandlerFIQ

上表中的 指令都是在2440init.s中的程序表明。

下面,咱们结合板子自带的2440test源代码中的2440init.s中的反常处理,来剖析arm中止处理的完成。

首要,在2440init.s中有:

__ENTRYb	ResetHandlerb	HandlerUndef	;handler for Undefined modeb	HandlerSWI	    ;handler for SWI interruptb	HandlerPabort	;handler for PAbortb	HandlerDabort	;handler for DAbortb	.		        ;reservedb	HandlerIRQ	;handler for IRQ interruptb	HandlerFIQ	;handler for FIQ interrupt

这儿便是相应的 反常处理向量表。程序正常发动就跳转到resethandler,如果是产生中止就跳转到handlerIRQ。关于handlerIRQ,它是用一个宏完成的。

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

上面是宏的声明。下面是详细用到宏的当地。

HandlerFIQ      HANDLER HandleFIQHandlerIRQ      HANDLER HandleIRQHandlerUndef    HANDLER HandleUndefHandlerSWI      HANDLER HandleSWIHandlerDabort   HANDLER HandleDabortHandlerPabort   HANDLER HandlePabort

上面的这段程序在编译的时分会被编译器打开,咱们能够将其间的IRQ相关的打开如下:

HandlerIRQ HANDLER HandleIRQ 会被下面的代码段替换:

HandlerIRQ	sub	sp,sp,#4	;decrement sp(to store jump address)stmfd	sp!,{r0}	;PUSH the work register to stack(lr doest push because it return to original address)ldr     r0,=HandleIRQ   ;load the address of HandleXXX to r0ldr     r0,[r0]	        ;load the contents(service routine start address) of HandleXXXstr     r0,[sp,#4]      ;store the contents(ISR) of HandleXXX to stackldmfd   sp!,{r0,pc}     ;POP the work register and pc(jump to ISR)

因而,产生中止时,就会b HandlerIRQ,跳转到上面的代码进行履行。依照上面的流程,处理器会把HandleIRQ地址中所存储的数 交给pc指针,作为下一条指令的地址,然后履行。那么HandleIRQ地址中存储的数是什么呢?

在2440init.s中有这样一段程序:

ldr r0,=HandleIRQ ;This routine is neededldr r1,=IsrIRQ    ;if there isnt subs pc,lr,#4 at 0x18, 0x1cstr r1,[r0]

从这儿,能够看出,HandleIRQ中存的是IsrIRQ。所以处理器会跳转到isrIRQ中履行。

IsrIRQsub	sp,sp,#4       ;reserved for PCstmfd	sp!,{r8-r9}ldr	r9,=INTOFFSETldr	r9,[r9]ldr	r8,=HandleEINT0add	r8,r8,r9,lsl #2ldr	r8,[r8]str	r8,[sp,#8]ldmfd	sp!,{r8-r9,pc}

在上面的程序中,INTOFFSET表明的是中止号关于EINT0的偏移号。这样核算得到中止向量号之后,跳转到中止函数进行处理。关于,上面的程序古怪的一点是没有看到康复cpsr和pc指针。因而,能够揣度,关于中止函数在ADS中有特别的声明方法,如:static void __irq Uart_DMA_ISR(void)。像这种声明方法,在编译的时分,编译器会主动在函数的结尾增加康复cpsr和pc的句子。别的, 寄存器r0-r12也是需求维护的,由于在中止函数和本来的上下文中都会用到,所以,我以为 编译器在中止处理函数中对r0-r12也进行了维护和康复。

别的,在ucosII中,对IsrIRQ函数进行了修正,咱们后边再进行剖析。

别的,咱们用软件完成了一套中止向量表:

ALIGNAREA RamData, DATA, READWRITE^   _ISR_STARTADDRESS		; _ISR_STARTADDRESS=0x33FF_FF00HandleReset 	#   4HandleUndef 	#   4HandleSWI	#   4HandlePabort    #   4HandleDabort    #   4HandleReserved  #   4HandleIRQ	#   4HandleFIQ	#   4;Dont use the label IntVectorTable,;The value of IntVectorTable is different with the address you think it may be.;IntVectorTable;@0x33FF_FF20HandleEINT0		#   4HandleEINT1		#   4HandleEINT2		#   4HandleEINT3		#   4HandleEINT4_7	#   4HandleEINT8_23	#   4HandleCAM		#   4		; Added for 2440.HandleBATFLT	#   4HandleTICK		#   4HandleWDT		#   4HandleTIMER0 	#   4HandleTIMER1 	#   4HandleTIMER2 	#   4HandleTIMER3 	#   4HandleTIMER4 	#   4HandleUART2  	#   4;@0x33FF_FF60HandleLCD 		#   4HandleDMA0		#   4HandleDMA1		#   4HandleDMA2		#   4HandleDMA3		#   4HandleMMC		#   4HandleSPI0		#   4HandleUART1		#   4HandleNFCON		#   4		; Added for 2440.HandleUSBD		#   4HandleUSBH		#   4HandleIIC		#   4HandleUART0 	#   4HandleSPI1 		#   4HandleRTC 		#   4HandleADC 		#   4;@0x33FF_FFA0

之前,咱们在产生中止时,pc指针就跳转到了 HandleIRQ地址中所存储的数 出履行。也便是说在HandleIRQ中存的是反常处理函数的进口地址。这便是反常处理向量表的效果。
所以,咱们能够看出,关于2440init.s完成的反常处理,选用的是两级向量表机制。 榜首级向量表是arm核自己完成的,产生相应的反常时,pc指针跳转到0x18地址中存的数,作为进口地址。 第二级向量表是由Handler宏完成的,持续跳转到 HandleIRQ地址中存的数,持续履行。

而关于IRQ来讲,还有第三级的向量表,在IsrIRQ中,又会依据中止号,比方uart2的中止,跳转到 HandleUart2地址中 存的数,持续履行。

在2440init.s中,并没有给HandleUndef等这些地址处赋值,因而,一旦履行到,程序就会跑飞。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qiche/dianzi/277244.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部