首页 > 其他分享 >08. NVIC中断控制器

08. NVIC中断控制器

时间:2024-03-03 18:33:41浏览次数:16  
标签:控制器 优先级 中断 08 global NVIC IRQn Interrupt

一、什么是中断

  在主程序运行过程中,出现了特定事件,使得 CPU 暂停当前正在运行的程序,转而去处理这个事件,等这个事件处理完成之后,CPU 再回到刚才被打断的位置继续处理,则就是 中断。那个打断 CPU 执行的特定事件,我们一般称之为 中断源。被中断打断的位置我们称为 断点。处理特定实际事件的过程,我们称为执行 中断处理函数

  正在执行中断程序的时候,这个时候有可能被另外一个中断源给中断,CPU 转而执行另外一个中断源的中断处理函数,这叫 中断嵌套。中断 B 能够打断中断 A,要看它们的优先级,优先级高的中断可以打断优先级的中断。优先级低的中断无法打断优先级高的中断。

  通过中断,我们可以实现实时控制,即在确定的时间内对相应的事件作出响应。通过中断,我们可以对检测出来的故障进行第一时间的处理。对于不知何时会来的数据,我们也可以借助中断来实现数据传输。

  中断向量表 定义在启动文件中,它是一块固定的内存,以 4 字节对齐,存放每个中断服务函数程序的首地址。当中断发生的时候,CPU 会自动执行对象的中断服务函数。

中断可以高效处理紧急程序,不会一直占用 CPU 的资源;

二、NVIC简介

  NVIC嵌套向量中断控制器,全称 Nested vectored interrupt controller。它是内核的器件。M3/M4/M7 内核都是支持 256 个中断,其中包含了 16 个系统中断和 240 个外部中断,并且具有 256 级的可编程中断设置。然而芯片厂商一般不会把内核的这些资源全部用完,如 STM32F407 的系统中断有 10 个,外部中断有 82 个。

  STM32F407 的系统中断有如下:

中断向量表的系统中断部分

  关于 82 个外部中断部分在《STM32F4xx 参考手册_V4(中文版).pdf》的 10.2 小节有详细的列表,这里就不列出来了。STM32F407 的中断向量表在 stm32f407xx.h 文件中被定义。

三、NVIC寄存器

  NVIC 相关的寄存器定义了可以在 core_cm4.h 文件中找到。

typedef struct
{
  __IOM uint32_t ISER[8U];                  // 中断使能寄存器
        uint32_t RESERVED0[24U];
  __IOM uint32_t ICER[8U];                  // 中断清除使能寄存器
        uint32_t RSERVED1[24U];
  __IOM uint32_t ISPR[8U];                  // 中断使能挂起寄存器
        uint32_t RESERVED2[24U];
  __IOM uint32_t ICPR[8U];                  // 中断解挂寄存器
        uint32_t RESERVED3[24U];
  __IOM uint32_t IABR[8U];                  // 中断有效位寄存器
        uint32_t RESERVED4[56U];
  __IOM uint8_t  IP[240U];                  // 中断优先级寄存器(8Bit位宽)
        uint32_t RESERVED5[644U];
  __OM  uint32_t STIR;                      // 中断触发中断寄存器
}  NVIC_Type;

  ISER[8]:ISER 全称是:Interrupt Set Enable Registers,这是一个 中断使能寄存器组。上面说了 CM4 内核支持 256 个中断,这里用 8 个 32 位寄存器来控制,每个位控制一个中断。但是 STM32F407 的可屏蔽中断最多只有 82 个,所以对我们来说,有用的就是两个(ISER[0 ~ 3]),总共可以表示 128 个中断。而 STM32F407 只用了其中的 82 个。ISER[0] 的 bit0 ~ 31 分别对应中断 0 ~ 31;ISER[1] 的 bit0 ~ 31 对应中断 32 ~ 63; ISER[2] 的 bit0 ~ 16 对应中断 64 ~ 81,这样总共 82 个中断就可以分别对应上了。你要使能某个中断,必须设置相应的 ISER 位为 1,使该中断被使能(这里仅仅是使能,还要配合中断分组、屏蔽、IO 口映射等设置才算是一个完整的中断设置)。

  ICER[8]:全称是:Interrupt Clear Enable Registers,是一个 中断除能寄存器组。该寄存器组与 ISER 的作用恰好相反,是用来清除某个中断的使能的。其对应位的功能,也和 ISER 一样。这里要专门设置一个 ICER 来清除中断位,而不是向 ISER 写 0 来清除,是因为 NVIC 的这些寄存器都是写 1 有效的,写 0 是无效的。

  ISPR[8]:全称是:Interrupt Set Pending Registers,是一个 中断使能挂起控制寄存器组。每个位对应的中断和 ISER 是一样的。通过置 1,可以将正在进行的中断挂起,而执行同级或更高级别的中断。写 0 是无效的。

  ICPR[8]:全称是:Interrupt Clear Pending Registers,是一个 中断解挂控制寄存器组。其作用与 ISPR 相反,对应位也和 ISER 是一样的。通过设置 1,可以将挂起的中断解挂。写 0 无效。

  IABR[8]:全称是:Interrupt Active Bit Registers,是一个 中断激活标志位寄存器组。对应位所代表的中断和 ISER 一样,如果为 1,则表示该位所对应的中断正在被执行。这是一个只读寄存器,通过它可以知道当前在执行的中断是哪一个。在中断执行完了由硬件自动清零。

  IP[240]:全称是:Interrupt Priority Registers,是一个 中断优先级控制的寄存器组。IP 寄存器组由 240 个 8bit的寄存器组成,每个可屏蔽中断占用 8bit,这样总共可以表示 240 个可屏蔽中断。而 STM32F407 只用到了其中的 82 个。IP[81] ~ IP[0] 分别对应中断 81 ~ 0。而每个可屏蔽中断占用的 8bit 并没有全部使用,而是只用了高 4 位。这 4 位,又分为抢占优先级和子优先级。抢占优先级在前,子优先级在后。而这两个优先级各占几个位又要根据 SCB->AIRCR 中的中断分组设置来决定。

四、中断优先级

  STM32 中的中断优先级可以分为:抢占式优先级响应优先级,响应优先级也称子优先级,每个中断源都需要被指定这两种优先级。抢占式优先级和响应优先级的区别:

  • 抢占优先级:抢占优先级高的中断可以打断正在执行的抢占优先级低的中断。
  • 响应优先级:抢占优先级相同,响应优先级高的中断不能打断响应优先级低的中断。

  当两个或者多个中断的抢占式优先级和响应优先级相同时,那么就遵循自然优先级,看中断向量表的中断排序,数值越小,优先级越高。

  在 NVIC 中由寄存器 NVIC_IPR0 ~ NVIC_IPR59 共 60 个寄存器控制中断优先级,每个寄存器的每 8 位又分为一组,可以分 4 组,所以就有了 240 组宽度为 8bit 的中断优先级控制寄存器,原则上每个外部中断可配置的优先级为 0 ~ 255,数值越小,优先级越高。但是实际上 M3/M4/M7 芯片为了精简设计,只使用了高四位 [7:4],低四位取零,这样以至于最多只有 16 级中断嵌套,即 2^4=16。

  对于 NVCI 的中断优先级分组:STM32F407 将中断分为 5 个组,组 0 ~ 4。该分组的设置是由 SCB->AIRCR 寄存器的 bit10 ~ 8 来定义的。具体的分配关系如下表所示:

AIRCR中断分组设置表

  例如优先级分组设置为 2,那么此时所有的 82 个中断,每个中断的中断优先寄存器的高四位中的高 2 位是抢占优先级,低 2 位是响应优先级。每个中断,你可以设置抢占优先级为 0 ~ 3,响应优先级为 0 ~ 3。抢占优先级的级别高于响应优先级。而数值越小所代表的优先级就越高。

  然后设置中断 1 的抢占优先级为 2,响应优先级为 1。中断 2 的抢占优先级为 3,响应优先级为 0。中断 3 的抢占优先级为 2,响应优先级为 0。那么这 3 个中断的优先级顺序为:中断 1 > 中断 3 > 中断 2。中断 1 和中断 3 都可以打断中断 2 的中断。而中断 1 和中断 3 却不可以相互打断!

五、NVIC相关函数

  ST 公司把 core_cm4.h 文件的 NVIC 相关函数封装到 stm32f4xx_hal_cortex.c 文件中。

5.1、设置中断优先级分组函数

  HAL_NVIC_SetPriorityGrouping() 函数是设置中断优先级分组函数。其声明如下:

void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup);

  其中,参数 PriorityGroup中断优先级分组号,可以选择范围如下:

#define NVIC_PRIORITYGROUP_0         0x00000007U /*!< 0 bits for pre-emption priority
                                                      4 bits for subpriority */
#define NVIC_PRIORITYGROUP_1         0x00000006U /*!< 1 bits for pre-emption priority
                                                      3 bits for subpriority */
#define NVIC_PRIORITYGROUP_2         0x00000005U /*!< 2 bits for pre-emption priority
                                                      2 bits for subpriority */
#define NVIC_PRIORITYGROUP_3         0x00000004U /*!< 3 bits for pre-emption priority
                                                      1 bits for subpriority */
#define NVIC_PRIORITYGROUP_4         0x00000003U /*!< 4 bits for pre-emption priority
                                                      0 bits for subpriority */

  这个函数在一个工程里基本只调用一次,而且是在程序 HAL 库初始化函数里面已经被调用,后续就不会再调用了。因为当后续调用设置成不同的中断优先级分组时,有可能造成前面设置好的抢占优先级和响应优先级不匹配。如果调用了多次,则以最后一次为准。

5.2、设置中断优先级函数

  HAL_NVIC_SetPriority() 函数是设置中断优先级函数。其声明如下:

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

  其中,参数 IRQn中断号,可以选择范围:IRQn_Type 定义的枚举类型,定义在 stm32f407xx.h。

typedef enum
{
/******  Cortex-M4 Processor Exceptions Numbers ****************************************************************/
  NonMaskableInt_IRQn         = -14,    /*!< 2 Non Maskable Interrupt                                          */
  MemoryManagement_IRQn       = -12,    /*!< 4 Cortex-M4 Memory Management Interrupt                           */
  BusFault_IRQn               = -11,    /*!< 5 Cortex-M4 Bus Fault Interrupt                                   */
  UsageFault_IRQn             = -10,    /*!< 6 Cortex-M4 Usage Fault Interrupt                                 */
  SVCall_IRQn                 = -5,     /*!< 11 Cortex-M4 SV Call Interrupt                                    */
  DebugMonitor_IRQn           = -4,     /*!< 12 Cortex-M4 Debug Monitor Interrupt                              */
  PendSV_IRQn                 = -2,     /*!< 14 Cortex-M4 Pend SV Interrupt                                    */
  SysTick_IRQn                = -1,     /*!< 15 Cortex-M4 System Tick Interrupt                                */
/******  STM32 specific Interrupt Numbers **********************************************************************/
  WWDG_IRQn                   = 0,      /*!< Window WatchDog Interrupt                                         */
  PVD_IRQn                    = 1,      /*!< PVD through EXTI Line detection Interrupt                         */
  TAMP_STAMP_IRQn             = 2,      /*!< Tamper and TimeStamp interrupts through the EXTI line             */
  RTC_WKUP_IRQn               = 3,      /*!< RTC Wakeup interrupt through the EXTI line                        */
  FLASH_IRQn                  = 4,      /*!< FLASH global Interrupt                                            */
  RCC_IRQn                    = 5,      /*!< RCC global Interrupt                                              */
  EXTI0_IRQn                  = 6,      /*!< EXTI Line0 Interrupt                                              */
  EXTI1_IRQn                  = 7,      /*!< EXTI Line1 Interrupt                                              */
  EXTI2_IRQn                  = 8,      /*!< EXTI Line2 Interrupt                                              */
  EXTI3_IRQn                  = 9,      /*!< EXTI Line3 Interrupt                                              */
  EXTI4_IRQn                  = 10,     /*!< EXTI Line4 Interrupt                                              */
  DMA1_Stream0_IRQn           = 11,     /*!< DMA1 Stream 0 global Interrupt                                    */
  DMA1_Stream1_IRQn           = 12,     /*!< DMA1 Stream 1 global Interrupt                                    */
  DMA1_Stream2_IRQn           = 13,     /*!< DMA1 Stream 2 global Interrupt                                    */
  DMA1_Stream3_IRQn           = 14,     /*!< DMA1 Stream 3 global Interrupt                                    */
  DMA1_Stream4_IRQn           = 15,     /*!< DMA1 Stream 4 global Interrupt                                    */
  DMA1_Stream5_IRQn           = 16,     /*!< DMA1 Stream 5 global Interrupt                                    */
  DMA1_Stream6_IRQn           = 17,     /*!< DMA1 Stream 6 global Interrupt                                    */
  ADC_IRQn                    = 18,     /*!< ADC1, ADC2 and ADC3 global Interrupts                             */
  CAN1_TX_IRQn                = 19,     /*!< CAN1 TX Interrupt                                                 */
  CAN1_RX0_IRQn               = 20,     /*!< CAN1 RX0 Interrupt                                                */
  CAN1_RX1_IRQn               = 21,     /*!< CAN1 RX1 Interrupt                                                */
  CAN1_SCE_IRQn               = 22,     /*!< CAN1 SCE Interrupt                                                */
  EXTI9_5_IRQn                = 23,     /*!< External Line[9:5] Interrupts                                     */
  TIM1_BRK_TIM9_IRQn          = 24,     /*!< TIM1 Break interrupt and TIM9 global interrupt                    */
  TIM1_UP_TIM10_IRQn          = 25,     /*!< TIM1 Update Interrupt and TIM10 global interrupt                  */
  TIM1_TRG_COM_TIM11_IRQn     = 26,     /*!< TIM1 Trigger and Commutation Interrupt and TIM11 global interrupt */
  TIM1_CC_IRQn                = 27,     /*!< TIM1 Capture Compare Interrupt                                    */
  TIM2_IRQn                   = 28,     /*!< TIM2 global Interrupt                                             */
  TIM3_IRQn                   = 29,     /*!< TIM3 global Interrupt                                             */
  TIM4_IRQn                   = 30,     /*!< TIM4 global Interrupt                                             */
  I2C1_EV_IRQn                = 31,     /*!< I2C1 Event Interrupt                                              */
  I2C1_ER_IRQn                = 32,     /*!< I2C1 Error Interrupt                                              */
  I2C2_EV_IRQn                = 33,     /*!< I2C2 Event Interrupt                                              */
  I2C2_ER_IRQn                = 34,     /*!< I2C2 Error Interrupt                                              */
  SPI1_IRQn                   = 35,     /*!< SPI1 global Interrupt                                             */
  SPI2_IRQn                   = 36,     /*!< SPI2 global Interrupt                                             */
  USART1_IRQn                 = 37,     /*!< USART1 global Interrupt                                           */
  USART2_IRQn                 = 38,     /*!< USART2 global Interrupt                                           */
  USART3_IRQn                 = 39,     /*!< USART3 global Interrupt                                           */
  EXTI15_10_IRQn              = 40,     /*!< External Line[15:10] Interrupts                                   */
  RTC_Alarm_IRQn              = 41,     /*!< RTC Alarm (A and B) through EXTI Line Interrupt                   */
  OTG_FS_WKUP_IRQn            = 42,     /*!< USB OTG FS Wakeup through EXTI line interrupt                     */
  TIM8_BRK_TIM12_IRQn         = 43,     /*!< TIM8 Break Interrupt and TIM12 global interrupt                   */
  TIM8_UP_TIM13_IRQn          = 44,     /*!< TIM8 Update Interrupt and TIM13 global interrupt                  */
  TIM8_TRG_COM_TIM14_IRQn     = 45,     /*!< TIM8 Trigger and Commutation Interrupt and TIM14 global interrupt */
  TIM8_CC_IRQn                = 46,     /*!< TIM8 Capture Compare global interrupt                             */
  DMA1_Stream7_IRQn           = 47,     /*!< DMA1 Stream7 Interrupt                                            */
  FSMC_IRQn                   = 48,     /*!< FSMC global Interrupt                                             */
  SDIO_IRQn                   = 49,     /*!< SDIO global Interrupt                                             */
  TIM5_IRQn                   = 50,     /*!< TIM5 global Interrupt                                             */
  SPI3_IRQn                   = 51,     /*!< SPI3 global Interrupt                                             */
  UART4_IRQn                  = 52,     /*!< UART4 global Interrupt                                            */
  UART5_IRQn                  = 53,     /*!< UART5 global Interrupt                                            */
  TIM6_DAC_IRQn               = 54,     /*!< TIM6 global and DAC1&2 underrun error  interrupts                 */
  TIM7_IRQn                   = 55,     /*!< TIM7 global interrupt                                             */
  DMA2_Stream0_IRQn           = 56,     /*!< DMA2 Stream 0 global Interrupt                                    */
  DMA2_Stream1_IRQn           = 57,     /*!< DMA2 Stream 1 global Interrupt                                    */
  DMA2_Stream2_IRQn           = 58,     /*!< DMA2 Stream 2 global Interrupt                                    */
  DMA2_Stream3_IRQn           = 59,     /*!< DMA2 Stream 3 global Interrupt                                    */
  DMA2_Stream4_IRQn           = 60,     /*!< DMA2 Stream 4 global Interrupt                                    */
  ETH_IRQn                    = 61,     /*!< Ethernet global Interrupt                                         */
  ETH_WKUP_IRQn               = 62,     /*!< Ethernet Wakeup through EXTI line Interrupt                       */
  CAN2_TX_IRQn                = 63,     /*!< CAN2 TX Interrupt                                                 */
  CAN2_RX0_IRQn               = 64,     /*!< CAN2 RX0 Interrupt                                                */
  CAN2_RX1_IRQn               = 65,     /*!< CAN2 RX1 Interrupt                                                */
  CAN2_SCE_IRQn               = 66,     /*!< CAN2 SCE Interrupt                                                */
  OTG_FS_IRQn                 = 67,     /*!< USB OTG FS global Interrupt                                       */
  DMA2_Stream5_IRQn           = 68,     /*!< DMA2 Stream 5 global interrupt                                    */
  DMA2_Stream6_IRQn           = 69,     /*!< DMA2 Stream 6 global interrupt                                    */
  DMA2_Stream7_IRQn           = 70,     /*!< DMA2 Stream 7 global interrupt                                    */
  USART6_IRQn                 = 71,     /*!< USART6 global interrupt                                           */
  I2C3_EV_IRQn                = 72,     /*!< I2C3 event interrupt                                              */
  I2C3_ER_IRQn                = 73,     /*!< I2C3 error interrupt                                              */
  OTG_HS_EP1_OUT_IRQn         = 74,     /*!< USB OTG HS End Point 1 Out global interrupt                       */
  OTG_HS_EP1_IN_IRQn          = 75,     /*!< USB OTG HS End Point 1 In global interrupt                        */
  OTG_HS_WKUP_IRQn            = 76,     /*!< USB OTG HS Wakeup through EXTI interrupt                          */
  OTG_HS_IRQn                 = 77,     /*!< USB OTG HS global interrupt                                       */
  DCMI_IRQn                   = 78,     /*!< DCMI global interrupt                                             */
  RNG_IRQn                    = 80,     /*!< RNG global Interrupt                                              */
  FPU_IRQn                    = 81      /*!< FPU global interrupt                                               */
} IRQn_Type;

  参数 PreemptPriority抢占优先级,可以选择范围:0 到 15,具体根据中断优先级分组决定。

  参数 SubPriority响应优先级,可以选择范围:0 到 15,具体根据中断优先级分组决定。

5.3、中断使能函数

  HAL_NVIC_EnableIRQ() 函数是中断使能函数。其声明如下:

void HAL_NVIC_EnableIRQ(IRQn_Type IRQn);

  其中,参数 IRQn中断号,可以选择范围:IRQn_Type 定义的枚举类型,定义在 stm32f407xx.h。

5.4、中断失能函数

  HAL_NVIC_DisableIRQ() 函数是中断失能函数。其声明如下:

void HAL_NVIC_EnableIRQ(IRQn_Type IRQn);

  其中,参数 IRQn中断号,可以选择范围:IRQn_Type 定义的枚举类型,定义在 stm32f407xx.h。

5.5、系统复位函数

  HAL_NVIC_SystemReset() 函数是系统复位函数。其声明如下:

void HAL_NVIC_SystemReset(void);

标签:控制器,优先级,中断,08,global,NVIC,IRQn,Interrupt
From: https://www.cnblogs.com/kurome/p/18050420

相关文章

  • 08. 场景加载
    awaitable关键字本节涉及到场景的加载和卸载,在勇士传说中,我们使用协程的方式来加载和卸载场景,在本节使用了unity2023.3最新的特性awaitableawaitable具体是啥,我也不太清楚,见下图加载场景在上一节中,我们监听了LoadRoomEvent事件,成功调用了SceneLoadManager.OnLoadRoom......
  • AT_arc083_b [ABC074D] Restoring Road Network 题解
    难度虚高,建议评橙/黄qwq。首先我们发现这是一道最短路问题,且\(N\le300\),于是采取floyd算法解决。具体地,我们分情况分类讨论。令我们当前枚举到的最短路径起点为\(i\),终点为\(j\),中转点为\(k\),输入的矩阵为\(dis\)。若\(dis_{i,j}>dis_{i,k}+dis_{k,j}\),则一定无......
  • 【题解】「HDU 7084」Pty loves string
    CQBZOJHDU7084不难想到把最终在\(S\)从中间分开,就变成了前后两个broder拼起来。考场重现:直接把所有的broder求出来,将相同长度的broder的下标存在一起,然后暴力匹配,最后还没来及优化。考场代码(除了fail树,其她其实都挺逼近正解正解是建出fail树(甚至搞忘还有这东......
  • Java流程控制08:For循环详解
     For循环:条件.for1.虽然所有循环结构都可以用while或者do...while表示,但Java提供了另一种语句----->for循环,使一些循环结构变得更加简单。2.for循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环机构。 3.for循环执行的次数是在执行前就确定的......
  • SC5307A SC5308A丨6 GHz射频下变频器
    产品简介:频率范围:100kHz至6GHz更多信息请加weixin-pt890111获取 SC5307A和SC5308A是高性能三级超外差下变频器,旨在满足诸如射频仪器,无线通信,卫星链路,软件定义无线电和信号智能等要求苛刻的应用。两个模块的输入射频频率范围为D至6GHz,可选IF带宽为80MHz,160MHz和320MHz。......
  • SC5407A SC5408A丨6 GHz射频上变频器
    产品简介:频率范围:100kHz至6GHz;在10kHz偏移,1GHz载波时,低残余相位噪声<-100dBc/Hz更多信息请加weixin-pt890111获取 SC5407A和SC5408A是高性能三级外差上变频器。输入射频频率范围从DC到6GHz,模块具有80MHz,160MHz和320MHz的可选IF带宽。每个模块都使用YIG振荡器作......
  • P8085 [COCI2011-2012#4] KRIPTOGRAM 题解
    P8085[COCI2011-2012#4]KRIPTOGRAM题解本文原发布于2024-02-07洛谷题库P8085[COCI2011-2012#4]KRIPTOGRAM题解区,现于2024-2-29转载至博客园思路解析这道题目的主要难点在于如何判断明文中形如\(\texttt{abcb}\)的子串可以和密文\(\texttt{bcac}\)匹配,因为如果......
  • P1083 [NOIP2012 提高组] 借教室
    题目链接:本题由于是对某一段区间的数统一进行删除某个数的操作,很容易想到差分。对于能否二分,有一个界定标准:状态的决策过程或者序列是否满足单调性或者可以局部舍弃性。在本题中,由于随着订单数量的增加,每天可用教室的数量一定单调下降。也即,如果前一份订单都不满足,那么之后的所......
  • MIT 6.S081入门lab4.5 Q&A(lec7)
    MIT6.S081入门lab4.5Q&A(lec7)、这部分主要是Q&A部分课程的观看笔记,因此这一部分只有课程观看笔记一、课程视频观看笔记pagtbl实验:基础知识回顾:0x800以上是DRAM,以下是DEVICE;CPU通过MMU获取地址;注意:页表自身也是存在于内存中可以从init打印出来的页表中观测到,0-0三级页表......
  • Using the HEC-RAS Controller to Add Station-Elevation Data From A Spreadsheet使
    by PaigeBrueWhenIammanipulatingstation-elevationdataforHEC-RAS,IoftendothisinMicrosoftExcel.However,itcanbetedioustocopyandpastedataforeachcross-sectionintotheGeometricDataEditor.当我为HEC-RAS操作桩号高程数据时,我经常在Micr......