|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
异常是能够引起程序流偏离正常流程的事件,当异常发生时,正在执行的程序就会被挂起,处理器转而执行一块与该事件相关的代码(异常处理)。事件可以是外部输入,也可以是内部产生的,外部产生的事件通常被称作中断或中断请求(IRQ)。几乎所有的现代处理器都支持异常和中断,微控制器的中断可以由片上外设或软件产生。由此可见,通常我们处理的中断是异常的一种。5 k, _9 o2 T4 ~, J. H
- E6 Y$ w/ P: M
每种异常类型都有对应的优先级,有些异常的优先级是固定的,有些是可编程的。
: o" N9 c4 |# p% J# c$ Q5 n
7 M1 ~' f8 B( r- U7 } W' n7 K先说几个概念:. J$ g, Z# P( a: N6 a& j
`) T4 \7 K2 s7 i$ j& M9 g1、不可屏蔽中断(NMI)% X( H' I3 ~1 ^& |# ~+ H4 J \
NMI同IRQ类似,只是它不能被禁止,并且优先级仅次于复位,它对于工业控制和汽车之类的高可靠性系统非常有用。根据微控制器设计的不同,NMI可以用于掉电处理,也可以连接到看门狗单元,以便在系统停止响应时将系统复位。由于NMI不能被控制寄存器禁止,其响应的及时性就得到了保证。9 a9 N. G; q& X. ~& |8 j
+ V' |. w' P- } V6 ^
2、硬件错误. i: y* b, Y1 l" E s. T
硬件错误异常用于处理程序执行时产生的错误,这些错误可以是试图执行未知的操作码、总线接口或存储器系统的错误,也可以是试图切换至ARM状态之类的非法操作。
4 {+ J4 o N9 s
( D& l. {3 }7 u: ]' p3、SVC(请求管理调用)
- c, f0 K$ m* p2 Z8 F9 ^SVC指令执行时就会产生SVC异常,其通常用在具有操作系统的系统中,为应用程序提供了访问系统服务的入口。
0 a, t7 ` I7 g4 M: ]- O" p& z4 H+ Y+ m f @6 I: ~
4、PendSV(可挂起的系统调用)/ i$ n; v) i3 n9 b! b X% c, q7 r2 B
PendSV是用于带OS(操作系统)的应用程序的另外一个异常,SVC异常在SVC指令执行后会马上开始,PendSV在这点上有所不同,它可以延迟执行,在OS上使用PendSV就要确保高优先级任务完成后才执行系统调度。
8 y: i. q4 K. ~: z, m, V. W5 }% K
2 U5 ?/ \# ?8 G9 R. {) A5、系统节拍
) ?4 ~, o6 q' C1 FNVIC中的Systick定时器为OS应用可以利用的另外一个特性。几乎所有操作系统的运行都需要上下文切换,而这一过程通常需要依靠定时器产生定时中断来完成。
% h# T2 J- o0 E& [( t( C K# D% p% u: p' ?1 O8 v1 C+ c
6、中断
1 Z1 b4 n7 C; J% d! g中断信号可以连接到片上外设,也可以通过IO端口连接到外部中断源上。外部中断只有在使能后才能使用,如果中断被禁止了,或者处理器正在运行另外一个相同或更高优先级的异常处理,则该中断请求会被存储在挂起状态寄存器中。当高优先级的中断处理完成或返回后,挂起的中断请求才可以执行。NVIC能够接受的中断请求信号可以是高逻辑电平,也可以是中断脉冲。应该注意的是,在微控制器的外部接口中,外部中断信号可以是高电平也可以是低电平,或者可以通过编程配置。
Z+ b0 k3 s; ^
- c, l' e) q" Z; r$ D异常的处理流程:
( b" Q2 K3 h! C+ G) [+ v
) ?& i1 m: g1 v; m- n* i' V# f1、接受异常请求4 ^ b, E0 e0 F( w) J
处理器要接受一个异常,需要满足的条件:# M. _1 x* E9 w
①对于中断和SysTick中断请求,中断必须使能
5 T4 g1 K4 I6 h0 K l1 V' K- j②处理器正在执行的异常处理的优先级不能相同或更大/ s8 ]- e8 i* C" T6 c/ L5 I
③中断屏蔽寄存器没有屏蔽掉异常: _0 d) ?# H' |" o
特别注意一点:对于SVC异常,如果用到SVC指令的异常处理的优先级与SVC异常本身相同或更大,这种情况就会引起硬件错误异常处理的执行。
( Y; b3 Q/ j( ^7 ?* y/ n* L i7 Y3 }
2、压栈和出栈
0 O% F3 a$ u- h6 A9 a1 @ [/ o0 j; O% _为了使被中断的程序能正确继续执行,在程序切换至异常处理前,处理器当前状态的一部分应该被保存。不同架构处理器的处理方法不同,有的采用硬件自动处理的方法来备份和恢复处理器状态,看需求,有的是需要程序中增加软件处理过程。% n7 m8 S2 ~7 X5 q
5 V% x: P8 d' f4 Y异常处理过程执行到最后时,将会利用执行特殊值来触发异常返回机制。处理器还会查看当前是否还有其他异常需要处理,如果没有,处理器就会恢复之前存储在栈空间的寄存器值,并继续执行中断前的程序。1 z' \0 q8 s4 x' }+ B
0 e7 g7 B! r) s
自动保存和恢复寄存器内容的操作被称为“压栈”和“出栈”,这种机制使得异常处理可以跟普通的C函数一样处理,同时也减小了软件开销以及回路大小,因此也降低了系统的功耗。
6 i' A1 I1 X* J# |% s( J' E
3 o- @- B1 o; [9 a- s3 H! O3、异常返回指令* i/ o% G' v( {8 w( J. i
根据处理器的不同中断处理返回有的需要特殊指令,一般都是普通的返回指令,加载到PC中的数值则会触发异常返回,这样就使得异常处理可以和普通的C函数一样使用。' V) W1 C; F1 i0 \( w/ g
两个不同的指令可以用于异常返回:. { p, }: ]# u) E* J! g
BX <Reg>q ;将寄存器中的值加载到PC中+ `" @6 A2 }8 a9 F* s
或% o3 B# l* ^# I& C& h) |
POP {<Reg1>,<Reg1>,...,PC} OP指令,PC也是更新的寄存器之一
4 t& d& \& E, `, Y' Q: A当其中一个指令执行,异常返回机制就会启动。: H/ G3 m9 w$ q& P5 ~
8 |8 G7 C8 I) j7 O% `9 d4、末尾连锁0 X! j3 i5 w+ i" p3 M
如果当其他的异常处理完成后,还有异常处于挂起状态,这时处理器不会返回到中断前的程序,而是重新进入异常处理流程,这也被称作末尾连锁。当末尾连锁发生时,处理器不必马上恢复栈的值,因为如果这么做的话还得重新压栈。异常的末尾连锁降低了异常处理的开销,因此也提高了能耗效率。
; E- e+ G( d$ ?! [* g# Z; r) A3 p: y* ]0 q- Q, X! {, t3 u1 z( z
- _* M9 v3 _7 l2 g
|
|