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]分配情况分配结果
01110:40位抢占优先级,4位响应优先级
11101:31位抢占优先级,3位响应优先级
21012:22位抢占优先级,2位响应优先级
31003:13位抢占优先级,1位响应优先级
40114:04位抢占优先级,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 */
asrt_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);
/* U systick as time ba source and configure 1ms tick (default clock after Ret 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]; /*!< Offt: 0x000 (R/W) Interrupt Set Enable Register */
uint32_t RESERVED0[24U];
__IOM uint32_t ICER[8U]; /*!< Offt: 0x080 (R/W) Interrupt Clear Enable Register */
uint32_t RSERVED1[24U];
__IOM uint32_t ISPR[8U]; /*!< Offt: 0x100 (R/W) Interrupt Set Pending Register */
uint32_t RESERVED2[24U];
__IOM uint32_t ICPR[8U]; /*!< Offt: 0x180 (R/W) Interrupt Clear Pending Register */
uint32_t RESERVED3[24U];
字体的演变__IOM uint32_t IABR[8U]; /*!< Offt: 0x200 (R/W) Interrupt Active bit Register */
uint32_t RESERVED4[56U];
__IOM uint8_t IP[240U]; /*!< Offt: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */
uint32_t RESERVED5[644U];
__OM uint32_t STIR; /*!< Offt: 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, plea 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 */
asrt_param(IS_NVIC_SUB_PRIORITY(SubPriority));
asrt_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 */
asrt_param(IS_NVIC_DEVICE_IRQ(IRQn));
/
* Enable interrupt */
NVIC_EnableIRQ(IRQn);
}