Skip to content

中断管理

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。

image-20250118214843632

SysTick是FreeRTOS的系统时基,PendSV中断处理任务的调度,FreeRTOS中PendSVSysTick被设置最低优先级 15,保证系统任务切换不会阻塞系统其他中断的响应

10.3 中断屏蔽寄存器

三个中断屏蔽寄存器,分别为 PRIMASK、 FAULTMASK 和BASEPRI , FreeRTOS所使用的中断管理就是利用的BASEPRI这个寄存器 。

image-20250118215217258

BASEPRI 寄存器的使用:
例如:在寄存器中写入 0x50,由于低四位不用,则实际表示的是中断优先级在 5-15 内的均被屏蔽,0-4 的中断优先级正常执行。

同时值得注意的是FreeRTOS只管理优先级 5-15的中断,所以中断服务函数的优先级应在此范围。

image-20250118215524089

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