单片机
返回首页

【STM32】HAL库-嵌套向量中断控制器NVIC

2022-06-16 来源:eefocus

中断与异常

嵌套向量中断控制器,简称为NVIC,其支持为数众多的系统异常和外部中断。


Cortex-M3支持256个中断。


中断/异常类型表如下

编号为 1-15 的称为系统异常(注意:没有编号为 0 的异常),大于等于 16 的称为(外部)中断。


除了个别异常的优先级被定死外,其它中断/异常的优先级都是可编程的

在这里插入图片描述
在这里插入图片描述

外部中断表如下

在这里插入图片描述

优先级

在 CM3 中,优先级对于异常来说很关键的,它会决定一个异常是否能被掩蔽,以及在未掩蔽的情况下何时可以响应。优先级的数值越小,则优先级越高。


CM3 支持中断嵌套,使得高优先级异常会抢占(preempt)低优先级异常。


有3个系统异常的优先级是固定的,并且是负数,分别为:复位,NMI 以及硬 fault


所有其它异常的先级则都是可编程的((但不能被编程为负数)


CM3 支持 3 个固定的高优先级(复位,NMI 以及硬 fault)和多达 256 级的可编程优先级,并且支持 128 级抢占式优先级

256级对应一个字节的大小,8位二进制,也就是每一个可编程的中断/异常有一个至少一个字节大小的寄存器来配置其优先级。并且是以 MSB 对齐的。

CM3 允许的最少使用位数为 3 个位,亦即至少要支持 8 级优先级


如使用3个位来定义优先级,则只有最高3位有效。

在这里插入图片描述

优先级 优先级设置寄存器的值

image.png

优先级分组

为了使抢占机能变得更可控,CM3 还把 256 级优先级按位分成高低两段,分别称为抢占优先级和子优先级


通过应用程序中断及复位控制寄存器(AIRCR)地址:0xE000_ED00来设置抢占式优先级与子优先级占用的位数。

在这里插入图片描述在这里插入图片描述

PRIGROUP的取值

在这里插入图片描述

子优先级至少是 1 个位。因此抢占优先级最多是 7 个位,造成了最多只有 128 级抢占的现象。


如使用最高3位来表达优先级,优先级分组选择5,则抢占式优先级用2个位表达,剩下的一个位则是子优先级。

在这里插入图片描述

使用最高3位来表达优先级,优先级分组选择1,则抢占式优先级占用3位,子优先级无效

在这里插入图片描述

如果两个中断的抢占式优先级和子优先级都相同,则先响应异常编号最小的那一个,例如,当 IRQ #3 的优先级与 IRQ #5 的优先级相等时,IRQ #3 会比 IRQ #5 先得到响应。


向量表

当发生中断或者异常时,需要定位其服务例程的入口地址(中断复位函数的入口地址)这些入口地址存储在所谓的“向量表”中。

也就是说向量表存储的是一个个函数的地址。默认情况下,,CM3 认为该表位于零地址处,且各向量占用 4 字节。

在这里插入图片描述

CM3支持动态重分发中断,CM3 允许向量表重定位——从其它地址处开始定位各异常向量。


为了实现这个功能,NVIC 中有一个寄存器,称为“向量表偏移量寄存器”(在地址 0xE000_ED08 处),通过修改它的值就能重定位向量表。

在这里插入图片描述

中断的触发与悬起(挂起)

当中断发生时候,该中断就被悬起。即使后来中断源撤消了中断请求,

已经被标记成悬起的中断也被记录下来。到了系统中它的优先级最高的时候,就会得到响应


悬起被置位:告诉CPU,有一个中断触发了,当该中断优先级最高时候,CPU将会根据向量表找到中断服务函数的入口地址,从而处理中断,当某中断的服务例程开始执行时,就称此中断进入了“活跃”状态,并且其悬起位会被硬件自动清除。

在这里插入图片描述

但是如果在某个中断得到响应之前,其悬起状态被清除了,则中断被取消。


在这里插入图片描述

如果中断源咬住请求信号不放,该中断就会在其上次服务例程返回后再次被置为悬起状态

在这里插入图片描述

Fault 类异常

CM3 中的 Faults 可分为以下几类:


总线 faults

存储器管理 faults

用法 faults

每个faults都有其对应的faults状态寄存器,用来指示出错的原因与类型。


更多细节请看CM3权威指南。


NVIC

嵌套向量中断控制器(NVIC)


NVIC 的访问地址是 0xE000_E000。所有 NVIC 的中断控制/状态寄存器都只能在特权级下访问,仅软件触发中断寄存器可以在用户级下访问以产生软件中断。


每个外部中断都有在 NVIC 的下列寄存器


使能与除能(失能)寄存器

悬起与“解悬”寄存器

优先级寄存器

活动状态寄存器(中断是否正在被CPU响应)

使能与除能(失能)寄存器

SETENA(使能)/CLRENA(失能) 可以按字/半字/字节的方式来访问

32 位寄存器,写1使能/失能,写0无效

CM3 中可以有 240 对使能位/除能位(SETENA 位/CLRENA 位),每个中断拥有一对。这 240 个对子分布在 8 对 32 位寄存器中(最后一对没有用完)

在这里插入图片描述

悬起与解悬寄存器

如果中断发生时,正在处理同级或高优先级异常,或者被掩蔽,则中断不能立即得到响应。此时中断被悬起。


中断的悬起状态可以通过“中断设置悬起寄存器(SETPEND)”和“中断悬起清除寄存器(CLRPEND)”来读取,还可以写它们来手工悬起中断。


其用法与前面介绍的使能/除能寄存器完全相同

在这里插入图片描述

中断优先级寄存器

每个外部中断都有一个对应的优先级寄存器,每个寄存器占用 8 位。

优先级寄存器都可以按字节访问,当然也可以按半字/字来访问

根据优先级组的设置,优先级可以被分为高低两个位段,分别是抢占优先级和亚优先级,

通过应用程序中断及复位控制寄存器(AIRCR)地址:0xE000_ED00来设置抢占式优先级与子优先级占用的位数。

在这里插入图片描述

系统异常的优先级设置

在这里插入图片描述

活动状态

每个外部中断都有一个活动状态位。在处理器执行了其 ISR(中断服务函数) 的第一条指令后,它的活动位就被置 1,并且直到 ISR 返回时才硬件清零。

哪怕中断被抢占,其活动状态也依然为 1。


按字/半字/字节访问,但是只读的

在这里插入图片描述

在这里插入图片描述

软件中断

软件触发中断请求

在这里插入图片描述

STM32的中断

以STM32F103C8T6为例


68个可屏蔽中断通道(不包含16个Cortex™-M3的中断线);

16个可编程的优先等级(使用了4位来表示中断优先级);

在这里插入图片描述

下面介绍HAL库的常用中断相关函数

其他的函数请查看stm32f1xx_hal_cortex.c文件


中断优先级分组

/**

  * @brief  Sets the priority grouping field (preemption priority and subpriority)

  *         using the required unlock sequence.

  * @param  PriorityGroup: The priority grouping bits length. 

  *         This parameter can be one of the following values:

  *         @arg NVIC_PRIORITYGROUP_0: 0 bits for preemption priority

  *                                    4 bits for subpriority

  *         @arg NVIC_PRIORITYGROUP_1: 1 bits for preemption priority

  *                                    3 bits for subpriority

  *         @arg NVIC_PRIORITYGROUP_2: 2 bits for preemption priority

  *                                    2 bits for subpriority

  *         @arg NVIC_PRIORITYGROUP_3: 3 bits for preemption priority

  *                                    1 bits for subpriority

  *         @arg NVIC_PRIORITYGROUP_4: 4 bits for preemption priority

  *                                    0 bits for subpriority

  * @note   When the NVIC_PriorityGroup_0 is selected, IRQ preemption is no more possible. 

  *         The pending IRQ priority will be managed only by the subpriority. 

  * @retval None

  */

void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup)

{

  /* Check the parameters */

  assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup));

  

  /* Set the PRIGROUP[10:8] bits according to the PriorityGroup parameter value */

  NVIC_SetPriorityGrouping(PriorityGroup);

}


设置中断的抢占式优先级与子优先级

/**

  * @brief  Sets the priority of an interrupt.

  * @param  IRQn: External interrupt number.

  *         This parameter can be an enumerator of IRQn_Type enumeration

  *         (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f10xx.h))

  * @param  PreemptPriority: The preemption priority for the IRQn channel.

  *         This parameter can be a value between 0 and 15

  *         A lower priority value indicates a higher priority 

  * @param  SubPriority: the subpriority level for the IRQ channel.

  *         This parameter can be a value between 0 and 15

  *         A lower priority value indicates a higher priority.          

  * @retval None

  */

void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)

  uint32_t prioritygroup = 0x00U;

  

  /* Check the parameters */

  assert_param(IS_NVIC_SUB_PRIORITY(SubPriority));

  assert_param(IS_NVIC_PREEMPTION_PRIORITY(PreemptPriority));

  

  prioritygroup = NVIC_GetPriorityGrouping();

  

  NVIC_SetPriority(IRQn, NVIC_EncodePriority(prioritygroup, PreemptPriority, SubPriority));

}


使能中断

/**

  * @brief  Enables a device specific interrupt in the NVIC interrupt controller.

  * @note   To configure interrupts priority correctly, the NVIC_PriorityGroupConfig()

  *         function should be called before. 

  * @param  IRQn External interrupt number.

  *         This parameter can be an enumerator of IRQn_Type enumeration

  *         (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f10xxx.h))

  * @retval None

  */

void HAL_NVIC_EnableIRQ(IRQn_Type IRQn)

{

  /* Check the parameters */

  assert_param(IS_NVIC_DEVICE_IRQ(IRQn));


  /* Enable interrupt */

  NVIC_EnableIRQ(IRQn);

}


失能中断

/**

  * @brief  Disables a device specific interrupt in the NVIC interrupt controller.

  * @param  IRQn External interrupt number.

  *         This parameter can be an enumerator of IRQn_Type enumeration

  *         (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f10xxx.h))  

  * @retval None

  */

void HAL_NVIC_DisableIRQ(IRQn_Type IRQn)

{

  /* Check the parameters */

  assert_param(IS_NVIC_DEVICE_IRQ(IRQn));


  /* Disable interrupt */

  NVIC_DisableIRQ(IRQn);

}


清除中断的挂起位

/**

  * @brief  Clears the pending bit of an external interrupt.

  * @param  IRQn External interrupt number.

  *         This parameter can be an enumerator of IRQn_Type enumeration

  *         (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f10xxx.h))  

  * @retval None

  */

void HAL_NVIC_ClearPendingIRQ(IRQn_Type IRQn)

{

  /* Check the parameters */

  assert_param(IS_NVIC_DEVICE_IRQ(IRQn));


  /* Clear pending interrupt */

  NVIC_ClearPendingIRQ(IRQn);

}


STM32CubeMX中的中断优先级配置

在这里插入图片描述

进入单片机查看更多内容>>
相关视频
  • 【TI MSPM0 应用实战】智能小车+工业角度编码器+血氧仪+烟雾探测器!硬核参考设计详解!

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

  • 直播回放: Microchip Timberwolf™ 音频处理器在线研讨会

  • 基于灵动MM32W0系列MCU的指夹血氧仪控制及OTA升级应用方案分享

精选电路图
  • 便携式混音器

  • 18W乙类音频放大器

  • 6晶体管H桥

  • USB LED调光器

  • USB自供电声卡

  • AVR LCD温度计—LM35

    相关电子头条文章