1. 异常与中断概念引入
异常主要是指来自CPU内部的意外事件,比如执行了未定义指令、算术溢出、除零运算等发生在CPU内部的意外事件,这些异常的发生,会引起CPU运行相应的异常处理程序;中断一般来自硬件(如片上外设、外部I/O输入等)发生的事件,当这些硬件产生中断信号时,CPU会暂停当前运行的程序,转而去处理相关硬件的中断服务程序。但无论是异常还是中断,都会引起程序执行偏离正常的流程,转而去执行异常/中断的处理函数。
下面对异常和中断的介绍,如果中断信号的产生原因来自CPU内部,则称之为异常;如果中断信号来自CPU外部,则称之为中断。有些场合如果没有明确指出是异常还是中断,就统称为中断。
1.1 为什么需要中断
在网上看到一个非常有意思的例子,这里引用下类似的例子来说明为什么需要中断。当你正在看一部很喜欢的电影时,这个时候你觉得有点口渴了,需要去烧一壶开水,假设水烧开需要10分钟。那么请问你如何知道水烧开了呢?也许你会有这两种选择:
- 每隔一小会你就跑去看一下这壶水有没有被烧开,然后回来接着看电影;
- 你可以等到水壶发出水被烧开的声音才去看一下,这期间你一直在看电影。
第一种情况的处理方式,实际上就是不断的查询水是否被烧开了,如果烧开了就关火,没烧开就接着继续看电影,这种处理方式可能会累死你,而且你也会觉得自己有点笨。写程序描述如下:
while (1)
{
see a film(看电影)
check water boiling(查看水是否烧开)
if (水还没开)
return(继续看电影)
else
关火
}
第二种方式可以看作是烧开水的声音发出了一个信号给你,你接收到这个信号,然后就知道了我该去关火了,也就是说这个信号中断了你看电影的过程,而在这之前你可以一直享受看电影的过程。写程序描述如下:
while (1)
{
see a film(看电影)
}
中断服务程序()
{
关火
}
这个例子类比于CPU的话,CPU也是可以选择这两种方式去处理意外事件的,查询方式或者中断方式。对于查询方式很明显会使得CPU的资源无法得到充分的利用,因为CPU的速度是远远大于外设的速度的,CPU在查询外设的状态时就需要等待外设的响应,使得CPU做了很多无用功。而对于中断方式,当外部事件还没达到就绪状态时(类比就是水还没烧开这件事),CPU可以专心的做其他任务,一旦CPU接收到中断信号时,转而去处理中断请求,CPU处理完毕之后再接着执行原来的任务。
从这个类比的例子可以看出,中断机制使得CPU具有了异步处理能力。有了中断机制之后,CPU可以一直专心的执行它的主任务,不用一直去查询设备的状态。设备本身如果达到了就绪状态,需要CPU去处理的时候,此时设备发出一个中断信号给CPU,通知CPU说:“我要你来处理一下了,赶紧来吧”!CPU收到通知之后,先把主任务暂停一会,然后跳转到相应外设的中断服务函数处理该外设的中断请求,处理完之后CPU再继续回去执行主任务。
1.2 ARM体系如何使用中断
在ARM体系中,使用中断的过程一般有如下步骤:
-
中断初始化
1.1 设置中断源,让某个外设可以产生中断;
1.2 设置中断控制器,使能/屏蔽某个外设的中断通道,设置中断优先级等;
1.3 使能CPU中断总开关
-
CPU在运行正常的程序
-
产生中断,比如用户按下了按键 —> 中断控制器 —> CPU
-
CPU每执行完一条指令都会检查是否有异常/中断产生
-
发现有异常/中断产生,开始处理:
5.1 保存现场
5.2 分辨异常/中断,调用对应的异常/中断处理函数
5.3 恢复现场
2. STM32异常与中断处理流程
2.1 概述
上面