新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應用 > GNU ARM匯編(五)中斷匯編之嵌套中斷處理

GNU ARM匯編(五)中斷匯編之嵌套中斷處理

作者: 時間:2016-11-20 來源:網(wǎng)絡 收藏
在上篇《GNU ARM匯編--(四)中斷匯編之非嵌套中斷處理》中分析了最簡單的中斷處理的寫法,再看TQ2440啟動代碼中的中斷向量表的寫法就一目了然了.今天抽時間對嵌套中斷處理的學習做下整理.

嵌套中斷處理的核心代碼如下:

本文引用地址:http://m.butianyuan.cn/article/201611/318690.htm

;/*; *  ____________________________________________________________________; * ; *  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


代碼的關(guān)鍵就是在中斷后切換到SVC模式下,利用svc mode的stack來實現(xiàn)中斷嵌套過程的備份以及恢復操作.從代碼中可以看到,從R0到PC都在棧中有備份,這里我們叫棧幀.記得《深入理解計算機系統(tǒng)》一書在講x86匯編的函數(shù)調(diào)用時也是棧幀的概念.這點上中斷嵌套和函數(shù)調(diào)用有相似之處.有了這個棧幀,利用壓棧出棧操作就一切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圖,就發(fā)現(xiàn)堆棧操作并沒有問題.可以假設(shè)剛開中斷立馬就有新的中斷了,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就不會出現(xiàn)錯誤了,在最后LDMIA r13!,{r14,pc}^ 中r14得到恢復.而r2保存的是spsr,也就是svc模式的狀態(tài),一直不變,不用擔心會被覆蓋.

最后,再看了一遍圖,覺得r10和r11的幀可以省去,因為r4-r9是用來存atpcs的r0-r3,r12,r14,而r10和r11用不到.貌似可以省點空間和時間,具體的待會實驗一下.

下面給出實際的嵌套中斷處理,利用r10來保存INTOFFSET的值,根據(jù)該值來判定是什么中斷,從而做不同的處理.具體的效果是:代碼會做流水燈的動作,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 @設(shè)置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跳轉(zhuǎn)到各自的中斷服務程序的,比如blne blink1和blne blink3,值得對比的blink1和blink3,他們的不同在于blink1自己用代碼做了延時,而blink3是調(diào)用bl delay做的延時,那么這個時候要注意的就是lr的push和pop操作,不然lr就被覆蓋了,程序不能正確返回了.

注意了以上兩點,程序上達到了嵌套處理的效果.因為采用的是下降邊沿觸發(fā),而按鍵沒有防抖處理,有時候單按一個鍵就有嵌套中斷了.最后總結(jié)一下這種處理的優(yōu)缺點:優(yōu)點是在為一個中斷處理服務完成前允許其它中斷,以縮短中斷延遲;而缺點是不處理中斷的優(yōu)先級,因此低優(yōu)先級的中斷會阻塞高優(yōu)先級的中斷.



評論


技術(shù)專區(qū)

關(guān)閉