ARM汇编嵌套中断处理

来源:互联网 发布:宽带网络那家好 编辑:程序博客网 时间:2024/04/28 13:56

参考书籍:《ARM嵌入式系统开发---软件设计与优化》、《一步步写嵌入式操作系统--ARM编程的方法与实践》

 嵌套中断考虑了当前调用中断处理执行过程中又发送中断的情形。使用类似函数递归调用的栈帧概念来将上下文压入堆栈。

具体参考《ARM嵌入式系统开发》第九章9.3.2部分和《一步步》的第五章5.4部分,前者比较通用完整。描速的都是在IRQ模式下不能简单打开中断,而是转换到SVC模式下保存上下文。

下面核心源代码是摘抄于《ARM嵌入式系统开发》的配套源码:

;/*; *  ____________________________________________________________________; * ; *  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 0x00FRAME_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     ; <insert code here>     BL      read_RescheduleFlag        ; 3 : more processing     CMP     r0,#0                      ; 3 : if processing?     LDMNEIA r13!,{r0-r3,r12,pc}^       ; 4 :   then return      MRS     r2,SPSR                    ; 5 : copy SPSR_irq     MOV     r0,r13                     ; 5 : copy r13_irq     ADD     r13,r13,#6*4               ; 5 : reset stack     MRS     r1,CPSR                    ; 6 : copy CPSR     BIC     r1,r1,#Maskmd              ; 6 :     ORR     r1,r1,#SVC32md             ; 6 :     MSR     CPSR_c,r1                  ; 6 : change SVC mode     SUB     r13,r13,#FRAME_SIZE-FRAME_R4 ; 7 : make stack space      STMIA   r13,{r4-r11}               ; 7 : save r4-r11     LDMIA   r0,{r4-r9}                 ; 7 : r4-r9 IRQ stack      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     ; <insert code here>     LDMIA   r13!,{r0-r12,r14}          ; 11 : restore context     MSR     SPSR_cxsf,r14              ; 11 : restore SPSR     LDMIA   r13!,{r14,pc}^             ; 11 : returnread_RescheduleFlag     ; <implement your own reschedule flag code here>     MOV     r0,#0                      ; more processing      MOV     pc,r14                     ; return     END

将irq和svc两种模式的堆栈图画出来观看的话,理解起来比较直观。因为我是初学,刚开始没能理解其中堆栈操作,原因是:

1.忘记了r0-r12,cpsr是irq和svc共用的堆栈,r13(sp),r14(lr)和spsr是不相同的。

2.对堆栈向下生长不够深刻,刚开始还记得后来有弄反了,导致理解不了,还一度认为书上有错。

3.对ARM的堆栈操作指令和多寄存器传送指令比较生疏,需要查表对照,一步一步得走

另外我觉得书上描速的完成一个栈帧从高地址往低地址的情况好像反了,感觉应该是lr_irq,r14_svc,spsr_irq,r12-r0的顺序。

下面在mini2440板子上實現嵌套中斷:使用了LED PB8(LED4)和PB7(LED3)低電平亮,外部中斷8和19,對應按鍵是K1和K6.

.equ    NOINT,      0xc0 .equ    I_Bit,      0x80 .equ    SVC_MOD,    0x13.equ    IRQ_MOD,    0x12.equ    WTCON,    0x53000000.equ    GPBCON,   0x56000010.equ    GPBDAT,   0x56000014.equ    GPBUP,    0x56000018.equ    GPGCON,   0x56000060.equ    EINTMASK, 0x560000a4  .equ    EXTINT1,  0x5600008c .equ    EXTINT2,  0x56000090.equ    EINTPEND, 0x560000a8  .equ    INTMSK,   0x4A000008        .equ    SRCPND,   0X4A000000  .equ    INTPND,   0X4A000010    .equ    SVC_Stack, 4096.equ    IRQ_Stack, 2048@栈帧定义.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.text.code 32.global _start_start: b resetldr     pc, _undefined_instruction          ldr     pc, _software_interrupt          ldr pc, _prefetch_abort          ldrpc, _data_abort          ldr pc, _not_used          ldr     pc, _irq         ldr     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 r0,=WTCONmov r1,#0x0str r1,[r0] @关看门狗msr cpsr_c,#(IRQ_MOD|NOINT)ldr sp,=IRQ_Stack        msr cpsr_c,#(SVC_MOD|NOINT) ldr sp,=SVC_Stackldr r0,=GPBCONldr r1,=0x14000str r1,[r0] @PB8,7输出ldr r0,=GPBDATmov r1,#0x180str r1,[r0] @8、7高电平        ldr r0,=GPGCONldr r1,=0x800002str r1,[r0] @使能外部中断8,外部中断19ldr r0,=EXTINT1mov r1,#0x03str r1,[r0] @外部8下降沿触发ldr r0,=EXTINT2ldr r1,=0x3000str r1,[r0] @外部19下降沿触发ldr r0, =EINTPEND ldr r1,=0x00fffff0str r1,[r0]@ 清EINTPEND,写1清零ldr r0,=EINTMASKldr r1,=0xfff7feffstr r1,[r0] @使能外部中断8、19,0为使能ldr r0, =SRCPND ldr r1,=0xffffffffstr r1,[r0]@ 清SRCPND,写1清零ldr r0, =INTPND ldr r1,=0xffffffff str r1,[r0]@ 清INTPND,写1清零ldr r0,=INTMSKldr r1,=0xffffffdfstr r1,[r0] @使能外部中断EINT8-23mrs r1, cpsr      bic r1, r1, #I_Bit    msr cpsr_c, r1 @开全局IRQ中断loop:b loopirq_server1:stmfd   sp!,{lr}        ldr r0,=GPBDATldr r1,[r0]bic r2,r1,#0x100str r2,[r0]bl delay1orr r2,r1,#0x100str r2,[r0]@bl delay1ldmfd   sp!,{lr} mov pc,lrirq_server2:stmfd   sp!,{lr}        ldr r0,=GPBDATldr r1,[r0]bic r2,r1,#0x80str r2,[r0]bl delay2orr r2,r1,#0x80str r2,[r0]@bl delay2ldmfd   sp!,{lr} mov pc,lrdelay1:       ldr r12,=0x5ffffffdelay1loop:      sub r12,r12,#1      cmp r12,#0x0      bne delay1loop      mov pc,lrdelay2:       ldr r3,=0x5ffffff  delay2loop:      sub r3,r3,#1      cmp r3,#0x0      bne delay2loop      mov pc,lrundefined_instruction:  nop  software_interrupt:  nop  prefetch_abort:   nop  data_abort:  nop  not_used:  nop  irq:  sub     r14,r14,#4                stmdb   r13!,{r0-r3,r12,r14}         @ save contextldr r0, =EINTPENDldr r10,[r0]ldr r11,=0x80100tst r10,r11 @判断是否为EINT8、19,r10记录哪个外部中断ldr r0, =EINTPEND ldr r1,[r0] @ldr r1,=0x100str r1,[r0] @清EINTPENDldr r0, =SRCPND ldr r1,[r0] @ldr r1,=0x20str r1,[r0] @清SRCPNDldr r0, =INTPND ldr r1,[r0] @ldr r1,=0x20str r1,[r0] @清INTPNDldmeqfd  r13!,{r0-r3,r12,pc}^mrs     r2,SPSR                      @ copy SPSR_irqmov     r0,r13                       @ copy r13_irqadd     r13,r13,#6*4                 @ reset stack         msr     cpsr_c,#(SVC_MOD|NOINT)      @ change SVC modesub     r13,r13,#FRAME_SIZE-FRAME_R4 @ make stack space stmia   r13,{r4-r11}                 @ save r4-r11ldmia   r0,{r4-r9}                   @ r4-r9 IRQ stack mrs r1, cpsr  bic r1, r1, #I_Bitmsr cpsr_c, r1 @开全局IRQ中断stmdb   r13!,{r4-r7}                 @ save r4-r7 SVCstr     r2,[r13,#FRAME_PSR]          @ save PSRstr     r8,[r13,#FRAME_R12]          @ save r12str     r9,[r13,#FRAME_PC]           @ save pc      str     r14,[r13,#FRAME_LR]          @ save lrldr r11,=0x80000cmp r10,r11bleq irq_server1blne irq_server2ldmia   r13!,{r0-r12,r14}            @ restore contextmsr     SPSR_cxsf,r14                @ restore SPSRldmia   r13!,{r14,pc}^               @ returnfiq:              nop

可以看到中斷的嵌套,但是按下K6多次後會有問題,譬如LED4一直暗,或一直亮,再按那兩個中斷按鍵也沒反應。JLink調試發現按一次按鍵,中斷重入好幾次,大概是沒有去抖動導致,連續按久了,堆棧溢出?同時還會跑到“ldr     pc, _undefined_instruction “這一句上,跑飛了?問題的原因還有待確認!

0 0