计算机原理与应用第七章——中断系统与Cortex-M微处理器的异常

第七章——中断系统与Cortex-M微处理器的异常

文章目录

  • 第七章——中断系统与Cortex-M微处理器的异常
    • 一、异常和中断的基本概念
      • (一)中断源
      • (二)中断管理
      • (三)中断优先级管理
      • (四)中断向量表
      • (五)中断过程
    • 二、Cortex-M微处理器的异常
      • (一)异常源
      • (二)中断管理
      • (三)中断优先级
      • (四)向量表重定位
      • (五)中断过程

一、异常和中断的基本概念

  • 中断:
    中断是内核的外部发生某一事件,产生触发信号,引起处理器暂停当前执行的程序,转去执行处理相应事件的程序,执行完毕后返回。
    中断是CPU和外部设备交换数据的主要方式之一,是用户要求计算机为自己服务的主要方式之一,针对不同的CPU,具体的做法是不一样的。

  • 异常:
    异常是程序执行过程中如果发生了意外事件,例如ARM体系中的软件中断、未定义指令、调试事件及系统复位功能等,正常执行的程序被暂停,转到相应的处理程序执行。

  • 关系:
    中断可看成是异常的一种。中断对内核来说是意外突发事件,请求信号来自外部;异常是内核产生的,即是在执行指令或存取中产生的。

(一)中断源

能够导致CPU产生中断的来源就是中断源。

  • 硬中断源 (外中断)
    ——外部的电路在CPU的引脚上产生的中断请求,可能是电位信号或者脉冲信号。不止一个,取决于接受硬中断请求的引脚。
  • 软中断源
    ——CPU执行程序过程中产生的中断,例如除法溢出,软中断指令等。
    计算机原理与应用第七章——中断系统与Cortex-M微处理器的异常_第1张图片
    常见中断源:
分类 举例
(1)常见的外部输入输出设备 (IRQ) 键盘,打印机,鼠标等
(2)数据通道中断源 (IRQ) 软盘,硬盘等
(3)实时过程产生的中断 (IRQ) 实时设备的采样中断,为某些实施控制设备发送控制信号
(4)定时或者计数信息 (IRQ) 计时、计数到一定值可以发出中断申请。一般都是外部中断,也可以是内部中断,例如实时时钟。
(5)故障源 一般是不可屏蔽中断(NMI)或者系统异常
(a)外设故障: 电源掉电,运行超限、监控诊断程序产生的诊断错误等。
(b)计算机故障:处理器出错(运算溢出、除数为0、非法数据格式),内存出错(非法地址、主存储器页面失效、数据或地址校验错),控制器出错(非法指令、未定义的操作码、堆栈溢出)等。
(6)程序调试设置的中断源 硬件断点:硬件调试器,软件断点:调试程序应支持单步运行和断点运行

(二)中断管理

不同的中断源又可以分为条件中断和无条件中断。

  • 无条件中断源的申请,CPU一定要响应 ,例如不可屏蔽中断。
  • 条件中断要求CPU处于开中断状态(就是CPU可以响应条件中断的状态)才响应中断,在关中断状态(就是不响应条件中断的状态)则不响应。

控制CPU处于开中断或者关中断的状态,也是和CPU有关。Cortex-M处理器内核中有中断屏蔽寄存器PRIMASK、FAULTMASK和BASEPRI,用于异常或者中断的屏蔽管理。有时CPU根据自己的工作状态会切换系统的开关中断状态。

(三)中断优先级管理

  • 中断优先级 (原因)
    可以有序处理多个中断源对CPU的同时申请, CPU优先处理优先级高的中断;
    可以允许中断嵌套。
  • 中断嵌套的规则:
    对于大多数系统,只有高优先级的中断源可以打断低优先级中断的服务;低级中断,或者同级中断原则上是不能要求中断嵌套的。

对于用户和开发人员,需要根据重要程度确定和处理实际中断源的优先级。更高优先级的异常具有更小的优先级编号。一些异常,比如复位(-3)、不可屏蔽中断NMI(-2)和硬件错误HardFault(-1)具有固定的优先级(优先级 ≠ \not= =异常编号)。除此之外,鱼油优先级编号0-255内的其他异常和中断具有可编程的优先级。 (中断源的优先级默认确定,部分优先级特别是外部优先级可以编程修改。)

(四)中断向量表

调用异常服务程序必须将处理器的指令指针转移到异常服务程序的入口,方法是使用中断向量表。
中断向量表是系统RAM或者系统ROM的一个区域 ,向量表的大小取决于CPU支持的中断类型和数量。 有两种类型:

  • 指令型 ,一般位于系统的ROM区域修改比较困难),存放的是一条转移指令。
    【CPU将指令指针调整到中断向量表的相应位置,然后指向该地址单元中的转移指令,跳转到相应异常的服务程序】。
  • 矢量中断型 ,在系统的ROM或者RAM区域存放的是中断向量(使用比较灵活)。中断向量是异常服务程序的入口地址。
    【CPU将指令指针调整到中断向量表的相应位置,然后根据这个表再找到服务程序的位置】

计算机原理与应用第七章——中断系统与Cortex-M微处理器的异常_第2张图片
经典的ARM7TDMI处理器采用的是指令型的中断向量表,而Cortex-M处理器采用矢量中断。

下面看看Cortex-M的矢量中断,向量表一定是在地址0开始的一段位置,只要异常编号乘以4可以得到向量表中该矢量地址的起始位置。
例如:编号为3的HardFault异常,其中断向量地址:3*4 = 0x0000000C
计算机原理与应用第七章——中断系统与Cortex-M微处理器的异常_第3张图片

(五)中断过程

  1. 初始化
    在中断过程发生之前,需要确认系统是否能响应该中断源,如果是有条件的外部中断,一定要检查它的屏蔽位、优先级和触发方式,为该中断准备对应的中断服务程序(ISR)。
  2. 中断申请
    除系统异常和软中断,中断申请是外部设备向CPU发送中断请求信号(电平信号或脉冲信号),需要注意外部设备发出的请求信号和CPU的要求是否一致。如果不一致,就要通过接口电路来解决。
    同时进行中断判优 (判别中断源的优先级),若符合中断条件和优先权,CPU接受中断请求,进入中断响应阶段。
  3. 中断响应
    保存断点地址(一般采用堆栈,有的采用寄存器),即原来程序指令所在的地址
    利用中断向量表,将程序指针指向中断服务程序入口
    ③在中断响应里,要完成断点保存、标志寄存器保存、关中断等,部分操作由CPU自动完成,用户也需要完成一些操作。
  4. 中断服务
    执行中断服务程序
  5. 中断返回
    返回到正常程序的断点,继续执行原来的程序。
    许多CPU把断点地址保存在堆栈中,返回时将断点地址弹出到指令指针。(由于堆栈具有“先入后出”的特点,很容易实现中断嵌套)如果断点地址在某个寄存器中,中断返回时就要用指令吧断点最低值传送到指令指针寄存器,这个工作往往要有用户在终端服务程序的最后来完成。

二、Cortex-M微处理器的异常

(一)异常源

Cortex-M微处理器的异常分为软中断源和硬中断源。

  • 硬中断源除了内核的系统异常(包括复位、硬件错误、存储器管理错误和总线错误等)外,主要是外部中断源,由嵌套向量中断控制器NVIC(Nested Vectored Interrupt Controller)来管理。
    主要是

    • 外部中断请求IRQ——多由定时器、I/O端口、通信接口(UART/SPI和I^2C)等外设产生;
    • 不可屏蔽中断NMI——多由看门狗定时器或者掉电检测产生;
    • SysTick系统节拍中断——来自处理器内核;
    • 内核系统异常;
      计算机原理与应用第七章——中断系统与Cortex-M微处理器的异常_第4张图片
  • 软中断源:

    • 系统异常,例如使用错误和调试监控等;
    • 一条中断指令,例如执行SVC指令触发的SVC异常;
    • 修改内核的软件触发中断寄存器(NVIC-STIRx)产生;
    • 修改内核的设置中断挂起寄存器(NVIC-ISPRx)产生;
    • 外部中断控制器EXTI的软件中断事件寄存器(EXTI_SWIERx)设置相应的请求位。

Cortex-M处理器支持的异常源通过异常类型编号来标识,都具有优先级特性,多数异常和中断的优先级还可以编程设置。异常类型编号1~15的为系统异常,类型16及以上的则为外部中断输入。(前三个也是复位、NMI、硬件错误)

ARM Cortex-M4处理器共支持240个外部中断,外部中断输入#0~#239也对应到NVIC的中断输入。
计算机原理与应用第七章——中断系统与Cortex-M微处理器的异常_第5张图片
CMSIS编号是厂商决定的,会提供在头文件IRQn的typedef段中进行异常编号的枚举值和枚举定义符号,所有的系统异常都是负值。

(二)中断管理

Cortex-M处理器内核中有中断屏蔽寄存器PRIMASK、FAULTMASK和BASEPRI,用于异常或者中断的屏蔽管理。

  1. PRIMASK寄存器

    • 只能在特权等级下访问,可以禁止除了NMI和HardFault外的所有异常;
    • 常应用于需要暂时禁止所有中断以执行一些时序关键的任务。
    • PRIMASK寄存器实质上是将当前的优先等级改为0(可编程最高等级)
  2. FAULTMASK寄存器

    • 只能在特权等级下访问,可以禁止除了NMI外的所有异常(甚至是HardFault异常)。
    • FAULTMASK寄存器实质上是将当前的优先等级提升为-1
    • 当FAULTMASK寄存器置1时,只有NMI异常会被响应。
    • 除了NMI异常处理之外,所有的异常处理会在返回退出时自动将FAULTMASK寄存器清除。
  • 上面两个寄存器,都是置1表示“禁止所有中断”,置0表示不进行禁止,使能中断。
  1. BASEPRI寄存器

    • 高优先级的异常可以屏蔽低优先级的异常,这种禁止方式也是对异常的控制管理。
    • 每个异常(包括中断)都具有一个优先等级,数值越小优先级越高。
    • 使用BASEPRI寄存器禁止某特定优先等级及其以下等级的中断。
      例如:0x40写入BASEPRI寄存器,则会屏蔽优先级小于等于0x40即在0x40~0xFF之间的中断。
  2. NVIC中的寄存器

    • Cortex-M4处理器的NVIC具有多个中断和异常管理的可编程寄存器,在CMSIS-Core里对应这些寄存器分别定义了NVIC和系统控制块SCB的结构体,可以编程设置其中的寄存器来实现中断管理。
    • NVIC和SCB位于系统控制空间(SCS),地址从0xE000E000开始,大小为4KB。

(三)中断优先级

Cortex-M的处理器的中断优先级都是有NVIC何SCB定义的寄存器来管理的。

  • 中断优先级寄存器NVIC_IPRx,每个32位的寄存器可管理4个IRQ中断的优先级配置(就是每个优先级配置用的是8位),对应CMSIS-Core中的NVIC->IP[n](若有60个寄存器,则n:0~239)
  • 3个SCB_SHPR寄存器存放内核异常的优先级配置, 最大可配置12个内核异常的优先级(有15个系统异常,可以看到这个并没有完全实现),对应CMSIS-Core中的NVIC->SHP[n](n:0~11)

Cortex-M处理器例如Cortex-M3、M4芯片支持的优先级数量可选择是2的倍数,也就是8、16、32等值,其优先等级的数量由芯片厂商具体决定。数量越大的优先级会增加NVIC的复杂度,增加功耗降低速度。

优先级的减少是通过去除优先级配置寄存器的最低位LSB来实现的

例如:写出Cortex-M3/M4处理器的3位优先级宽度可实现的等级:
8位的优先级配置寄存器,设计使用3位优先级,可知第0~4位(共5位)未实现,都置0。可能的优先级就是
0x00(最高优先级)、0x20 、 0x40、0x60、0x80、0xA0、0xC0、0xE0(1110 0000)。

以此类推,若使用了4位优先级宽度就是2^4=16个可编程优先级。

Cortex-M0:

Cortex-M0+处理器的NVIC_IPR只有8个寄存器,则最多支持32个IRQ中断源(4x8=32),加上16个内核异常,一共有48个中断源。中断优先级配置PRI_xx的8位中只有最高2位[7:6]有效,则只有4个可用的优先级配置:0x00、0x40、0x80、0xC0。【这些都是厂家规定了的】

Cortex-M0+处理器的优先级配置相对简单,优先级寄存器存放的配置PRI_xx越低则中断优先级越高,优先级比较高的中断可以随时抢占优先级低的中断服务。一般默认中断源的异常编号越低,其中断优先级也越高,用户可以根据实际需要进行相应配置。

Cortex-M4:

Cortex-M4处理器的8位优先级寄存器进一步划分为两个部分:分组优先级(也称抢占优先级,pre-emption priority)和子优先级(subpriority)。

  • 分组优先级决定了是否能嵌套,高的组优先级中断(数值低)可以抢占低的组优先级(数值高)中断,如果组优先级是一样的,即使子优先级比正在执行的中断的子优先级高也是不能抢占的。
  • 在组优先级一致的情况下,多个中断请求同时发生,这样的情况下子优先级高的可以先执行,而子优先级低的则只能暂时挂起(pending)。

Cortex-M4处理器的系统控制块SCB中有一个优先级分组的配置寄存器SCB_AIRCR(应用中断和复位控制寄存器),其中PRIGROUP域的值决定了8种不同的优先级分组方式:
计算机原理与应用第七章——中断系统与Cortex-M微处理器的异常_第6张图片

  • 配置寄存器宽度多少是用户可以决定的;

  • 配置了宽度x之后,就表示每个8位里只有高x位时可用的,然后在这x位里,有多少个是“抢占优先级域”,有多少个“子优先级域”,就是由分组决定的。

     例:配置寄存器的宽度为3,AIRCR设置的优先级分组为5。
     宽度为3,就有总共8个优先级。分组为5,即只有最高两位是抢占优先级域,第5位是子优先级域。
     这样的话就有4个分组(抢占)优先级(第7~6位),分别是0x00,0x40,0x80,0xC0,
     然后每个分组优先级下具有2个子优先级。
     所有的子优先级为:0x00,0x20,0x040,0x60,0x80,0xA0,0xC0,0xE0。
    

计算机原理与应用第七章——中断系统与Cortex-M微处理器的异常_第7张图片

	但是要注意,如果配置寄存器的宽度是3位,但是优先级分组是1,那是什么情况?
	情况就是:子优先级域的值都是0,这样就不存在子优先级的分组了,
	总共优先级个数是8,即0x00,0x20,0x040,0x60,0x80,0xA0,0xC0,0xE0,
	所有的子优先级也是0x00,0x20,0x040,0x60,0x80,0xA0,0xC0,0xE0。

计算机原理与应用第七章——中断系统与Cortex-M微处理器的异常_第8张图片

(四)向量表重定位

Cortex-M处理器的向量表一般被定义在微控制器供应商的启动代码中。起始地址0x00000000处是Flash存储器或者ROM设备,运行时不能修改,但是为了运行时动态修改或者重定义向量表,Cortex-M4处理器采用了**“向量表重定位”**的方式。

“向量表重定位”方式提供一个可编程的向量表偏移寄存器 SCB_VTOR,SCB_VTOR寄存器配置新向量表的基地址
一般是将新向量表的位置重定位为RAM存储器的首地址(0x20000000)。由于最小的中断向量表要求对齐为128字节,所以SCB_VTOR寄存器的最低7位保留且被强制置为0
映射要求是,必须注意向量表的起始地址的要求:必须先求出系统中共有多少个向量,再把这个数字向上增大到是 2 的整次幂,而起始地址必须对齐到后者的边界上。因此中断向量表的大小一般要被扩展为下一个2的整数次方。

例1:Cortex-M微控制器有32个或者75个中断源的情况下,请给出向量表的大小以及可能设置的向量表的基地址。

32个中断源的向量表大小为:

(32(用于中断)+16(系统异常))×4(每个向量的字节数)=192

扩展为下一个2的整数次方得到256字节(一个地址是4个字节,),因此向量表的基地址可被设置为0x00000000、0x00000100、0x00000200等。

75个中断源的向量表大小为:
(75(用于中断)+16(系统异常))×4(每个向量的字节数)=364

扩展为下一个2的整数次方得到512字节,因此向量表的基地址可被设置为0x00000000、0x00000200、0x00000400等。

(五)中断过程

  1. 初始化过程
    Cortex-M处理器在CPU复位后,所有中断处于禁止状态,且默认的优先级为0。在使用任何一种中断之前,需要进行如下操作:

    • 设置所需中断的优先级(该步骤是可选的)
    • 使能外设中的可以触发中断的中断产生控制
    • 使能NVIC中的中断。
  2. 中断申请过程
    若满足下列的中断申请条件,Cortex-M处理器会接受中断申请:

    • 处理器正在运行,未被暂停或处于复位状态;
    • 中断处于使能状态,NMI和HardFault总是处于使能;
    • 中断的优先级高于当前的等级;
    • 中断未被屏蔽寄存器PRIMASK等屏蔽。

    Cortex-M处理器的NVIC控制器支持,不需要配置NVIC的寄存器来选择其中一种中断类型:

    • 脉冲(pulse-sensitive)中断请求的外设
      脉冲中断请求在处理器时钟的上升沿同步采集,因此其脉冲宽度至少要保持一个时钟周期,中断输入才会被接受并且设置中断挂起状态。当有效的脉冲中断请求消失后,挂起状态依然保持有效,而且在进入中断处理之前多次的脉冲中断请求会被只当做一次中断请求来处理。
    • 高电平(level-sensitive)中断请求的外设
      对于电平触发的请求,只要保持有效的信号电平是NVIC的中断输入被确认,就会引发该中断的挂起。
      计算机原理与应用第七章——中断系统与Cortex-M微处理器的异常_第9张图片
      中断挂起是一种等待处理器处理的状态,当处理器正在执行另外一个高等优先级或者同等优先级的中断,或者中断被中断屏蔽寄存器给屏蔽了,即使中断源外设取消了请求信号,已产生的中断挂起状态会一直保持到其它中断处理结束或者中断屏蔽被清除。中断挂起状态在进入到中断处理即中断活跃状态之后被清除。
  • 经典ARM处理器的中断请求例如IRQ和FIQ都需要在中断处理之前一直保持请求信号;
  • Cortex-M处理器中的NVIC可以确保即使中断的源设备取消了中断请求信号,已产生的中断挂起仍会被处理。

中断挂起状态可以通过中断设置挂起寄存器NVIC_ISPR[n]和中断清除挂起寄存器NVIC_ICPR[n]来访问。

注意:
注意以下几点:

  • 中断服务程序ISR(interrupt service routine)开始处理中断请求时,开始进入中断活跃状态,这时中断的请求信号被自动清除。
  • 中断挂起状态之后,若外设一直保持某个中断请求,即使软件清除了中断挂起状态,或者中断挂起状态已经被中断处理完成,则中断请求还是会被确认且再次进入挂起状态的。
  • NMI方式是具有最高优先级且不能被禁止的中断,若当前没有运行NMI处理或者处理器处于被暂停、锁定的状态,NMI请求会被立即响应。
  1. 中断响应过程
    Cortex-M处理器在中断响应过程中,系统自动完成以下的操作:

    • 多个寄存器和返回地址被压入当前正在使用的栈。
    • 取出中断向量,转入中断服务处理程序执行指令。
    • 同时更新多个NVIC寄存器和内核寄存器的值。栈指针PSP或者MSP自动调整为压栈完成后的值。程序计数器PC更新为异常处理的起始地址,链接寄存器LR更新为EXC_RETURN的值,(EXC_RETURN用来保存异常处理流程的状态信息,包括压栈使用的哪个栈指针)
  2. 中断服务过程
    执行中断处理服务程序时,处理器处于处理模式,处于特权访问等级,使用主栈指针MSP
    中断嵌套是正在执行的处理会被挂起(pending)而被更高优先级的中断抢占。
    中断处理服务结尾,程序代码执行的返回会引起EXC_RETURN数值被加载到程序计数器PC中,触发中断返回过程。
    **每个外部中断都有一个活跃状态位,当中断处理开始执行时该位会被置1,中断返回后会被清零。**活跃状态位保存在中断状态寄存器NVIC->IABR中。可能有多个被置位的活跃状态位。

  3. 中断返回
    异常返回是由一个特殊的值EXC_RETURN来触发。该数值由异常返回指令写入PC时,就会触发异常返回过程。

BX  LR	     若EXC_RETURN数值仍在LR中,则在异常处理结束时可以使用BX  LR指令执行中断返回。
POP {PC} 或 POP {……,PC}        异常处理后,LR的值通常会被压入栈中
加载(LDR)或多寄存器加载(LDM)       加载指令以PC为目的寄存器可以产生中断返回。

你可能感兴趣的:(计算机原理,stm32,linux)