ARM异常与中断处理

发布者:幸福如意最新更新时间:2020-04-23 来源: eefocus关键字:ARM  异常  中断处理 手机看文章 扫描二维码
随时随地手机看文章

中断是ARM处理器提高工作效率的方法之一。


Ⅰ、形象理解中断:

假设有个大房间里面有小房间,婴儿正在睡觉,他的妈妈在外面看书。母亲怎么才能知道小孩醒?


过一会打开一次房门,看婴儿是否睡醒,让后接着看书

一直等到婴儿发出声音以后再过去查看,期间都在读书


查询

while(1)

{

    1 read book(读书)

    2 open door(开门)

    if(睡)

        return(read book)

    else

        照顾小孩

 

}


中断

while(1)

{

    read book

    中断服务程序()//声音中断

    {

        处理照顾小孩

    }

}

两种方式对比:很明显,第一种会累死妈妈滴。


这种是比较形象化的比喻,真正在ARM处理器中是如何处理的呢?


有数据(孩子声音)

保护现场(放下手头工作)

调用中断函数(打开房门查看)

处理数据(照顾孩子)

恢复现场(继续工作)

 

这里存在几个问题:


ARM处理是怎样知道有数据的,谁来告诉它

如何保存正在运行的程序

在哪里调用中断函数

如何恢复程序

 

问题解决:


中断控制器,通过设置中断控制器,监听中断源,例如串口的数据接收中断源

保存寄存器,例如程序返回寄存器,后面通过代码比较好懂

硬件规定异常向量地址,软件设置异常向量表,发生中断时,跳转到处理函数

恢复寄存器


Ⅱ、为了更好、更安全的运行程序,ARM分出了多种工作模式:

用户模式(usr),也称普通模式

系统模式(sys),也称兴奋模式

未定义模式(und),指令不能识别

管理模式(svc)

终止模式(abt)

中断模式

快速中断模式

 

Ⅲ、再论保护现场

在这些模式下都有一堆自己一堆寄存器,进入其他模式之前都会先保存r0到r14的寄存器到栈中,加粗的代表是这个模式下的专属寄存器。

Ⅳ、中断模式与快速中断模式的区别

ARM有irq和fiq中断通道,这两个通道可以通过CPSR寄存器I位和F位设置使能。


当触发irq中断时,如果此时再来一个irq,此时ARM是不会鸟你的。ARM核心就像老板,老板本来在做事,然后来了一个客户,秘书打断它,让客户进去。而此时再来一个客户,要么秘书不断去敲门问,要么客户走人。老板第一个客户没有会见完,不会理你。 


但是有一种情况例外,当ARM处在IRQ模式,这个时候fiq pin来了一个中断信号,fiq pin是什么?快速中断,好比公安局的来查刑事案件,才不管老板是不是在会见客户,直接打断,进入到fiq模式,跳到相应的fiq的异常向量表处去执行代码。那如果当ARM处理FIQ模式,fiq pin又来中断信号,也就是又一批公安来了,那没戏,都是执法人员,你打不断我。如果此时irq pin来了呢?来了也不理,正在办案,还敢来妨碍公务。 


所以得出一个结论: IRQ模式只能被FIQ模式打断,FIQ模式下谁也打不断。


中断概念介绍到此,下面将结合三步骤和前面提到的几个问题做详细编程!!!


Ⅴ、芯片手册

由于中断是没有线连接的,所以略过原理图。


1、程序状态寄存器(PSR)

前面提到CPU可以工作在多种模式,CPU也可以处理中断,这些都是可以在CPSR中设置的。


看一下PSR可以设置CPU哪些东西:


T位为1,表示CPU工作于Thumb指令集(一条指令16位)

F位为1,表示CPU不接收任何FIQ中断请求

I位为1,表示CPU不接收任何IRQ中断请求

中间保留位

V是CPU的计算溢出位

C是CPU的计算进位

Z是CPU的计算0位

N是CPU的计算正位,逻辑运算

可以通过设置低4位让CPU进入不同模式,不过处于用户模式是无法设置这4个位的

为什么有CPSR和SPSR?


SPSR是保存程序状态寄存器,CPSR是当前程序状态寄存器,当发生异常时或者中断时,SPSR会保存CPSR的值。


ARM920t给出异常进入和退出的操作,基本上前面都提到了。


2、中断控制器

上面是CPU的中断处理,但是我们还有很多的外设啊,比如按键中断,这些需要中断控制器来完成。


图为中断的流程:最终进入CPU处理的中断需要经过多个屏蔽寄存器的筛选,这些寄存器就是“小秘书”

3、中断向量表

按键中断后,中断处理函数如何调用(中断向量表)

4、外设中断

这里以按键为例子:按键接在GPF0处,只要配置GPF0为中断引脚

除此之外,按键还要配置上升沿触发还是下降沿触发

设置完成后要使能中断吧,对应中断使能即可,这是中断第一屏蔽关

Ⅵ、中断编程

这里以按键中断作为例子,按键触发中断,点亮LED灯。


前面提到了这么多,编程是否有关呢?


答案是确定的,可以想象一下中断的过程:


按键触发中断(中断引脚)

经过屏蔽寄存器(不屏蔽)

进入模式选择(快中断、普通中断)

CPU总中断

 


编程需要解决的问题:


按键中断后,中断处理函数如何调用(中断向量表)

如何得知是对应按键触发中断的(中断源寄存器)

中断之后在哪里保存现场,又是如何恢复现场(保存寄存器)

 


设置中断向量表

这些地址都是硬件规定的,编程只需要在对应位置上放上跳转指令即可


_start:

b reset          /* vector 0 : reset */

ldr pc, und_addr /* vector 4 : und */

ldr pc, swi_addr /* vector 8 : swi */

b halt /* vector 0x0c : prefetch aboot */

b halt /* vector 0x10 : data abort */

b halt /* vector 0x14 : reserved */

ldr pc, irq_addr /* vector 0x18 : irq */

b halt /* vector 0x1c : fiq */

 

 und_addr:

.word do_und

 

swi_addr:

.word do_swi

 

irq_addr:

.word do_irq

设置按键中断源、中断控制器屏蔽中断源

/* 配置GPIO为中断引脚 */

GPFCON &= ~((3<<0) | (3<<4));

GPFCON |= ((2<<0) | (2<<4));   /* S2,S3被配置为中断引脚 */

 

GPGCON &= ~((3<<6) | (3<<22));

GPGCON |= ((2<<6) | (2<<22));   /* S4,S5被配置为中断引脚 */

 

/* 设置中断触发方式: 双边沿触发 */

EXTINT0 |= (7<<0) | (7<<8);     /* S2,S3 */

EXTINT1 |= (7<<12);             /* S4 */

EXTINT2 |= (7<<12);             /* S5 */

 

/* 设置EINTMASK使能eint11,19 */

EINTMASK &= ~((1<<11) | (1<<19));

 

    INTMSK &= ~((1<<0) | (1<<2) | (1<<5));

保护现场,恢复现场

do_irq:

/* 执行到这里之前:

* 1. lr_irq保存有被中断模式中的下一条即将执行的指令的地址

* 2. SPSR_irq保存有被中断模式的CPSR

* 3. CPSR中的M4-M0被设置为10010, 进入到irq模式

* 4. 跳到0x18的地方执行程序 

*/

 

/* sp_irq未设置, 先设置它 */

ldr sp, =0x33d00000

 

/* 保存现场 */

/* 在irq异常处理函数中有可能会修改r0-r12, 所以先保存 */

/* lr-4是异常处理完后的返回地址, 也要保存 */

sub lr, lr, #4

stmdb sp!, {r0-r12, lr}  

/* 处理irq异常 */

bl handle_irq_c

/* 恢复现场 */

ldmia sp!, {r0-r12, pc}^  /* ^会把spsr_irq的值恢复到cpsr里 */

中断处理函数

void handle_irq_c(void)

{

/* 分辨中断源 */

int bit = INTOFFSET;

 

/* 调用对应的处理函数 */

if (bit == 0 || bit == 2 || bit == 5)  /* eint0,2,eint8_23 */

{

key_eint_irq(bit); /* 处理中断, 清中断源EINTPEND */

}

 

/* 清中断 : 从源头开始清 */

SRCPND = (1< INTPND = (1<}

void key_eint_irq(int irq)

{

unsigned int val = EINTPEND;

unsigned int val1 = GPFDAT;

unsigned int val2 = GPGDAT;

if (irq == 0) /* eint0 : s2 控制 D12 */

{

if (val1 & (1<<0)) /* s2 --> gpf6 */

{

/* 松开 */

GPFDAT |= (1<<6);

}

else

{

/* 按下 */

GPFDAT &= ~(1<<6);

}

}

else if (irq == 2) /* eint2 : s3 控制 D11 */

{

if (val1 & (1<<2)) /* s3 --> gpf5 */

{

/* 松开 */

GPFDAT |= (1<<5);

}

else

{

/* 按下 */

GPFDAT &= ~(1<<5);

}

}

else if (irq == 5) /* eint8_23, eint11--s4 控制 D10, eint19---s5 控制所有LED */

{

if (val & (1<<11)) /* eint11 */

{

if (val2 & (1<<3)) /* s4 --> gpf4 */

{

/* 松开 */

GPFDAT |= (1<<4);

}

else

{

/* 按下 */

GPFDAT &= ~(1<<4);

}

}

else if (val & (1<<19)) /* eint19 */

{

if (val2 & (1<<11))

{

/* 松开 */

/* 熄灭所有LED */

GPFDAT |= ((1<<4) | (1<<5) | (1<<6));

}

else

{

/* 按下: 点亮所有LED */

GPFDAT &= ~((1<<4) | (1<<5) | (1<<6));

}

}

}

 

EINTPEND = val;

}

关键字:ARM  异常  中断处理 引用地址:ARM异常与中断处理

上一篇:ARM 处理器 ~ 中断与异常
下一篇:ARM9 mini2451裸机学习——NAND flash驱动学习 2

小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved