ARM汇编嵌套中断处理
参考书籍:《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 nestedInterruptHandlerMaskmdEQU 0x1f;
processor mode mask
SVC32mdEQU 0x13;
SVC mode
I_BitEQU 0x80;
IRQ bit FRAME_R0EQU 0x00
FRAME_R1EQU FRAME_R0+4
FRAME_R2EQU FRAME_R1+4
FRAME_R3EQU FRAME_R2+4
FRAME_R4EQU FRAME_R3+4
FRAME_R5EQU FRAME_R4+4
FRAME_R6EQU FRAME_R5+4
FRAME_R7EQU FRAME_R6+4
FRAME_R8EQU FRAME_R7+4
FRAME_R9EQU FRAME_R8+4
FRAME_R10EQU FRAME_R9+4
FRAME_R11EQU FRAME_R10+4
FRAME_R12EQU FRAME_R11+4
FRAME_PSREQU FRAME_R12+4
FRAME_LREQU FRAME_PSR+4
FRAME_PCEQU FRAME_LR+4
FRAME_SIZE EQU FRAME_PC+4 AREA nih9_9,CODE,readonly
nestedInterruptHandler ;
instructionstate : comment
SUBr14,r14,#4;
2 :
STMDBr13!,{r0-r3,r12,r14};
2 : save context
;
BLread_RescheduleFlag;
3 : more processing
CMPr0,#0;
3 : if processing?
LDMNEIA r13!,{r0-r3,r12,pc}^;
4 :then return
MRSr2,SPSR;
5 : copy SPSR_irq
MOVr0,r13;
5 : copy r13_irq
ADDr13,r13,#6*4;
5 : reset stack
MRSr1,CPSR;
6 : copy CPSR
BICr1,r1,#Maskmd;
6 :
ORRr1,r1,#SVC32md;
6 :
MSRCPSR_c,r1;
6 : change SVC mode
SUBr13,r13,#FRAME_SIZE-FRAME_R4 ;
7 : make stack space
STMIAr13,{r4-r11};
7 : save r4-r11
LDMIAr0,{r4-r9};
7 : r4-r9 IRQ stack
BICr1,r1,#I_Bit;
8 :
MSRCPSR_c,r1;
8 : enable int
STMDBr13!,{r4-r7};
9 : save r4-r7 SVC
STRr2,[r13,#FRAME_PSR];
9 : save PSR
STRr8,[r13,#FRAME_R12];
9 : save r12
STRr9,[r13,#FRAME_PC];
9 : save pc
STRr14,[r13,#FRAME_LR];
9 : save lr
;
LDMIAr13!,{r0-r12,r14};
11 : restore context
MSRSPSR_cxsf,r14;
11 : restore SPSR
LDMIAr13!,{r14,pc}^;
11 : returnread_RescheduleFlag
;
MOVr0,#0;
more processing
MOVpc,r14;
returnEND
将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.
.equNOINT,0xc0
.equI_Bit,0x80
.equSVC_MOD,0x13
.equIRQ_MOD,0x12.equWTCON,0x53000000.equGPBCON,0x56000010
.equGPBDAT,0x56000014
.equGPBUP,0x56000018.equGPGCON,0x56000060.equEINTMASK, 0x560000a4
.equEXTINT1,0x5600008c
.equEXTINT2,0x56000090
.equEINTPEND, 0x560000a8.equINTMSK,0x4A000008.equSRCPND,0X4A000000
.equINTPND,0X4A000010.equSVC_Stack, 4096
.equIRQ_Stack, 2048@栈帧定义
.equFRAME_R0,0x00
.equFRAME_R1,FRAME_R0+4
.equFRAME_R2,FRAME_R1+4
.equFRAME_R3,FRAME_R2+4
.equFRAME_R4,FRAME_R3+4
.equFRAME_R5,FRAME_R4+4
.equFRAME_R6,FRAME_R5+4
.equFRAME_R7,FRAME_R6+4
.equFRAME_R8,FRAME_R7+4
.equFRAME_R9,FRAME_R8+4
.equFRAME_R10,FRAME_R9+4
.equFRAME_R11,FRAME_R10+4
.equFRAME_R12,FRAME_R11+4
.equFRAME_PSR,FRAME_R12+4
.equFRAME_LR,FRAME_PSR+4
.equFRAME_PC,FRAME_LR+4
.equFRAME_SIZE,FRAME_PC+4.text
.code 32
.global _start
_start:
b reset
ldrpc, _undefined_instruction
ldrpc, _software_interrupt
ldrpc, _prefetch_abort
ldr pc, _data_abort
ldrpc, _not_used
ldrpc, _irq
ldrpc, _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,0xdeadbeef
reset:
ldr r0,=WTCON
mov r1,#0x0
str r1,[r0] @关看门狗 msr cpsr_c,#(IRQ_MOD|NOINT)
ldr sp,=IRQ_Stackmsr cpsr_c,#(SVC_MOD|NOINT)
ldr sp,=SVC_Stack ldr r0,=GPBCON
ldr r1,=0x14000
str r1,[r0] @PB8,7输出 ldr r0,=GPBDAT
mov r1,#0x180
str r1,[r0] @8、7高电平ldr r0,=GPGCON
ldr r1,=0x800002
str r1,[r0] @使能外部中断8,外部中断19 ldr r0,=EXTINT1
mov r1,#0x03
str r1,[r0] @外部8下降沿触发 ldr r0,=EXTINT2
ldr r1,=0x3000
str r1,[r0] @外部19下降沿触发 ldr r0, =EINTPEND
ldr r1,=0x00fffff0
str r1,[r0]@ 清EINTPEND,写1清零
ldr r0,=EINTMASK
ldr r1,=0xfff7feff
str r1,[r0] @使能外部中断8、19,0为使能 ldr r0, =SRCPND
ldr r1,=0xffffffff
str r1,[r0]@ 清SRCPND,写1清零 ldr r0, =INTPND
ldr r1,=0xffffffff
str r1,[r0]@ 清INTPND,写1清零 ldr r0,=INTMSK
ldr r1,=0xffffffdf
str r1,[r0] @使能外部中断EINT8-23 mrs r1, cpsr
bic r1, r1, #I_Bit
msr cpsr_c, r1 @开全局IRQ中断loop: b loopirq_server1:
stmfdsp!,{lr}ldr r0,=GPBDAT
ldr r1,[r0]
bic r2,r1,#0x100
str r2,[r0]
bl delay1
orr r2,r1,#0x100
str r2,[r0]
@bl delay1 ldmfdsp!,{lr}
mov pc,lrirq_server2:
stmfdsp!,{lr}ldr r0,=GPBDAT
ldr r1,[r0]
bic r2,r1,#0x80
str r2,[r0]
bl delay2
orr r2,r1,#0x80
str r2,[r0]
@bl delay2 ldmfdsp!,{lr}
mov pc,lrdelay1:
ldr r12,=0x5ffffff
delay1loop:
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:
subr14,r14,#4
stmdbr13!,{r0-r3,r12,r14}@ save context ldr r0, =EINTPEND
ldr r10,[r0]
ldr r11,=0x80100
tst r10,r11 @判断是否为EINT8、19,r10记录哪个外部中断 ldr r0, =EINTPEND
ldr r1,[r0] @ldr r1,=0x100
str r1,[r0] @清EINTPEND ldr r0, =SRCPND
ldr r1,[r0] @ldr r1,=0x20
str r1,[r0] @清SRCPND ldr r0, =INTPND
ldr r1,[r0] @ldr r1,=0x20
str r1,[r0] @清INTPND ldmeqfdr13!,{r0-r3,r12,pc}^ mrsr2,SPSR@ copy SPSR_irq
movr0,r13@ copy r13_irq
addr13,r13,#6*4@ reset stack
msrcpsr_c,#(SVC_MOD|NOINT)@ change SVC mode
subr13,r13,#FRAME_SIZE-FRAME_R4 @ make stack space
stmiar13,{r4-r11}@ save r4-r11
ldmiar0,{r4-r9}@ r4-r9 IRQ stack
mrs r1, cpsr
bic r1, r1, #I_Bit
msr cpsr_c, r1 @开全局IRQ中断
stmdbr13!,{r4-r7}@ save r4-r7 SVC
strr2,[r13,#FRAME_PSR]@ save PSR
strr8,[r13,#FRAME_R12]@ save r12
strr9,[r13,#FRAME_PC]@ save pc
strr14,[r13,#FRAME_LR]@ save lr
ldr r11,=0x80000
cmp r10,r11
bleq irq_server1
blne irq_server2 ldmiar13!,{r0-r12,r14}@ restore context
msrSPSR_cxsf,r14@ restore SPSR
ldmiar13!,{r14,pc}^@ return
fiq:
nop
可以看到中斷的嵌套,但是按下K6多次後會有問題,譬如LED4一直暗,或一直亮,再按那兩個中斷按鍵也沒反應。JLink調試發現按一次按鍵,中斷重入好幾次,大概是沒有去抖動導致,連續按久了,堆棧溢出?同時還會跑到“ldrpc, _undefined_instruction “這一句上,跑飛了?問題的原因還有待確認!
【ARM汇编嵌套中断处理】
推荐阅读
- mybatisplus|mybatisplus where QueryWrapper加括号嵌套查询方式
- 有一种爱叫那一滴眼泪
- Improve|Improve Nested Conditionals(优化嵌套的条件语句) 面对大量的if-else语句
- Python|Win10下 Python开发环境搭建(PyCharm + Anaconda) && 环境变量配置 && 常用工具安装配置
- 单片机|Arduino、arm、树莓派、单片机四者有什么不同()
- 03_ARMv8指令集介绍加载与存储指令
- 集合框架(集合嵌套存储和遍历元素的案例代码实现)
- 汇编实验(格雷码转二进制(ASCII码)的实现和调试)
- markdown中使用iframe|markdown中使用iframe 嵌套网页
- 儿童学编程语言swift语言|儿童学编程语言swift语言 playgrounds12 嵌套模式