中断管理
10.1 中断优先级¶
中断优先级分组一共有 5 种分配方式:
优先级分组 | 抢占优先级 | 子优先级 | 优先级配置寄存器高 4 位 |
---|---|---|---|
NVIC_PriorityGroup_0 | 0 级抢占优先级 | 0-15 级子优先级 | 0bit 用于抢占优先级,4bit 用于子优先级 |
NVIC_PriorityGroup_1 | 0-1 级抢占优先级 | 0-7 级子优先级 | 1bit 用于抢占优先级,3bit 用于子优先级 |
NVIC_PriorityGroup_2 | 0-3 级抢占优先级 | 0-3 级子优先级 | 2bit 用于抢占优先级,2bit 用于子优先级 |
NVIC_PriorityGroup_3 | 0-7 级抢占优先级 | 0-1 级子优先级 | 3bit 用于抢占优先级,1bit 用于子优先级 |
NVIC_PriorityGroup_4 | 0-15 级抢占优先级 | 0 级子优先级 | 4bit 用于抢占优先级,0bit 用于子优先级 |
其中FreeRTOS的优先级分组为NVIC_PriorityGroup_4
,将所有优先级位指定为抢占优先级位,方便FreeRTOS管理。优先级分组的设置位置在HAL_Init()
函数中,STM32CubeMX默认的优先级分组NVIC_PriorityGroup_4
,在裸机程序中我们可以自由选择优先级分组,但当我们使用FreeRTOS时,便只有NVIC_PriorityGroup_4
一个选项。
关于优先级有一点需要注意, 中断优先级数值(0-15)越小越优先,任务优先级数值(0-31)越大越优先
10.2 中断优先级寄存器¶
三个系统中断优先级配置寄存器,分别为 SHPR1(0xE000ED18)、 SHPR2(0xE000ED1C)、 SHPR3(0xE000ED20),每一个中断寄存器四个字节,32Bit。
SysTick
是FreeRTOS的系统时基,PendSV
中断处理任务的调度,FreeRTOS中PendSV
和SysTick
被设置最低优先级 15,保证系统任务切换不会阻塞系统其他中断的响应
10.3 中断屏蔽寄存器¶
三个中断屏蔽寄存器,分别为 PRIMASK、 FAULTMASK 和BASEPRI , FreeRTOS所使用的中断管理就是利用的BASEPRI这个寄存器 。
BASEPRI
寄存器的使用:
例如:在寄存器中写入 0x50
,由于低四位不用,则实际表示的是中断优先级在 5-15 内的均被屏蔽,0-4 的中断优先级正常执行。
同时值得注意的是FreeRTOS只管理优先级 5-15的中断,所以中断服务函数的优先级应在此范围。
10.4 中断管理函数¶
C
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0)
/* 关中断 */
portFORCE_INLINE static void vPortRaiseBASEPRI( void )
{
uint32_t ulNewBASEPRI;
__asm volatile
(
" mov %0, %1 \n" \
" msr basepri, %0 \n" \
" isb \n" \
" dsb \n" \
:"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
);
}
/* 开中断 */
portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
{
__asm volatile
(
" msr basepri, %0 " :: "r" ( ulNewMaskValue ) : "memory"
);
}