最近在study ARM,在网上看到一些先行者们总结出来的一些东西,觉得很有参考意义,特收藏起来便于日后查找学习(在此向原帖作者致敬)。
中断
ARM体系的CPU有7种工作模式,可以通过软件来进行模式切换,或者发生各类中断、异常进行相应模式。
CPU可以识别两种类型中断,正常中断(IRQ)和快速响应中断(FIQ)状态寄存器的PSR中F和R位决定是中断的启闭。为了使能中断,必须将PSR中F或R位清零,并且中断屏蔽寄存器相应位也要清零。
ARM中断分为子中断源和一般中断源,子中断源多了两个寄存器SUBRCPN(标识子中断源是否发生)INTSUBMSK(屏蔽子中断源)
ARM中断发生过程:
如为子中断源,则SUBSRCPND寄存器相应位置1,然后根据子中断源屏蔽寄存器(INTSUBMSK)的设置来判断该中断是否被屏蔽,如未屏蔽,则在SRCPND寄存器相应位置1。
如为非子中断则直接在SRCPND寄存器相应位置1。
如果INTMOD寄存器中该中断被设置为FIQ快速中断(相应位置1),即该中断立即执行。如不是,则判断INTMSK寄存器中该中断是否被屏蔽,如未屏蔽,则进入中断优先仲裁器进行中断优先设置(PRIORITY寄存器)
经过中断优先仲裁后,最高优先级的中断在INTPND寄存器中相应位置1(同一时间,此寄存器只有一位置1),INTOFFSET寄存器值用来表示INTPND寄存器置1位(即INTPND寄存器中位[x]为1时,INTOFFSET寄存器值为x,可以用它确定是什么中断。
中断设置
从上图我们可以看出,要启用一个中断,我们主要设置以下寄存器:
1、 INTMOD设置是否为快速中断(一个系统中只能有一个快速中断,默认没有快速中断,如不使用,可以不用设置)
2、 INTMSK设置该中断是否被屏蔽
3、 PRIORITY设置该中断的优先级
如为子中断源,还需设置
4、INTSUBMSK设置子中断源是否被屏蔽
如果外接中断,还需设置以下寄存器:
5、 GPXCON设置相应引脚为中断输入
6、 EINTMASK设置外部中断输入使能
7、 EXTINT0-EXTINT2设置外部引脚输入中断电平信号类型
其中,为外部中断输入时,EINTPEND寄存器用于保存是否有中断发生。EINTMASK 、EINTPEND寄存器[3-0]位保留取值为0
中断信号清除
清除中断时在EINTPEND、 INTPND、SUBSRCPND及SRCPND寄存器该位写入1令此位为0,写入0效果。其清除过程为EINTPEND、SUBSRCPND、SRCPND 、INTPND,否则,将导致无限次中断。
中断向量及处理程序
当IRQ中断发生时,CPU自动切换到中断模式,并将返回地址、CPSR寄存器保存到中断模式下的对应寄存器中,并跳转到Ox00000018处执行,在该地址处一般安排一条跳转指令B XXX(32M范围)或ldr pc,xxx(4G范围)指令,需要注意的事,在此处不能用BL指令,这是因为该指令将引起LR寄存器的变化,导致中断结束后不能跳回原程序。在中断程序中,一般先计算返回地址和保存相关寄存器.
中断向量:
b Start
nop
nop
nop
nop
nop
b IRQ_Handle ;中断处理程序
nop
Start
ldr r0,=WTCON ;watch dog disable
ldr r1,=0x0
str r1,[r0]
中断处理程序
IRQ_Handle
sub lr,lr,#4 ;计算返回地址
stmfd sp!,{r0-r12,lr}
bl xxx ;调用中断处理程序
ldmfd sp!,{r0-r12,pc}^ ;恢复程序环境,并返回CPSR寄存器的值
1、 中断检测程序
硬件说明:K1(EINT1)接GPF1 K2(EINT4)接GPF4 K3(EINT2)接GPF2
K4(EINT0)接GPF0
GPFCON每两位控制一个端口,其中00为输入端,01为输出端,取值
11保留,10为中断输入
软件说明:GPF0-GPF2、GPF4设置为中断输入端0b1000101010=0x22a
主要程序说明:
1、设置中断相关寄存器
ldr r0,=GPFCON ;设置GPF0-GPF2\GPF4为中断输入
ldr r1,=0x22a
str r1,[r0]
ldr r0,=GPFUP
ldr r1,=0xff
str r1,[r0]
ldr r0,=EINTMASK ;使GPF0-GPF2\GPF4为中断输入有效
ldr r1,=0xffffffef
str r1,[r0]
ldr r0,=EXTINT0 ;设置中断电平信号类型
ldr r1,=0x2022
str r1,[r0]
ldr r0,=PRIORITY ;确定优先级
ldr r1,=0x7e
str r1,[r0]
ldr r0,=INTMSK ;开启中断
ldr r1,=0xffffffe8
str r1,[r0]
此时中断尚未开启,我们需用指令msr cpsr_c,#0x5f 清除CPSR寄存器I位,开启中断,使中断使能
2、 清除中断
ldr r0,=EINTPEND
cmp r1,#4
streq r3,[r0]
ldr r0,=SRCPND
str r3,[r0]
ldr r0,=INTPND
str r3,[r0]
因为EINTPEND寄存器[0-3]保留为0,故当EINT4发生时,才需要清除EINTPEND寄存器。注意寄存器清除顺序不能错。
文章评论(0条评论)
登录后参与讨论