出现问题场景:
作为刚接触FreeRTOS实时操作系统的菜鸟,我在练习一个程序功能:按键3按下,将LED闪烁的任务挂起;按键4按下,将LED闪烁的任务恢复到就绪。按键使用外部中断。恢复就绪的语句是
xTaskResumeFromISR(xHandleTaskLED1(该函数用于在中断中恢复一个被挂起的任务)。
两个按键的中断优先级程序如下:
/*------------------------------------------------------------------------*/
HAL_NVIC_SetPriority(EXTI3_IRQn, 2, 0); //KEY3按键中断优先级配置
HAL_NVIC_EnableIRQ(EXTI3_IRQn);
HAL_NVIC_SetPriority(EXTI4_IRQn, 3, 0); //KEY4按键中断优先级配置
HAL_NVIC_EnableIRQ(EXTI4_IRQn);
/*------------------------------------------------------------------------*/
按键3的中断优先级配置为2,按键4配置为3。按键3的挂起任务是在另一个任务中实现,按下按键3后正常将LED任务挂起。按键4的恢复任务在中断中,按下按键4出现整个系统卡死,没有任何反应。
出现问题原因:
-
在使用FreeRTOS系统时,如果想在中断中恢复一个被挂起的任务,需要使用 xTaskResumeFromISR( TaskHandle_t xTaskToResume)函数,而不是 xTaskResume(TaskHandle_t xTaskToResume) 函数。
-
当单片机芯片使用的是CM内核的MCU,官方强烈建议将NVIC的优先级分组配置为全抢占式优先级,没有响应式优先级。这样方便系统管理。我看了以下我的设置:HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4); 全为抢占式优先级,正常。
-
在系统的 FreeRTOSConfig.h 配置头文件里,定义了一个宏定义: #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 。它的意思是:用户可以在抢占式优先级为 5 - 15的中断里调用FreeRTOS的API函数(抢占式式优先级为0的中断里面不允许调用)。 仔细看,我定义的是从5-15的优先级中断可以去调用系统的API,但是上面的代码中,我把两个按键的优先级设置为2和3,已经超过了5-15的抢占式优先级范围,所以我按下按键后,调用不了恢复任务函数!
解决办法:
-
我将 #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 宏定义改为 #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 1 (因为0级抢占式优先级不允许用户使用)。这表明 在 1 - 15级的抢占式优先级范围,我的按键3和按键4的中断优先级在范围之内,可以调用系统的API函数了。这样,我的问题就解决了。