STM32-NVIC中斷優先級分組-中斷優先級設置


STM32-中斷優先級管理NVIC

1.NVIC中斷優先級分組

NVIC的全稱是Nested vectoredinterrupt controller,即嵌套向量中斷控制器。STM32F中文參考手冊中搜索向量表可以找到相應的中斷說明。
CM4/CM7 內核支持256個中斷,其中包含了16個內核中斷和240個外部中斷,並且具有256級的可編程中斷設置。
STM32F4/F7並沒有使用CM4內核的全部東西,而是只用了它的一部分。
STM32F40xx/STM32F41xx總共有92個中斷。10個內核中斷,82個可屏蔽中斷。
STM32F42xx/STM32F43xx則總共有97個中斷。10個內核中斷,87個可屏蔽中斷。
STM32F76x總共118個中斷,10個內核中斷,108個可屏蔽中斷。

STM32具有16級可編程的中斷優先級,而我們常用的就是這些可屏蔽中斷。

幾十個中斷,怎么管理?

首先,對STM32中斷進行分組,組0~4。同時,對每個中斷設置一個搶占優先級和一個響應優先級值。

分組配置是在寄存器SCB->AIRCR中配置: IP bit[7:4]有4位,2^4=16,所以說它們的優先級可以有16個值,這時候如果是2位搶占優先級,那么它的值可能為0、1、2、3。也就是搶占優先級可以取0到3 。首先進行分組來決定幾位搶占優先級、幾位響應優先級。數越小它的優先級越高。

AIRCR[10:8] IP bit[7:4]分配情況 分配結果
0 111 0:4 0位搶占優先級,4位響應優先級
1 110 1:3 1位搶占優先級,3位響應優先級
2 101 2:2 2位搶占優先級,2位響應優先級
3 100 3:1 3位搶占優先級,1位響應優先級
4 011 4:0 4位搶占優先級,0位響應優先級

搶占優先級 & 響應優先級區別:

高優先級的搶占優先級是可以打斷正在進行的低搶占優先級中斷的。搶占決定了是否能打斷別人。
搶占優先級相同的中斷,高響應優先級不可以打斷低響應優先級的中斷。
搶占優先級相同的中斷,當兩個中斷同時發生的情況下,哪個響應優先級高,哪個先執行。
如果兩個中斷的搶占優先級和響應優先級都是一樣的話,則看哪個中斷先發生就先執行;

舉例:

假定設置中斷優先級組為2,然后設置

中斷3(RTC中斷)的搶占優先級為2,響應優先級為1。

中斷6(外部中斷0)的搶占優先級為3,響應優先級為0

中斷7(外部中斷1)的搶占優先級為2,響應優先級為0。

那么這3個中斷的優先級順序為:中斷7>中斷3>中斷6。

一般情況下,系統代碼執行過程中,只設置一次中斷優先級分組,比如分組2,設置好分組之后一般不會再改變分組。隨意改變分組會導致中斷管理混亂,程序出現意想不到的執行結果。

中斷優先級分組函數位於HALLIB中的stm32f7xx_hal_cortex.c:void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup);

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); } 

可以找到IS_NVIC_PRIORITY_GROUP的定義,進而確定PriorityGroup參數怎么寫。

#define IS_NVIC_PRIORITY_GROUP(GROUP) (((GROUP) == NVIC_PRIORITYGROUP_0) || \ ((GROUP) == NVIC_PRIORITYGROUP_1) || \ ((GROUP) == NVIC_PRIORITYGROUP_2) || \ ((GROUP) == NVIC_PRIORITYGROUP_3) || \ ((GROUP) == NVIC_PRIORITYGROUP_4)) 

在stm32f7xx_hal.c中可以找到HAL_Init函數:其中HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);可以看到中斷分組為2 。

HAL_StatusTypeDef HAL_Init(void) { /* Configure Flash prefetch and Instruction cache through ART accelerator */ #if (ART_ACCLERATOR_ENABLE != 0) __HAL_FLASH_ART_ENABLE(); #endif /* ART_ACCLERATOR_ENABLE */ /* Set Interrupt Group Priority */ HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2); /* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */ HAL_InitTick(TICK_INT_PRIORITY); /* Init the low level hardware */ HAL_MspInit(); /* Return function status */ return HAL_OK; } 

2.NVIC中斷優先級設置

分組設置好之后,怎么設置單個中斷的搶占優先級和響應優先級?

中斷設置相關寄存器:

_IO uint8_t IP[240]; //中斷優先級控制的寄存器組

_IO uint32_t ISER[8]; //中斷使能寄存器組
_IO uint32_t ICER[8]; //中斷失能寄存器組
_IO uint32_t ISPR[8]; //中斷掛起寄存器組
_IO uint32_t ICPR[8]; //中斷解掛寄存器組
_IO uint32_t IABR[8]; //中斷激活標志位寄存器組

位於core_cm7.h中:NVIC_Type結構體中成員變量就是那些寄存器。

/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). */ typedef struct { __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ uint32_t RESERVED0[24U]; __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ uint32_t RSERVED1[24U]; __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ uint32_t RESERVED2[24U]; __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ uint32_t RESERVED3[24U]; __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ uint32_t RESERVED4[56U]; __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ uint32_t RESERVED5[644U]; __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ } NVIC_Type; 

對於每個中斷怎么設置優先級?

中斷優先級控制的寄存器組:IP[240],全稱是:Interrupt Priority Registers

240個8位寄存器,每個中斷使用一個寄存器來確定優先級。STM32F40x系列一共82個可屏蔽中斷,使用IP[81]~IP[0]。

每個IP寄存器的高4位用來設置搶占和響應優先級(根據分組),低4位沒有用到。

在stm32f7xx_hal_cortex.c可找到:

/** * @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 (stm32f7xxxx.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 = 0x00; /* 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)); } 

中斷優先級設置步驟:

  • 系統運行后在HAL_Init函數中設置中斷優先級分組。調用函數:
    HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);
    //中斷優先級分組2 整個系統執行過程中,只設置一次中斷分組。
  • 針對每個中斷,設置對應的搶占優先級和響應優先級:
    void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t
    PreemptPriority, uint32_t SubPriority);
  • 使能中斷通道:
    void HAL_NVIC_EnableIRQ(IRQn_Type IRQn);
void HAL_NVIC_EnableIRQ(IRQn_Type IRQn) { /* Check the parameters */ assert_param(IS_NVIC_DEVICE_IRQ(IRQn)); /* Enable interrupt */ NVIC_EnableIRQ(IRQn); } 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM