理解 FreeRTOS 中的 configMAX_SYSCALL_INTERRUPT_PRIORITY 和 configKERNEL_INTERRUPT_PRIORITY
RTOS 中断嵌套方案把可用的中断优先级分成两组一组会被 RTOS 临界区屏蔽另一组不会被临界区屏蔽。configMAX_SYSCALL_INTERRUPT_PRIORITY是两组的分界。在 Cortex-M 上数值越小逻辑优先级越高。逻辑优先级高于这条分界的中断不会被taskENTER_CRITICAL()屏蔽这些中断里不能调用 FreeRTOS API。数值等于这条分界的中断会被屏蔽可以调用以FromISR结尾的 API。理解 FreeRTOS的configMAX_SYSCALL_INTERRUPT_PRIORITY和configKERNEL_INTERRUPT_PRIORITY需要从中断优先级管理和实时操作系统的工作原理入手。以下是对这两个配置参数的解释configMAX_SYSCALL_INTERRUPT_PRIORITY定义configMAX_SYSCALL_INTERRUPT_PRIORITY是仍允许调用中断安全 FreeRTOS API 的最高逻辑优先级。写入BASEPRI时使用已经按优先级位数左移、与 NVIC 优先级寄存器高位对齐的数值。目的临界区期间屏蔽这条线以及逻辑优先级更低的中断避免这些中断在内核修改内部数据时再次进入并调用 API造成竞态或数据损坏。逻辑优先级更高的中断不会被这段临界区屏蔽因此它们的处理函数里不能调用任何 FreeRTOS API。使用中断处理函数需要调用FromISRAPI 时用NVIC_SetPriority()设置的优先级数值必须大于或等于configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY。configKERNEL_INTERRUPT_PRIORITY定义configKERNEL_INTERRUPT_PRIORITY是 SysTick 和 PendSV 的优先级同样是左移后写入系统异常优先级寄存器的数值。目的把节拍中断和任务切换放在最低逻辑优先级使已经嵌套的中断都退出后再切换任务。应用中断可以抢占 SysTick。使用这个值设为硬件最低逻辑优先级。优先级寄存器 8 位都实现时最低优先级的数值是 255。只实现高 4 位时最低优先级是 15 左移 4 位即0xF0。未实现的低 4 位写 0 或写 1 效果相同所以0xF0和 255 都可以。示例配置在 Cortex-M 内核中假如有 8 级优先级取值范围是 07。数值 0 是最高逻辑优先级数值 7 是最低逻辑优先级。对于实现了 4 位优先级NVIC_SetPriority()使用 015的 ARM Cortex-M#define configPRIO_BITS 4 #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15 #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 /* 0xF0SysTick / PendSV */ #define configKERNEL_INTERRUPT_PRIORITY \ ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY (8 - configPRIO_BITS) ) /* 0x50。高 4 位必须是 5不能把宏直接定义成 5 */ #define configMAX_SYSCALL_INTERRUPT_PRIORITY \ ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY (8 - configPRIO_BITS) )在这个例子中对cortex来说0最高configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY为 5对应的configMAX_SYSCALL_INTERRUPT_PRIORITY为0x50。NVIC 优先级为 5、6、7、…、15 的中断可以调用FromISR函数。configLIBRARY_LOWEST_INTERRUPT_PRIORITY为 15对应的configKERNEL_INTERRUPT_PRIORITY为0xF0。SysTick 和 PendSV 处于最低逻辑优先级其他中断可以抢占它们串口中断优先级设为 6 时串口中断可以调用FromISR函数。定时器中断优先级设为 4 时定时器中断处理函数不能调用FromISR函数重要注意事项优先级编号ARM Cortex-M 用较小的数值表示较高的逻辑优先级。NVIC_SetPriority()传入未移位的优先级。上面两个 config 宏必须是左移到优先级寄存器高位之后的值并且configMAX_SYSCALL_INTERRUPT_PRIORITY不能为 0。中断安全 API中断里只能调用以FromISR结尾的 FreeRTOS API而且该中断的逻辑优先级不能高于configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY。优先级分组实现的优先级位全部用作抢占优先级不要再划分子优先级。配置一致性中断优先级、configMAX_SYSCALL_INTERRUPT_PRIORITY和configKERNEL_INTERRUPT_PRIORITY使用同一套位数和移位方式。