你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32 中断优先级管理

[复制链接]
STMCU小助手 发布时间:2022-4-1 15:20
01. 概述
CM4 内核支持 256 个中断,其中包含了 16 个内核中断和 240 个外部中断,并且具有256 级的可编程中断设置。但 STM32F4 并没有使用 CM4 内核的全部东西,而是只用了它的一部分。

STM32F40xx/STM32F41xx 总共有 92 个中断,STM32F42xx/STM32F43xx 则总共有 96 个中断,STM32F40xx/STM32F41xx 的 92 个中断里面,包括 10 个内核中断和 82 个可屏蔽中断,具有16级可编程的中断优先级,而我们常用的就是这82个可屏蔽中断。

02. 结构体声明
core_cm4.h文件中

  1. /** \brief  Structure type to access the Nested Vectored Interrupt Controller (NVIC).
  2. */
  3. typedef struct
  4. {
  5.   __IO uint32_t ISER[8];                 /*!< Offset: 0x000 (R/W)  Interrupt Set Enable Register           */
  6.        uint32_t RESERVED0[24];
  7.   __IO uint32_t ICER[8];                 /*!< Offset: 0x080 (R/W)  Interrupt Clear Enable Register         */
  8.        uint32_t RSERVED1[24];
  9.   __IO uint32_t ISPR[8];                 /*!< Offset: 0x100 (R/W)  Interrupt Set Pending Register          */
  10.        uint32_t RESERVED2[24];
  11.   __IO uint32_t ICPR[8];                 /*!< Offset: 0x180 (R/W)  Interrupt Clear Pending Register        */
  12.        uint32_t RESERVED3[24];
  13.   __IO uint32_t IABR[8];                 /*!< Offset: 0x200 (R/W)  Interrupt Active bit Register           */
  14.        uint32_t RESERVED4[56];
  15.   __IO uint8_t  IP[240];                 /*!< Offset: 0x300 (R/W)  Interrupt Priority Register (8Bit wide) */
  16.        uint32_t RESERVED5[644];
  17.   __O  uint32_t STIR;                    /*!< Offset: 0xE00 ( /W)  Software Trigger Interrupt Register     */
  18. }  NVIC_Type;
复制代码

STM32F4 的中断在这些寄存器的控制下有序的执行的。只有了解这些中断寄存器,才能方便的使用 STM32F4 的中断。

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

ICER[8]:
全称是:Interrupt Clear-Enable Registers,是一个中断除能寄存器组。该寄存器组与 ISER 的作用恰好相反,是用来清除某个中断的使能的。其对应位的功能,也和 ICER 一样。这里要专门设置一个 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,是一个中断优先级控制的寄存器组。这个寄存器组相当重要!STM32F4 的中断分组与这个寄存器组密切相关。IP 寄存器组由 240 个 8bit的寄存器组成,每个可屏蔽中断占用 8bit,这样总共可以表示 240 个可屏蔽中断。而 STM32F4只用到了其中的 82 个。IP[81]~IP[0]分别对应中断 81~0。而每个可屏蔽中断占用的 8bit 并没有全部使用,而是只用了高 4 位。这 4 位,又分为抢占优先级和响应优先级。抢占优先级在前,响应优先级在后。而这两个优先级各占几个位又要根据 SCB->AIRCR 中的中断分组设置来决定。

03. 中断分组
STM32F4 将中断分为 5 个组,组 0~4。该分组的设置是由 SCB->AIRCR 寄存器的 bit10~8 来定义的。

20200823164432912.png

我们就可以清楚的看到组 0~4 对应的配置关系,例如组设置为 3,那么此时所有的 82 个中断,每个中断的中断优先寄存器的高四位中的最高 3 位是抢占优先级,低 1 位是响应优先级。每个中断,你可以设置抢占优先级为 0~7,响应优先级为 1 或 0。抢占优先级的级别高于响应优先级。而数值越小所代表的优先级就越高。

这里需要注意两点:第一,如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行;第二,高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。而抢占优先级相同的中断,高优先级的响应优先级不可以打断低响应优先级的中断。

结合实例说明一下:假定设置中断优先级组为 2,然后设置中断 3(RTC_WKUP 中断)的抢占优先级为 2,响应优先级为 1。中断 6(外部中断 0)的抢占优先级为 3,响应优先级为 0。中断 7(外部中断 1)的抢占优先级为 2,响应优先级为 0。那么这 3 个中断的优先级顺序为:中断 7>中断 3>中断 6。

上面例子中的中断 3 和中断 7 都可以打断中断 6 的中断。而中断 7 和中断 3 却不可以相互打断!

04. 相关类型
misc.h文件

NVIC_InitTypeDef类型

  1. /**
  2.   * @brief  NVIC Init Structure definition  
  3.   */

  4. typedef struct
  5. {
  6.   uint8_t NVIC_IRQChannel;                    /*!< Specifies the IRQ channel to be enabled or disabled.
  7.                                                    This parameter can be an enumerator of @ref IRQn_Type
  8.                                                    enumeration (For the complete STM32 Devices IRQ Channels
  9.                                                    list, please refer to stm32f4xx.h file) */

  10.   uint8_t NVIC_IRQChannelPreemptionPriority;  /*!< Specifies the pre-emption priority for the IRQ channel
  11.                                                    specified in NVIC_IRQChannel. This parameter can be a value
  12.                                                    between 0 and 15 as described in the table @ref MISC_NVIC_Priority_Table
  13.                                                    A lower priority value indicates a higher priority */

  14.   uint8_t NVIC_IRQChannelSubPriority;         /*!< Specifies the subpriority level for the IRQ channel specified
  15.                                                    in NVIC_IRQChannel. This parameter can be a value
  16.                                                    between 0 and 15 as described in the table @ref MISC_NVIC_Priority_Table
  17.                                                    A lower priority value indicates a higher priority */

  18.   FunctionalState NVIC_IRQChannelCmd;         /*!< Specifies whether the IRQ channel defined in NVIC_IRQChannel
  19.                                                    will be enabled or disabled.
  20.                                                    This parameter can be set either to ENABLE or DISABLE */   
  21. } NVIC_InitTypeDef;
复制代码

MISC_Vector_Table_Base
  1. /** @defgroup MISC_Vector_Table_Base
  2.   * @{
  3.   */

  4. #define NVIC_VectTab_RAM             ((uint32_t)0x20000000)
  5. #define NVIC_VectTab_FLASH           ((uint32_t)0x08000000)
  6. #define IS_NVIC_VECTTAB(VECTTAB) (((VECTTAB) == NVIC_VectTab_RAM) || \
  7.                                   ((VECTTAB) == NVIC_VectTab_FLASH))
复制代码

MISC_System_Low_Power

  1. /** @defgroup MISC_System_Low_Power
  2.   * @{
  3.   */

  4. #define NVIC_LP_SEVONPEND            ((uint8_t)0x10)
  5. #define NVIC_LP_SLEEPDEEP            ((uint8_t)0x04)
  6. #define NVIC_LP_SLEEPONEXIT          ((uint8_t)0x02)
  7. #define IS_NVIC_LP(LP) (((LP) == NVIC_LP_SEVONPEND) || \
  8.                         ((LP) == NVIC_LP_SLEEPDEEP) || \
  9.                         ((LP) == NVIC_LP_SLEEPONEXIT))
复制代码

MISC_Preemption_Priority_Group


  1. /** @defgroup MISC_Preemption_Priority_Group
  2.   * @{
  3.   */

  4. #define NVIC_PriorityGroup_0         ((uint32_t)0x700) /*!< 0 bits for pre-emption priority
  5.                                                             4 bits for subpriority */
  6. #define NVIC_PriorityGroup_1         ((uint32_t)0x600) /*!< 1 bits for pre-emption priority
  7.                                                             3 bits for subpriority */
  8. #define NVIC_PriorityGroup_2         ((uint32_t)0x500) /*!< 2 bits for pre-emption priority
  9.                                                             2 bits for subpriority */
  10. #define NVIC_PriorityGroup_3         ((uint32_t)0x400) /*!< 3 bits for pre-emption priority
  11.                                                             1 bits for subpriority */
  12. #define NVIC_PriorityGroup_4         ((uint32_t)0x300) /*!< 4 bits for pre-emption priority
  13.                                                             0 bits for subpriority */

  14. #define IS_NVIC_PRIORITY_GROUP(GROUP) (((GROUP) == NVIC_PriorityGroup_0) || \
  15.                                        ((GROUP) == NVIC_PriorityGroup_1) || \
  16.                                        ((GROUP) == NVIC_PriorityGroup_2) || \
  17.                                        ((GROUP) == NVIC_PriorityGroup_3) || \
  18.                                        ((GROUP) == NVIC_PriorityGroup_4))

  19. #define IS_NVIC_PREEMPTION_PRIORITY(PRIORITY)  ((PRIORITY) < 0x10)

  20. #define IS_NVIC_SUB_PRIORITY(PRIORITY)  ((PRIORITY) < 0x10)

  21. #define IS_NVIC_OFFSET(OFFSET)  ((OFFSET) < 0x000FFFFF)
复制代码

MISC_SysTick_clock_sourc

  1. /** @defgroup MISC_SysTick_clock_source
  2.   * @{
  3.   */

  4. #define SysTick_CLKSource_HCLK_Div8    ((uint32_t)0xFFFFFFFB)
  5. #define SysTick_CLKSource_HCLK         ((uint32_t)0x00000004)
  6. #define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \
  7.                                        ((SOURCE) == SysTick_CLKSource_HCLK_Div8))
复制代码

中断名字(stm32f4xx.h)

  1. /**
  2. * @brief STM32F4XX Interrupt Number Definition, according to the selected device
  3. *        in @ref Library_configuration_section
  4. */
  5. typedef enum IRQn
  6. {
  7. /******  Cortex-M4 Processor Exceptions Numbers ****************************************************************/
  8.   NonMaskableInt_IRQn         = -14,    /*!< 2 Non Maskable Interrupt                                          */
  9.   MemoryManagement_IRQn       = -12,    /*!< 4 Cortex-M4 Memory Management Interrupt                           */
  10.   BusFault_IRQn               = -11,    /*!< 5 Cortex-M4 Bus Fault Interrupt                                   */
  11.   UsageFault_IRQn             = -10,    /*!< 6 Cortex-M4 Usage Fault Interrupt                                 */
  12.   SVCall_IRQn                 = -5,     /*!< 11 Cortex-M4 SV Call Interrupt                                    */
  13.   DebugMonitor_IRQn           = -4,     /*!< 12 Cortex-M4 Debug Monitor Interrupt                              */
  14.   PendSV_IRQn                 = -2,     /*!< 14 Cortex-M4 Pend SV Interrupt                                    */
  15.   SysTick_IRQn                = -1,     /*!< 15 Cortex-M4 System Tick Interrupt                                */
  16. /******  STM32 specific Interrupt Numbers **********************************************************************/
  17.   WWDG_IRQn                   = 0,      /*!< Window WatchDog Interrupt                                         */
  18.   PVD_IRQn                    = 1,      /*!< PVD through EXTI Line detection Interrupt                         */
  19.   TAMP_STAMP_IRQn             = 2,      /*!< Tamper and TimeStamp interrupts through the EXTI line             */
  20.   RTC_WKUP_IRQn               = 3,      /*!< RTC Wakeup interrupt through the EXTI line                        */
  21.   FLASH_IRQn                  = 4,      /*!< FLASH global Interrupt                                            */
  22.   RCC_IRQn                    = 5,      /*!< RCC global Interrupt                                              */
  23.   EXTI0_IRQn                  = 6,      /*!< EXTI Line0 Interrupt                                              */
  24.   EXTI1_IRQn                  = 7,      /*!< EXTI Line1 Interrupt                                              */
  25.   EXTI2_IRQn                  = 8,      /*!< EXTI Line2 Interrupt                                              */
  26.   EXTI3_IRQn                  = 9,      /*!< EXTI Line3 Interrupt                                              */
  27.   EXTI4_IRQn                  = 10,     /*!< EXTI Line4 Interrupt                                              */
  28.   DMA1_Stream0_IRQn           = 11,     /*!< DMA1 Stream 0 global Interrupt                                    */
  29.   DMA1_Stream1_IRQn           = 12,     /*!< DMA1 Stream 1 global Interrupt                                    */
  30.   DMA1_Stream2_IRQn           = 13,     /*!< DMA1 Stream 2 global Interrupt                                    */
  31.   DMA1_Stream3_IRQn           = 14,     /*!< DMA1 Stream 3 global Interrupt                                    */
  32.   DMA1_Stream4_IRQn           = 15,     /*!< DMA1 Stream 4 global Interrupt                                    */
  33.   DMA1_Stream5_IRQn           = 16,     /*!< DMA1 Stream 5 global Interrupt                                    */
  34.   DMA1_Stream6_IRQn           = 17,     /*!< DMA1 Stream 6 global Interrupt                                    */
  35.   ADC_IRQn                    = 18,     /*!< ADC1, ADC2 and ADC3 global Interrupts                             */

  36. #if defined(STM32F40_41xxx)
  37.   CAN1_TX_IRQn                = 19,     /*!< CAN1 TX Interrupt                                                 */
  38.   CAN1_RX0_IRQn               = 20,     /*!< CAN1 RX0 Interrupt                                                */
  39.   CAN1_RX1_IRQn               = 21,     /*!< CAN1 RX1 Interrupt                                                */
  40.   CAN1_SCE_IRQn               = 22,     /*!< CAN1 SCE Interrupt                                                */
  41.   EXTI9_5_IRQn                = 23,     /*!< External Line[9:5] Interrupts                                     */
  42.   TIM1_BRK_TIM9_IRQn          = 24,     /*!< TIM1 Break interrupt and TIM9 global interrupt                    */
  43.   TIM1_UP_TIM10_IRQn          = 25,     /*!< TIM1 Update Interrupt and TIM10 global interrupt                  */
  44.   TIM1_TRG_COM_TIM11_IRQn     = 26,     /*!< TIM1 Trigger and Commutation Interrupt and TIM11 global interrupt */
  45.   TIM1_CC_IRQn                = 27,     /*!< TIM1 Capture Compare Interrupt                                    */
  46.   TIM2_IRQn                   = 28,     /*!< TIM2 global Interrupt                                             */
  47.   TIM3_IRQn                   = 29,     /*!< TIM3 global Interrupt                                             */
  48.   TIM4_IRQn                   = 30,     /*!< TIM4 global Interrupt                                             */
  49.   I2C1_EV_IRQn                = 31,     /*!< I2C1 Event Interrupt                                              */
  50.   I2C1_ER_IRQn                = 32,     /*!< I2C1 Error Interrupt                                              */
  51.   I2C2_EV_IRQn                = 33,     /*!< I2C2 Event Interrupt                                              */
  52.   I2C2_ER_IRQn                = 34,     /*!< I2C2 Error Interrupt                                              */
  53.   SPI1_IRQn                   = 35,     /*!< SPI1 global Interrupt                                             */
  54.   SPI2_IRQn                   = 36,     /*!< SPI2 global Interrupt                                             */
  55.   USART1_IRQn                 = 37,     /*!< USART1 global Interrupt                                           */
  56.   USART2_IRQn                 = 38,     /*!< USART2 global Interrupt                                           */
  57.   USART3_IRQn                 = 39,     /*!< USART3 global Interrupt                                           */
  58.   EXTI15_10_IRQn              = 40,     /*!< External Line[15:10] Interrupts                                   */
  59.   RTC_Alarm_IRQn              = 41,     /*!< RTC Alarm (A and B) through EXTI Line Interrupt                   */
  60.   OTG_FS_WKUP_IRQn            = 42,     /*!< USB OTG FS Wakeup through EXTI line interrupt                     */
  61.   TIM8_BRK_TIM12_IRQn         = 43,     /*!< TIM8 Break Interrupt and TIM12 global interrupt                   */
  62.   TIM8_UP_TIM13_IRQn          = 44,     /*!< TIM8 Update Interrupt and TIM13 global interrupt                  */
  63.   TIM8_TRG_COM_TIM14_IRQn     = 45,     /*!< TIM8 Trigger and Commutation Interrupt and TIM14 global interrupt */
  64.   TIM8_CC_IRQn                = 46,     /*!< TIM8 Capture Compare Interrupt                                    */
  65.   DMA1_Stream7_IRQn           = 47,     /*!< DMA1 Stream7 Interrupt                                            */
  66.   FSMC_IRQn                   = 48,     /*!< FSMC global Interrupt                                             */
  67.   SDIO_IRQn                   = 49,     /*!< SDIO global Interrupt                                             */
  68.   TIM5_IRQn                   = 50,     /*!< TIM5 global Interrupt                                             */
  69.   SPI3_IRQn                   = 51,     /*!< SPI3 global Interrupt                                             */
  70.   UART4_IRQn                  = 52,     /*!< UART4 global Interrupt                                            */
  71.   UART5_IRQn                  = 53,     /*!< UART5 global Interrupt                                            */
  72.   TIM6_DAC_IRQn               = 54,     /*!< TIM6 global and DAC1&2 underrun error  interrupts                 */
  73.   TIM7_IRQn                   = 55,     /*!< TIM7 global interrupt                                             */
  74.   DMA2_Stream0_IRQn           = 56,     /*!< DMA2 Stream 0 global Interrupt                                    */
  75.   DMA2_Stream1_IRQn           = 57,     /*!< DMA2 Stream 1 global Interrupt                                    */
  76.   DMA2_Stream2_IRQn           = 58,     /*!< DMA2 Stream 2 global Interrupt                                    */
  77.   DMA2_Stream3_IRQn           = 59,     /*!< DMA2 Stream 3 global Interrupt                                    */
  78.   DMA2_Stream4_IRQn           = 60,     /*!< DMA2 Stream 4 global Interrupt                                    */
  79.   ETH_IRQn                    = 61,     /*!< Ethernet global Interrupt                                         */
  80.   ETH_WKUP_IRQn               = 62,     /*!< Ethernet Wakeup through EXTI line Interrupt                       */
  81.   CAN2_TX_IRQn                = 63,     /*!< CAN2 TX Interrupt                                                 */
  82.   CAN2_RX0_IRQn               = 64,     /*!< CAN2 RX0 Interrupt                                                */
  83.   CAN2_RX1_IRQn               = 65,     /*!< CAN2 RX1 Interrupt                                                */
  84.   CAN2_SCE_IRQn               = 66,     /*!< CAN2 SCE Interrupt                                                */
  85.   OTG_FS_IRQn                 = 67,     /*!< USB OTG FS global Interrupt                                       */
  86.   DMA2_Stream5_IRQn           = 68,     /*!< DMA2 Stream 5 global interrupt                                    */
  87.   DMA2_Stream6_IRQn           = 69,     /*!< DMA2 Stream 6 global interrupt                                    */
  88.   DMA2_Stream7_IRQn           = 70,     /*!< DMA2 Stream 7 global interrupt                                    */
  89.   USART6_IRQn                 = 71,     /*!< USART6 global interrupt                                           */
  90.   I2C3_EV_IRQn                = 72,     /*!< I2C3 event interrupt                                              */
  91.   I2C3_ER_IRQn                = 73,     /*!< I2C3 error interrupt                                              */
  92.   OTG_HS_EP1_OUT_IRQn         = 74,     /*!< USB OTG HS End Point 1 Out global interrupt                       */
  93.   OTG_HS_EP1_IN_IRQn          = 75,     /*!< USB OTG HS End Point 1 In global interrupt                        */
  94.   OTG_HS_WKUP_IRQn            = 76,     /*!< USB OTG HS Wakeup through EXTI interrupt                          */
  95.   OTG_HS_IRQn                 = 77,     /*!< USB OTG HS global interrupt                                       */
  96.   DCMI_IRQn                   = 78,     /*!< DCMI global interrupt                                             */
  97.   CRYP_IRQn                   = 79,     /*!< CRYP crypto global interrupt                                      */
  98.   HASH_RNG_IRQn               = 80,     /*!< Hash and Rng global interrupt                                     */
  99.   FPU_IRQn                    = 81      /*!< FPU global interrupt                                              */
  100. #endif /* STM32F40_41xxx */
复制代码

05. 相关函数
  1. /* Exported macro ------------------------------------------------------------*/
  2. /* Exported functions --------------------------------------------------------*/

  3. void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
  4. void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
  5. void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);
  6. void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);
  7. void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource);
复制代码


收藏 评论0 发布时间:2022-4-1 15:20

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版