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]分配情况01111110210131004011
0:41:32:23:14:0
分配结果
0位抢占优先级,4位响应优先级1位抢占优先级,3位响应优先级2位抢占优先级,2位响应优先级3位抢占优先级,1位响应优先级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_tPreemptPriority, 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);}
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- efsc.cn 版权所有 赣ICP备2024042792号-1
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务