微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > GNU ARM汇编(五)中断汇编之嵌套中断处理

GNU ARM汇编(五)中断汇编之嵌套中断处理

时间:11-20 来源:互联网 点击:

代码的关键就是在中断后切换到SVC模式下,利用svc mode的stack来实现中断嵌套过程的备份以及恢复操作.从代码中可以看到,从R0到PC都在栈中有备份,这里我们叫栈帧.记得《深入理解计算机系统》一书在讲x86汇编的函数调用时也是栈帧的概念.这点上中断嵌套和函数调用有相似之处.有了这个栈帧,利用压栈出栈操作就一切ok了.

刚看这个代码,对有个地方有疑问,就是觉得中断开早了:

BIC r1,r1,#I_Bit ; 8 :
MSR CPSR_c,r1 ; 8 : enable int
STMDB r13!,{r4-r7} ; 9 : save r4-r7 SVC
STR r2,[r13,#FRAME_PSR] ; 9 : save PSR
STR r8,[r13,#FRAME_R12] ; 9 : save r12
STR r9,[r13,#FRAME_PC] ; 9 : save pc
STR r14,[r13,#FRAME_LR] ; 9 : save lr

觉得开中断的代码应该放在后面,这样才能保证svc mode下的stack frame不会被破坏.但在草稿纸上画一下irq和svc下的stack图,就发现堆栈操作并没有问题.可以假设刚开中断立马就有新的中断了,r4-r7 r8 r9都有在STMIA r13,{r4-r11} 中保存到svc的stack中,LDMIA r0,{r4-r9} 和STMDB r13!,{r4-r7} 保证了最初的r0-r3在栈中,而LDMIA r0,{r4-r9}和STR r8,[r13,#FRAME_R12] 以及STR r9,[r13,#FRAME_PC] 保证了R12和PC,保证正确返回.(这里的r9装的是r14_irq,所以pc就是r14_irq,这样就保证了从中断服务例程中返回).至于STR r14,[r13,#FRAME_LR]中的r14是r14_svc,将其压入svc的stack中,中断例程用bl就不会出现错误了,在最后LDMIA r13!,{r14,pc}^ 中r14得到恢复.而r2保存的是spsr,也就是svc模式的状态,一直不变,不用担心会被覆盖.

最后,再看了一遍图,觉得r10和r11的帧可以省去,因为r4-r9是用来存atpcs的r0-r3,r12,r14,而r10和r11用不到.貌似可以省点空间和时间,具体的待会实验一下.

下面给出实际的嵌套中断处理,利用r10来保存INTOFFSET的值,根据该值来判定是什么中断,从而做不同的处理.具体的效果是:代码会做流水灯的动作,Key1代表INT1,中断处理动作是4个灯全全亮然后全灭,Key4代表代表INT0,中断处理动作是第一个灯和第三个灯亮,然后第二个灯和第四个灯亮.

/*simple interruptioncopyleft@dndxhej@gmail.com*/.equ	Maskmd,	0x1f                     @ processor mode mask.equ	SVC32md,     0x13                     @ SVC mode.equ	I_Bit,       0x80                     @ IRQ bit .equ	FRAME_R0,    0x00			.equ	FRAME_R1,    FRAME_R0+4.equ	FRAME_R2,    FRAME_R1+4.equ	FRAME_R3,    FRAME_R2+4.equ	FRAME_R4,    FRAME_R3+4.equ	FRAME_R5,    FRAME_R4+4.equ	FRAME_R6,    FRAME_R5+4.equ	FRAME_R7,    FRAME_R6+4.equ	FRAME_R8,    FRAME_R7+4.equ	FRAME_R9,    FRAME_R8+4.equ	FRAME_R10,   FRAME_R9+4.equ	FRAME_R11,   FRAME_R10+4.equ	FRAME_R12,   FRAME_R11+4.equ	FRAME_PSR,   FRAME_R12+4.equ	FRAME_LR,    FRAME_PSR+4.equ	FRAME_PC,    FRAME_LR+4.equ	FRAME_SIZE,  FRAME_PC+4.equ   NOINT, 0xc0.equ	WTCON,	0x53000000.equ 	GPBCON,	0x56000010  	@led.equ	GPBDAT,	0x56000014  	@led.equ   GPBUP,        0x56000018    @led.equ 	GPFCON, 0x56000050  	@interrupt config.equ	EINTMASK, 0x560000a4.equ 	EXTINT0,  0x56000088.equ 	EXTINT1,  0x5600008c.equ 	EXTINT2,  0x56000090.equ	INTMSK,	 0x4A000008.equ   EINTPEND,     0x560000a8.equ   INTSUBMSK,    0X4A00001C.equ   SRCPND,   0X4A000000.equ   INTPND,   0X4A000010.equ	INTOFFSET,	0x4A000014.global _start_start:		b	resetldr     pc, _undefined_instructionldr 	pc, _software_interruptldr	pc, _prefetch_abortldr	pc, _data_abortldr	pc, _not_used@b	irqldr 	pc, _irqldr 	pc, _fiq_undefined_instruction:		.word undefined_instruction_software_interrupt:		.word software_interrupt_prefetch_abort:		.word prefetch_abort_data_abort:			.word data_abort_not_used:			.word not_used_irq:				.word irq_fiq:				.word fiq.balignl 16,0xdeadbeefreset:ldr     r3, =WTCONmov	r4, #0x0                       

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

网站地图

Top