您的位置 首页 基础

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

在上篇《GNUARM汇编–(四)中断汇编之非嵌套中断处理》中分析了最简单的中断处理的写法,再看TQ2440启动代码中的中断向量表的写法…

在上篇《GNU ARM汇编–(四)中止汇编之非嵌套中止处理》中剖析了最简略的中止处理的写法,再看TQ2440发动代码中的中止向量表的写法就一望而知了.今日抽时间对嵌套中止处理的学习做下收拾.

嵌套中止处理的中心代码如下:

;/*; *  ____________________________________________________________________; * ; *  Copyright (c) 2004, Andrew N. Sloss, Chris Wright and Dominic Symes; *  All rights reserved.; *  ____________________________________________________________________; * ; *  NON-COMMERCIAL USE License; *  ; *  Redistribution and use in source and binary forms, with or without ; *  modification, are permitted provided that the following conditions ; *  are met: ; *  ; *  1. For NON-COMMERCIAL USE only.; * ; *  2. Redistributions of source code must retain the above copyright ; *     notice, this list of conditions and the following disclaimer. ; * ; *  3. Redistributions in binary form must reproduce the above ; *     copyright notice, this list of conditions and the following ; *     disclaimer in the documentation and/or other materials provided ; *     with the distribution. ; * ; *  4. All advertising materials mentioning features or use of this ; *     software must display the following acknowledgement:; * ; *     This product includes software developed by Andrew N. Sloss,; *     Chris Wright and Dominic Symes. ; * ; *   THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS AND ANY ; *   EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ; *   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ; *   PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE ; *   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, ; *   OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ; *   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, ; *   OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ; *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR ; *   TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ; *   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY ; *   OF SUCH DAMAGE. ; * ; *  If you have questions about this license or would like a different; *  license please email :; * ; *  andrew@sloss.net; * ; * ; */;/*; *; *  Module       : nih9_9.s; *  Descriptions : Nested Interrupt Handler; *  Example      : 9.9; *  OS           : generic; *  Platform     : generic; *  History      :; *; *  31th December 2003; *  - added header; *; */EXPORT nestedInterruptHandlerMaskmd     EQU 0x1f                     ; processor mode maskSVC32md    EQU 0x13                     ; SVC modeI_Bit      EQU 0x80                     ; IRQ bit FRAME_R0   EQU 0x00			FRAME_R1   EQU FRAME_R0+4FRAME_R2   EQU FRAME_R1+4FRAME_R3   EQU FRAME_R2+4FRAME_R4   EQU FRAME_R3+4FRAME_R5   EQU FRAME_R4+4FRAME_R6   EQU FRAME_R5+4FRAME_R7   EQU FRAME_R6+4FRAME_R8   EQU FRAME_R7+4FRAME_R9   EQU FRAME_R8+4FRAME_R10  EQU FRAME_R9+4FRAME_R11  EQU FRAME_R10+4FRAME_R12  EQU FRAME_R11+4FRAME_PSR  EQU FRAME_R12+4FRAME_LR   EQU FRAME_PSR+4FRAME_PC   EQU FRAME_LR+4FRAME_SIZE EQU FRAME_PC+4AREA nih9_9,CODE,readonlynestedInterruptHandler ; instruction       state : comment		SUB     r14,r14,#4                 ; 2 :STMDB   r13!,{r0-r3,r12,r14}       ; 2 : save context; BL      read_RescheduleFlag        ; 3 : more processingCMP     r0,#0                      ; 3 : if processing?LDMNEIA r13!,{r0-r3,r12,pc}^       ; 4 :   then return MRS     r2,SPSR                    ; 5 : copy SPSR_irqMOV     r0,r13                     ; 5 : copy r13_irqADD     r13,r13,#6*4               ; 5 : reset stackMRS     r1,CPSR                    ; 6 : copy CPSRBIC     r1,r1,#Maskmd              ; 6 :ORR     r1,r1,#SVC32md             ; 6 :MSR     CPSR_c,r1                  ; 6 : change SVC modeSUB     r13,r13,#FRAME_SIZE-FRAME_R4 ; 7 : make stack space STMIA   r13,{r4-r11}               ; 7 : save r4-r11LDMIA   r0,{r4-r9}                 ; 7 : r4-r9 IRQ stack BIC     r1,r1,#I_Bit               ; 8 : MSR     CPSR_c,r1                  ; 8 : enable intSTMDB   r13!,{r4-r7}               ; 9 : save r4-r7 SVCSTR     r2,[r13,#FRAME_PSR]        ; 9 : save PSRSTR     r8,[r13,#FRAME_R12]        ; 9 : save r12STR     r9,[r13,#FRAME_PC]         ; 9 : save pc      STR     r14,[r13,#FRAME_LR]        ; 9 : save lr; LDMIA   r13!,{r0-r12,r14}          ; 11 : restore contextMSR     SPSR_cxsf,r14              ; 11 : restore SPSRLDMIA   r13!,{r14,pc}^             ; 11 : returnread_RescheduleFlag; MOV     r0,#0                      ; more processing MOV     pc,r14                     ; returnEND

代码的要害便是在中止后切换到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                     str	r4, [r3]	@ disable watchdog    ldr	r0, =GPBCONldr	r1, =0x15400str	r1, [r0]ldr	r2, =GPBDATldr	r1, =0x160str	r1, [r2]bl delaymsr cpsr_c, #0xd2 @进入中止形式ldr sp, =0xc00 @中止形式的栈指针界说msr cpsr_c, #0xd3 @进入svc形式ldr sp, =0xfff @设置svc形式的栈指针@--------------------------------------------ldr	r0, =GPBUPldr	r1, =0x03f0  str	r1, [r0]      ldr	r0, =GPFCONldr	r1, =0x2ea@0x2    str	r1, [r0]  ldr	r0, =EXTINT0@ldr	r1, =0x8f888@0x0@0x8f888      @~(7|(7<<4)|(7<<8)|(7<<16))ldr	r1, =0xafaaastr	r1, [r0]  ldr	r0, =EINTPENDldr	r1, =0xf0@0b10000str	r1, [r0]  ldr	r0, =EINTMASKldr	r1, =0x00@0b00000str	r1, [r0]  ldr	r0, =SRCPNDldr	r1, =0xff@0x1@0b11111str	r1, [r0]  ldr	r0, =INTPNDldr	r1, =0xff@0x1@0b11111str	r1, [r0]  ldr	r0, =INTMSKldr	r1, =0xffffff00@0b00000str	r1, [r0]  MRS r1, cpsrBIC r1, r1, #0x80MSR cpsr_c, r1bl     mainirq:sub     r14,r14,#4                 @ 2 :stmdb   sp!,{r0-r3,r12,r14}       @ 2 : save context@ @BL      read_RescheduleFlag        @ 3 : more processing@CMP     r0,#0                      @ 3 : if processing?@LDMNEIA sp!,{r0-r3,r12,pc}^       @ 4 :   then return @@@@@@@@@@@@@@@@ldr r10,=INTOFFSET           @用r10保存中止的offsetldr r10,[r10]ldr r0,=EINTPENDldr r1,=0xf0str r1,[r0] ldr	r0, =SRCPNDldr	r1, =0x3f@0b11111str	r1, [r0]  ldr	r0, =INTPNDldr	r1, =0x3f@0b11111str	r1, [r0]  @@@@@@@@@@@@@@mrs     r2,SPSR                    @ 5 : copy SPSR_irqmov     r0,sp                     @ 5 : copy sp_irqadd     sp,sp,#6*4               @ 5 : reset stackmrs     r1,CPSR                    @ 6 : copy CPSRbic     r1,r1,#Maskmd              @ 6 :orr     r1,r1,#SVC32md             @ 6 :msr     CPSR_c,r1                  @ 6 : change SVC modesub     sp,sp,#FRAME_SIZE-FRAME_R4 @ 7 : make stack space stmia   sp,{r4-r11}               @ 7 : save r4-r11ldmia   r0,{r4-r9}                 @ 7 : r4-r9 IRQ stack bic     r1,r1,#I_Bit               @ 8 : msr     CPSR_c,r1                  @ 8 : enable intstmdb   sp!,{r4-r7}               @ 9 : save r4-r7 SVCstr     r2,[sp,#FRAME_PSR]        @ 9 : save PSRstr     r8,[sp,#FRAME_R12]        @ 9 : save r12str     r9,[sp,#FRAME_PC]         @ 9 : save pc      str     r14,[sp,#FRAME_LR]        @ 9 : save lr@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@cmp	r10,#0x0bleq	blink1cmp	r10,#0x1bleq	blink3@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@LDMIA   sp!,{r0-r12,r14}          @ 11 : restore contextMSR     SPSR_cxsf,r14              @ 11 : restore SPSRLDMIA   sp!,{r14,pc}^             @ 11 : returndelay:ldr r3,=0xffffdelay1:sub r3,r3,#1cmp r3,#0x0bne delay1mov pc,lrblink1:ldr	r0, =GPBDATldr	r1, =0x000str	r1, [r0]ldr r3,=0xffffdelay2:sub r3,r3,#1cmp r3,#0x0bne delay2ldr	r0, =GPBDATldr	r1, =0x1f0str	r1, [r0]ldr r3,=0xffffdelay3:sub r3,r3,#1cmp r3,#0x0bne delay3mov pc,lrblink2:ldr	r0, =GPBDATldr	r1, =0x140str	r1, [r0]ldr r3,=0xffffdelay12:sub r3,r3,#1cmp r3,#0x0bne delay12ldr	r0, =GPBDATldr	r1, =0xa0str	r1, [r0]ldr r3,=0xffffdelay13:sub r3,r3,#1cmp r3,#0x0bne delay13mov pc,lrblink3:ldr	r0, =GPBDATldr	r1, =0x0a0str	r1, [r0]stmfd	sp!,{lr}bl delayldr	r0, =GPBDATldr	r1, =0x140str	r1, [r0]bl delayldmfd	sp!,{lr}mov pc,lrmain:ledloop:ldr r1,=0x1c0str r1,[r2]bl delayldr r1,=0x1a0str r1,[r2]bl delayldr r1,=0x160str r1,[r2]bl delayldr r1,=0x0e0str r1,[r2]bl delayb ledloopundefined_instruction:nopsoftware_interrupt:nopprefetch_abort:	nopdata_abort:nopnot_used:nopfiq:nop

代码比较繁琐,有几点值得留意:在嵌套中止处理中,压栈后先保存INTOFFSET的值,再清中止(SRCPND和INTPND).由于SRCPND和INTPND铲除后INTOFFSET就主动铲除了,所以要先保存.在中止服务程序中,是能够用bl跳转到各自的中止服务程序的,比方blne blink1和blne blink3,值得比照的blink1和blink3,他们的不同在于blink1自己用代码做了延时,而blink3是调用bl delay做的延时,那么这个时分要留意的便是lr的push和pop操作,否则lr就被掩盖了,程序不能正确回来了.

留意了以上两点,程序上达到了嵌套处理的作用.由于选用的是下降边缘触发,而按键没有防抖处理,有时分单按一个键就有嵌套中止了.最终总结一下这种处理的优缺陷:长处是在为一个中止处理服务完结前答应其它中止,以缩短中止推迟;而缺陷是不处理中止的优先级,因而低优先级的中止会堵塞高优先级的中止.

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

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

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

微信扫一扫关注我们

返回顶部