STM32标准库开发的中断优先级分组问题:为什么需要设置优先级分组
学习FreeRTOS时,发现开启串口中断后系统无法正常运行,本以为是FreeRTOS里关于中断的一些部分没有配置好,结果排查了一圈,最后发现是没有设置优先级分组的问题。
FreeRTOS官方建议调用NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4)将优先级分组设置为分组4,而我认为系统上电后的默认状态与分组4是等效的,因此没有调用这个函数,但并非如此。
本人理解:
由官方手册可以知道,M3内核将8位优先级寄存器分为两个部分:抢占优先级和子优先级,优先级分组由SCB_AIRCR寄存器里的8:10位控制,这三位决定了优先级寄存器的8位中,抢占优先级和子优先级各占几位,对应关系也在手册里给出。


可以发现,这三位的值就是抢占优先级和子优先级的分界点。这三位上电后的复位值为0,即优先级寄存器的八位中,第0位是子优先级,1:7位是抢占优先级,而STM32F1只实现了八位中的高四位,因此上电后这四位都是抢占优先级,与分组4是等效的。
问题:
上面错误的地方在于,程序有时需要用到SCB_AIRCR寄存器的值,如果不写入正确的值,后面用到时就会出现问题。
例如,在NVIC_Init()函数中,需要将输入的优先级换算为实际写入寄存器内的值,这里就要用到SCB_AIRCR寄存器内的值,如果是0,那么计算出的是有问题的,并不会设置为预期的优先级。
点击查看代码
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
{
uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));
assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority));
assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));
if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)
{
/* Compute the Corresponding IRQ Priority --------------------------------*/
tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;
tmppre = (0x4 - tmppriority);
tmpsub = tmpsub >> tmppriority;
tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;
tmppriority |= NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub;
tmppriority = tmppriority << 0x04;
NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;
/* Enable the Selected IRQ Channels --------------------------------------*/
NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
(uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
}
else
{
/* Disable the Selected IRQ Channels -------------------------------------*/
NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
(uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
}
}

浙公网安备 33010602011771号