购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.5 Cortex-M0+处理器的异常及处理

异常(Exception)是事件,它将使程序流退出当前的程序线程,然后执行和该事件相关的代码片段(子程序)。通过软件代码,可以使能或者禁止处理器核对异常事件的响应。事件可以是内部的也可以是外部的,如果事件来自外部,则称为中断请求(Interrupt Request,IRQ)。

本节介绍Cortex-M0+处理器异常所处的状态、异常类型、异常优先级、向量表等。

2.5.1 异常所处的状态

每个异常均处于以下状态之一。

(1)非活动(Inactive)。当异常处于该状态时,它既不活动也不挂起。

(2)挂起(Pending)。当异常处于该状态时,表示它在等待处理器为其提供服务。一个来自外设或软件的中断请求可以将相应中断的状态改为挂起。

(3)活动(Active)。处理器正在处理异常但尚未完成。异常句柄可以中断另一个异常的执行。在这种情况下,两个异常均处于活动状态。

注: 异常句柄是指在异常模式中,所执行的一段代码,也称为异常服务程序。如果异常是由IRQ引起的,则将其称为中断句柄(Interrupt Handler)/中断服务程序(Interrupt Service Route,ISR)。

(4)活动和挂起。处理器正在处理异常,并且同一来源还有一个挂起的异常。

2.5.2 异常类型

在Cortex-M0+处理器中,提供了不同的异常类型,以满足不同应用的需求,包括复位、不可屏蔽中断、硬件故障、请求管理调用、可挂起的系统调用、系统滴答和外部中断。

1.复位

Armv6-M框架支持两级复位。复位包括:

(1)上电复位用于复位处理器、SCS和调试逻辑;

(2)本地复位用于复位处理器和SCS,不包括与调试相关的资源。

2.不可屏蔽中断

不可屏蔽中断(Non-Maskable Interrupt,NMI)特点如下:

(1)用户不可屏蔽NMI;

(2)它用于对安全性苛刻的系统中,如工业控制或汽车;

(3)它可以用于电源失败或看门狗。

对STM32G0来说,NMI是由SRAM奇偶校验错误、Flash存储器双ECC错误或时钟故障引起的。

3.硬件故障

硬件故障(HardFault)常用于处理程序执行时产生的错误,这些错误可以是试图执行未知的操作码、总线接口或存储器系统的错误,也可以是尝试切换到Arm状态之类的非法操作。

4.请求管理调用

请求管理调用(SuperVisor Call,SVC)是由SVC指令触发的异常。在操作系统环境中,应用程序可以使用SVC指令来访问操作系统内核功能和设备驱动程序。

5.可挂起的系统调用

可挂起的系统调用(PendSV)是用于包含操作系统的应用程序的另一个异常,SVC异常在SVC指令执行后会马上开始,PendSV在这点上有所不同,它可以延迟执行,在操作系统上使用PendSV可以确保高优先级任务完成后再执行系统调用。

6.系统滴答(SysTick)

NVIC中的SysTick定时器为操作系统可以使用的另一个特性。几乎所有操作系统的运行都需要上下文(现场)切换,而这一过程通常需要依靠定时器来完成。Cortex-M0+处理器内集成了一个简单的定时器,这样使得操作系统的移植更加容易。

7.外部中断

Cortex-M0+处理器中的NVIC,支持最多32个中断请求(IRQ)。由于STM32G0提供了SYSCFG模块,使得STM32G0可以响应中断事件的数量大于32个,这是因为SYSCFG模块可以将几个中断组合到一个中断线上。通过读取SYSCFG模块中的ITLINEx寄存器,就可以快速确定产生中断请求的外设源了。

只有用户使能外部中断后,才能使用它。如果禁止了外部中断,或者处理器正在运行另一个相同或更高优先级的异常处理,则中断请求会被保存在挂起状态寄存器中。当处理完高优先级的中断或返回后,才能执行挂起的中断请求。对NVIC来说,可接受的中断请求信号可以是高逻辑电平,也可以是中断脉冲(最少为一个时钟周期)。

注: (1)在MCU外部接口中,外部中断信号可以是高电平也可以是低电平,或者可以通过编程配置。

(2)软件可以修改外部中断的优先级,但是不能修改复位、NMI和硬件故障的优先级。

2.5.3 异常优先级

在Cortex-M0+处理器中,每个异常都有相关联的优先级,其中:

(1)较低的优先级值意味着具有较高的优先级;

(2)除了复位、硬件故障和NMI外,软件可配置其他所有异常的优先级。

如果软件没有配置任何优先级,则所有可配置优先级异常的优先级为0。

注: 可配置优先级的值在0~192的范围内,以64为步长。具有固定负优先级值的复位、硬件故障和NMI异常始终有比其他任何异常更高的优先级。复位的优先级值为-3,NMI的优先级值为-2,硬件故障的优先级值为-1,除此之外的其他异常(包括外设中断和软件异常)的优先级为0~3。

为IRQ[0]分配较高的优先级值,为IRQ[1]分配较低的优先级值,则意味着IRQ[1]的优先级高于IRQ[0]。如果IRQ[1]和IRQ[0]均有效,则先处理IRQ[1],处理完毕后再处理IRQ[0]。

如果多个挂起的异常具有相同的优先级,则优先处理具有最低优先级编号的异常。例如,如果IRQ[0]和IRQ[1]都处于挂起状态并具有相同的优先级,则先处理IRQ[0]。

当处理器执行一个异常句柄时,如果发生了具有更高优先级的异常,则会抢占该异常句柄。如果又发生与正在处理的异常具有相同优先级的异常,则不会抢占当前正在处理的句柄。然而,新中断的状态变为挂起。

2.5.4 向量表

向量表包含用于所有异常句柄的堆栈指针和起始地址(也称为异常向量)。向量表中异常向量的顺序如图2.22所示。每个向量的最低有效位必须为1,用来指示异常句柄是用Thumb代码编写的。

图2.22 向量表中异常向量的顺序

系统复位时,向量表固定在地址0x00000000。具有特权级的软件可以写入向量表偏移寄存器(Vector Table Offset Register,VTOR),以根据向量表的大小和TBLOFF设置的粒度,将向量表的起始地址重新定位到其他存储器位置。

注: 为了简化软件层的应用程序设计,Cortex微控制器软件接口标准(Cortex Microcontroller Software Interface Standard,CMSIS)只使用IRQ号。它对中断以外的其他异常使用负值。IPSR返回异常号。

2.5.5 异常的进入和返回

在描述异常的处理时,会用到下面的术语。

(1)抢占(preemption)。

如图2.23所示,当处理器正在处理一个中断,一个具有更高优先级的新请求到达时,新的异常可以抢占当前的中断,称之为嵌套的异常处理。

图2.23 抢占和中断嵌套

注: 图中的保存上下文就是通常所说的保存现场,也就是说,在处理器进入异常句柄之前,先将进入异常句柄之前处理器的状态保存起来,处理器的状态包括寄存器以及状态标志等,称之为上文。此外,处理器还得知道在处理完中断句柄后该如何继续执行原来的程序,称之为下文。只有处理器能正确地保存上下文的信息,才能在其进入异常句柄后,正确地从异常句柄返回。应该说术语“上下文”比“现场”更能反映处理器处理异常的机制。

在处理完较高优先级的异常后,先前被打断的异常句柄将恢复继续执行。

Cortex-M0+处理器内的微指令控制序列会自动地将上下文保存到当前堆栈,并在中断返回时将其恢复。

(2)返回(return)。

当完成处理异常句柄时,会发生返回这种情况,并且:

①没有正在挂起需要待处理的具有足够优先级的异常;

②已完成的异常句柄未处理迟到的异常。

处理器弹出堆栈,并且将处理器的状态恢复到发生中断之前的状态。

(3)尾链(tail-chaining)。

如图2.24所示,这种机制加快了异常处理的速度。在处理完一个异常句柄后,如果一个挂起的异常满足进入异常的要求,则跳过弹出堆栈的过程,并将控制权转移到新的异常句柄。

图2.24 尾链机制

因此,将具有较低优先级(较高优先级值)的背靠背中断连接在一起,这样在处理异常句柄时,就能显著减少处理延迟并降低器件功耗。

(4)迟到(late-arriving)。

如图2.25所示,这种机制可加快抢占速度。如果在保存当前异常的状态期间又发生了较高优先级的异常,则处理器将切换未处理较高优先级的异常,并为该异常启动向量获取。由于状态保存不受延迟到达的影响,因此对于两种异常状态,保存的状态都相同。从迟到异常的异常句柄返回时,将应用常规的尾链规则。

图2.25 迟到机制

1.异常进入

当存在具有足够优先级的挂起异常时,将发生进入异常,并且:

(1)处理器处于线程模式;

(2)新异常的优先级要高于正在被处理的异常,在这种情况下,新异常抢占正在被处理的异常。

当一个异常抢占另一个异常时,将嵌套异常。当处理采纳(处理)一个异常时,除非异常是尾链或迟到的异常,处理器将信息压入当前的堆栈。该操作称为压栈(入栈)。8个数据字的结构称为堆栈帧,堆栈帧如图2.26所示。

图2.26 堆栈帧

在压栈之后,堆栈指针指向堆栈中的最低地址。堆栈帧与双字地址对齐。堆栈帧包含返回地址。这是被中断打断的当前正在执行程序的下一条地址。当从异常返回时,将该值恢复到PC,这样可以继续执行被打断的程序。

处理器提取向量,从向量表中读取异常句柄的起始地址。当完成压栈后,处理器开始执行异常句柄。同时处理器将EXC_RETURN值写入LR。这指示哪个堆栈指针对应于堆栈帧,以及处理器在进入异常之前所处的模式。

如果处理器在进入异常期间没有发生更高优先级的异常,则处理器开始执行异常句柄,并自动将当前挂起的中断状态修改为活动。

如果处理器在进入异常期间发生了一个更高优先级的异常,则处理器开始对该异常执行异常句柄,并且不会更改较早异常的挂起状态。这是迟到的情况。

2.异常返回

当处理器处理句柄模式,并且执行以下指令之一,尝试将PC设置为EXC_RETURN值时,将发生异常返回:

(1)加载PC的POP指令;

(2)使用任何寄存器的B PBX指令。

处理器在异常入口处将EXC_RETURN值保存到LR中。异常机制依靠该值来检测处理器何时完成异常句柄。EXC_RETURN值的第[31:4]位为0xFFFFFFF。当处理器将匹配该模式的值加载至PC时,它将检测到该操作不是正常的分支操作,而是完成异常。结果,它启动异常返回序列。EXC_RETURN值的位[3:0]指示所要求返回的堆栈和处理器模式,异常返回行为如表2.11所示。

表2.11 异常返回行为

思考与练习2.19:请说明在Cortex-M0+处理器中,异常的定义,以及处理异常的过程。

思考与练习2.20:根据图2.23,说明处理中断嵌套的过程。

思考与练习2.21:请说明在Cortex-M0处理器中,向量表所实现的功能。

思考与练习2.22:请说明在Cortex-M0处理器中,异常的类型。

2.5.6 NVIC中的中断寄存器集

NVIC中的中断寄存器集如表2.12所示。本节详细介绍这些寄存器的功能,以帮助读者更好地理解处理器异常的原理和控制机制。

表2.12 NVIC中的中断寄存器集

1.中断设置使能寄存器

中断设置使能寄存器(NVIC Interrupt Set Enable Register,NVIC_ISER)使能中断,并显示了所使能的中断,该寄存器的位分配如图2.27所示。

图2.27 中断设置使能寄存器的位分配

[31:0]:SETENA,中断设置使能位。当写入时:

①0,没有影响;

②1,使能中断。

当读取时:

①0,表示禁止中断;

②1,表示使能中断。

如果使能了待处理的中断,则NVIC会根据其优先级激活该中断。如果未使能中断,则中断有效信号将中断的状态改为挂起,但NVIC不会激活该中断,无论其优先级如何。

2.中断清除使能寄存器

中断清除使能寄存器(NVIC Interrupt Clear Enable Register,NVIC_ICER)禁用中断,并显示使能了哪些中断,该寄存器的位分配如图2.28所示。

图2.28 中断清除使能寄存器的位分配

[31:0]:CLRENA,中断清除使能位。当写入时:

①0,没有影响;

②1,禁止中断。

当读取时:

①0,禁止中断;

②1,使能中断。

3.中断设置挂起寄存器

中断设置挂起寄存器(NVIC Interrupt Set Pending Register,NVIC_ISPR)强制中断进入挂起状态,并指示正在挂起的中断,该寄存器的位分配如图2.29所示。

图2.29 中断设置挂起寄存器的位分配

[31:0]:SETPEND,中断设置挂起位。当写入时:

①0,没有影响;

②1,将中断状态改为挂起。

当读取时:

①0,当前没有挂起中断;

②1,当前有挂起中断。

注: 将1写入NVIC_ISPR位对应于:对于一个正在挂起的中断无效;禁用的中断将该中断的状态设置为挂起。

4.中断清除挂起寄存器

中断清除挂起寄存器(NVIC Interrupt Clear Pending Register,NVIC_ICPR)从中断中删除挂起状态,并显示正在挂起的中断,该寄存器的位分配如图2.30所示。

图2.30 中断清除挂起寄存器的位分配

[31:0]:CLRPEND,清除中断挂起位。当写入时:

①0,没有影响;

②1,删除挂起状态并中断。

当读取时:

①0,没有挂起中断;

②1,正在挂起中断。

5.中断优先级寄存器

中断优先级寄存器(NVIC Interrupt Priority Register,NVIC_IPR)0~7为每个中断提供了8位的优先级字段。这些寄存器只能通过字访问,每个寄存器包含4个优先级字段,这8个寄存器的位分配如图2.31所示,这些位分配的功能如表2.13所示。

图2.31 中断优先级寄存器的位分配

表2.13 位分配的功能

2.5.7 电平和脉冲中断

Cortex-M0+处理器中断对电平和脉冲均敏感。脉冲中断也称为边沿触发中断。

电平敏感中断一直保持有效,直到外设将中断信号设置为无效为止。通常,发生这种情况是因为ISR访问外设,导致其清除了中断请求。脉冲中断是在处理器时钟的上升沿同步采样的中断信号。为了确保NVIC检测到中断,外设必须在至少一个时钟周期内使中断信号有效,在此期间NVIC检测到脉冲并锁存中断。

当处理器进入ISR时,它会自动从中断中删除挂起中断。对于电平敏感的中断,如果在处理器从ISR返回之前没有使该信号无效,则中断状态再次变为挂起,处理器必须再次执行它的ISR。这意味着外设可以保持有效的中断信号,直到不需要继续服务为止。

Cortex-M0+处理器锁存所有中断。由于以下原因之一,挂起外设中断。

(1)NVIC检测到中断信号有效,而相应的中断无效。

(2)NVIC检测到中断信号的上升沿。

(3)软件写入相应的中断设置挂起寄存器位。

中断状态保持挂起,直到发生下面的情况之一为止。

(1)处理器进入中断的ISR。这会将中断的状态从挂起改为活动。

①对于电平敏感中断,当处理器从ISR返回时,NVIC采样中断信号。如果该信号有效,则中断状态变为挂起,这可能导致处理器立即重新进入ISR。否则,中断状态将变为非活动状态。

②对于脉冲中断,NVIC持续监视中断信号,如果发出脉冲信号,则中断状态将变为挂起并激活。在这种情况下,当处理器从ISR返回时,中断状态将变为挂起,这可能导致处理器立即重新进入ISR。如果在处理器处于ISR中时没有发出中断信号,则当处理器从ISR返回时,中断状态变为非活动状态。

(2)软件写入相应的中断清除挂起寄存器位。

对于电平敏感的中断,如果中断信号仍然有效,则中断状态不会变化。否则,中断状态将变为非活动状态。

对于脉冲中断,中断状态变为:

①非活动状态(如果状态为挂起);

②活动(如果状态是活动和挂起)。

确保软件使用正确对齐的寄存器访问。处理器不支持对NVIC的非对齐访问。即使一个中断被禁止,它也可以进入挂起状态。禁用中断只会阻止处理器接收该中断。

在对VTOR进行编程以重定位向量表之前,应确保新的向量表的入口已经设置了故障句柄、NMI和所有类似中断的使能异常。 HcApYWWELGjU11YATmmyQpoTwbYYlMzAEd7Z3smT6uA0HBdklnCbuo79F0N8Sepp

点击中间区域
呼出菜单
上一章
目录
下一章
×