一、异常和中断简介
中断一般由硬件(如外设和外部输入引脚)产生的事件,它会引起程序流偏离正常的流程(如给外设提供服务)。当外设或硬件需要处理器的服务时,一般会出现下面的流程:
①外设确认到处理器的中断请求。
②处理器暂停当前执行的任务
③处理器执行外设的ISR,若有必要可以选择由软件清除中断请求。
④处理器继续执行之前暂停的任务。
所有的cortex-m处理器都会提供一个用于中断处理的嵌套向量中断控制器(NVIC)。除了中断请求,还有其他需要服务的事件,将其称为异常。按照ARM的说法,中断也是一种异常。cortex-m处理器中的其他异常包括错误异常和其他用于OS支持的系统异常(如SVC指令)。处理异常的程序代码一般被称作异常处理,它们属于以编译程序映像的一部分。典型的cortex-m4微控制器中,NVIC接收多个中断源产生的中断请求,如下图所示:
cortex-m3 和cortex-m4 的NVIC支持最多240个IRQ(中断请求)、1个不可屏蔽中断(NMI)、1个SysTick(系统节拍)定时中断及多个系统异常。多数IRQ由定时器、I/O端口和通信接口(如UART和I2C)等外设产生。NMI通常由看门狗定时器或掉电检测器等外设产生,其余的异常则是来自处理器内核、中断还可以利用软件生成。
为了继续执行被中断的程序,异常流程需要利用一些手段来保存被中断程序的状态,这样在异常处理完成后还可以被恢复。一般来说,这个过程可以由硬件机制实现,也可由硬件和软件操作共同完成。对于cortex-m4处理器,当异常被接受后,有些寄存器会被自动保存到栈中,而且也会在返回流程中自动恢复。利用这种机制,可以将异常处理写作普通的C函数,同时也不会带来额外的软件开销。
二、异常类型
cortex-m处理器的异常架构具有多种特性,支持多个系统异常和外部中断。编号1-15的为系统异常,16及以上的则为中断输入(处理器的输入,不必从封装上的I/O引脚上访问)。包括所有中断在内的多数异常,都具有可编程的优先级,一些系统异常则具有固定的优先级。不同的cortex-m3或cortex-m4微控制器的中断源的编号(1~240)可能会不同,优先级也可能会有所差异。这是因为为了满足不同的应用需求,芯片设计者可能会对cortex-m3或cortex-m4设计进行相应的配置。
系统异常列表如下
异常编号 | 异常类型 | 优先级 | 描述 |
---|---|---|---|
1 | 复位 | -3(最高) | 复位 |
2 | NMI | -2 | 不可屏蔽中断(外部NMI输入) |
3 | 硬件错误 | -1 | 所有的错误都可能会引发,前提是相应的错误处理未使能 |
4 | MemManage错误 | 可编程 | 存储器管理错误,存储器管理单元(MPU)冲突或访问非法位置 |
5 | 总线错误 | 可编程 | 总线错误。当高级高性能总线(AHB)接口收到从总线的错误响应时产生(若未取指也被称作预取终止,数据访问则为数据终止) |
6 | 使用错误 | 可编程 | 程序错误或试图访问协处理器导致的错误(cortex-m3和cortex-m4处理器不支持协处理器) |
7-10 | 保留 | NA | NA |
11 | SVC | 可编程 | 请求管理调用。一般用于OS环境且允许应用任务访问系统服务 |
12 | 调试监控 | 可编程 | 调试监控。在使用基于软件的调试方案时,断点和监视点灯调试事件的异常 |
13 | 保留 | NA | NA |
14 | PendSV | 可编程 | 可挂起的服务调用。OS一般用该异常进行上下文切换 |
15 | SYSTICK | 可编程 | 系统节拍定时器。当其在处理器中存在时,由定时器外设产生。可用于OS或简单的定时器外设。 |
16 | 外部中断#0 | 可编程 | 可由片上外设或外设中断源产生 |
17 | 外部中断#1 | 可编程 | 可由片上外设或外设中断源产生 |
… | … | … | … |
255 | 外部中断#239 | 可编程 | 可由片上外设或外设中断源产生 |
三、中断管理简介
cortex-m处理器具有多个用于中断和异常管理的可编程寄存器,这些寄存器多数位于NVIC和系统控制块(SCB)中。实际上,SCB是作为NVIC的一部分实现的,不过CMSIS-CORE将其寄存器定义在了单独的结构体中。处理器内核中还有用于中断屏蔽的寄存器(如PRIMASK、FAULTMASK和BASEPRI)。NVIC和SCB位于系统控制空间(SCS),地址从0xE000E000开始,大小为4kb。SCS中还有SysTick定时器、存储器保护单元(MPU)以及用于调试的寄存器等。该地址区域中基本上所有的寄存器都只能由运行在特权访问等级的代码访问。唯一的例外为软件触发中断寄存器(STIR),它可被设置为非特权模式访问。对于一般的应用程序编程,最好是使用CMSIS-CORE访问函数。如有必要,还可以直接访问NVIC或SCB中的寄存器。复位后,所有中断都处于禁止状态,且默认的优先级为0.在使用任何一个中断之前,需要:
①设置所需中断的优先级(可选)、
②使能外设中的可以触发中断的中断产生控制
③使能NVIC中的中断。
四、优先级定义
对于cortex-m异常是否能被处理器接受以及何时被处理器接受并执行异常处理,是由异常的优先级和处理器当前的优先级决定的。更高优先级的异常(优先级编号更小)可以抢占低优先级的异常(优先级编号更大),这就是异常/中断嵌套的情形。有些异常(复位、NMI、HardFault)具有固定的优先级,其优先级由负数表示,这样,它们的优先级就会比其他的异常高。其他异常则具有可编程的优先级,范围为0~255.
cortex-m3和cortex-m4处理器在设计上具有3个固定的最高优先级以及256个可编程优先级(具有最多128个抢占等级),可编程优先级的实际数量由芯片设计商决定。多数M3或M4芯片支持的优先级较少,如8、16、32等。这是因为大量的优先级会增加NVIC的复杂度,而且会增加功耗降低的速度。多数情况下,应用程序只需少量的编程优先级。因此,芯片设计人员需要基于目标应用的优先级数量定制处理器设计。优先级的减少是通过去除优先级配置寄存器的最低位(LSB)实现的。
中断优先级由优先级寄存器控制,宽度为3~8位。若设计中只实现了3位优先级,优先级配置寄存器如下图所示: