14.1. 异常与中断的基本概念¶
异常是导致处理器脱离正常运行转向执行特殊代码的任何事件,如果不及时进行处理,轻则系统出错,重则会导致系统毁灭性
瘫痪。所以正确地处理异常,避免错误的发生是提高软件鲁棒性(稳定性)非常重要的一环,对于实时系统更是如此。
异常是指任何打断处理器正常执行,并且迫使处理器进入一个由有特权的特殊指令执行的事件。异常通常可以分成两类:同步
异常和异步异常。由内部事件(像处理器指令运行产生的事件)引起的异常称为同步异常,例如造成被零除的算术运算引发一
个异常,又如在某些处理器体系结构中,对于确定的数据尺寸必须从内存的偶数地址进行读和写操作。从一个奇数内存地址的
读或写操作将引起存储器存取一个错误事件并引起一个异常,(称为校准异常)。
异步异常主要是指由于外部异常源产生的异常,是一个由外部硬件装置产生的事件引起的异步异常。同步异常不同于异步异常
的地方是事件的来源,同步异常事件是由于执行某些指令而从处理器内部产生的,而异步异常事件的来源是外部硬件装置。例
如按下设备某个按钮产生的事件。同步异常与异步异常的区别还在于,同步异常触发后,系统必须立刻进行处理而不能够依然
执行原有的程序指令步骤;而异步异常则可以延缓处理甚至是忽略,例如按键中断异常,虽然中断异常触发了,但是系统可以
忽略它继续运行(同样也忽略了相应的按键事件)。
中断,中断属于异步异常。所谓中断是指中央处理器CPU正在处理某件事的时候,外部发生了某一事件,请求CPU迅速处理,CPU
暂时中断当前的工作,转入处理所发生的事件,处理完后,再回到原来被中断的地方,继续原来的工作,这样的过程称为中断。
中断能打断线程的运行,无论该线程具有什么样的优先级,因此中断一般用于处理比较紧急的事件,而且只做简
单处理,例如标记该事件,在使用 RT-Thread系统时,一般建议使用信号量、消息或事件标志组等标志中断的发
生,将这些内核对象发布给处理线程,处理线程再做具体处理。
通过中断机制,在外设不需要CPU介入时,CPU可以执行其它线程,而当外设需要CPU时通过产生中断信号使CPU立即停止当前
线程转而来响应中断请求。这样可以使CPU避免把大量时间耗费在等待、查询外设状态的操作上,因此将大大提高系统实时性
以及执行效率。
此处读者要知道一点,RT-Thread源码中有许多处临界段的地方, 临界段虽然保护了关键代码的执行不被打断,
但也会影响系统的实时,任何使用了操作系统的中断响应都不会比裸机快。比如,某个时候有一个线程在运行中,并且该线程
部分程序将中断屏蔽掉,也就是进入临界段中,这个时候如果有一个紧急的中断事件被触发,这个中断就会被挂起,不能得到
及时响应,必须等到中断开启才可以得到响应,如果屏蔽中断时间超过了紧急中断能够容忍的限度,危害是可想而知的。所以,
操作系统的中断在某些时候会有适当的中断延迟,因此调用中断屏蔽函数进入临界段的时候,也需快进快出。
RT-Thread的中断管理支持:
开/关中断。
恢复中断。
中断使能。
中断屏蔽。
14.1.1. 中断的介绍¶
与中断相关的硬件可以划分为三类:外设、中断控制器、CPU本身。
外设:当外设需要请求CPU时,产生一个中断信号,该信号连接至中断控制器。
中断控制器:中断控制器是CPU众多外设中的一个,它一方面接收其它外设中断信号的输入,另一方面,它会发出中断信号给
CPU。可以通过对中断控制器编程实现对中断源的优先级、触发方式、打开和关闭源等设置操作。在Cortex-M系列控制器中常
用的中断控制器是NVIC(内嵌向量中断控制器Nested
Vectored Interrupt Controller)。
CPU:CPU会响应中断源的请求,中断当前正在执行的线程,转而执行中断处理程序。NVIC最多支持240个中断,每个中断最多
256个优先级。
14.1.2. 和中断相关的名词解释¶
中断号:每个中断请求信号都会有特定的标志,使得计算机能够判断是哪个设备提出的中断请求,这个标志就是中断号。
中断请求:“紧急事件”需向CPU提出申请,要求CPU暂停当前执行的线程,转而处理该“紧急事件”,这一申请过程称为中断请求。
中断优先级:为使系统能够及时响应并处理所有中断,系统根据中断时间的重要性和紧迫程度,将中断源分为若干个级别,称
作中断优先级。
中断处理程序:当外设产生中断请求后,CPU暂停当前的线程,转而响应中断申请,即执行中断处理程序。
中断触发:中断源发出并送给CPU控制信号,将中断触发器置“1”,表明该中断源产生了中断,要求CPU去响应该中断,CPU暂停
当前线程,执行相应的中断处理程序。
中断触发类型:外部中断申请通过一个物理信号发送到NVIC,可以是电平触发或边沿触发。
中断向量:中断服务程序的入口地址。
中断向量表:存储中断向量的存储区,中断向量与中断号对应,中断向量在中断向量表中按照中断号顺序存储。
临界段:代码的临界段也称为临界区,一旦这部分代码开始执行,则不允许任何中断打断。为确保临界段代码的执行不被中断,
在进入临界段之前须关中断,而临界段代码执行完毕后,要立即开中断。RT-Thread支持中断屏蔽和中断使能。