前言
工作中我们有时需要暂停某个任务的运行,过一段时间后恢复运行。挂起和删除的本质区别是:挂起任务堆栈和任务控制块的数据不会被删除。
1、任务挂起和恢复API函数介绍
函数 | 描述 |
---|---|
vTaskSuspend() | 挂起一个任务 |
vTaskResume() | 恢复一个任务的运行 |
xTaskResumeFromISR() | 中断服务函数中恢复一个任务的运行 |
- A任务处在运行态时,可以调用vTaskSuspend()将自身挂起。
- B任务也可以调用vTaskSuspend()将A任务挂起。
- 同理调用vTaskResume(),可以将一个挂起态的任务转化为就绪态并告诉调度器该任务已处于就绪态。并不是在调用vTaskResume()函数后,任务直接进入运行态。至于什么时候进入运行态,是由任务调度器完成的。
2、函数vTaskSuspend()
函数原型如下:
/*
参数:要挂起的任务的任务句柄,创建任务的时候会为每个任务分配一个任务
句柄。如果使用函数 xTaskCreate()创建任务的话那么函数的参数
pxCreatedTask 就是此任务的任务句柄,如果使用函数 xTaskCreateStatic()
创建任务的话那么函数的返回值就是此任务的任务句柄。也可以通过函
数 xTaskGetHandle()来根据任务名字来获取某个任务的任务句柄。
注意!如果参数为 NULL 的话表示挂起任务自己。
*/
void vTaskSuspend( TaskHandle_t xTaskToSuspend)
3、函数vTaskResume()
函数原型:
/*
参数:要恢复的任务的任务句柄。
note:将一个任务从挂起态恢复到就绪态,只有通过函数 vTaskSuspend()设置为挂起态的任务才
可以使用 vTaskRexume()恢复!
*/
void vTaskResume( TaskHandle_t xTaskToResume)
4、函数xTaskResumeFromISR()
函数原型:
/*
参数:要恢复的任务的任务句柄。
返回值:
pdTRUE: 恢复运行的任务的任务优先级等于或者高于正在运行的任务(被中断打
断的任务),这意味着在退出中断服务函数以后必须进行一次上下文切换。
pdFALSE: 恢复运行的任务的任务优先级低于当前正在运行的任务(被中断打断的
任务),这意味着在退出中断服务函数的以后不需要进行上下文切换。
*/
BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume)
4.1 注意事项
- FreeRTOS的API函数只有带FromISR后缀的才能在中断函数中使用!
- 如果中断中使用了带FromISR后缀的函数,中断的优先级不能设置的过高(对应的数字过小)。中断的优先级不能高于宏定义configMAX_SYSCALL_INTERRUPT_PRIORITY,这个宏定义在FreeRTOSConfig.h中:
/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 4 /* 15 priority levels */
#endif
/* 在调用“设置优先级”函数时可以使用的最低中断优先级 */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0xf
/* 可以被任何中断服务程序使用的最高中断优先级,它可以调用来中断安全的FreeRTOS API函数。
不要从任何比这个优先级更高的中断调用中断安全的FREERTOS API函数!(优先级越高,数值越低)*/
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
/* 内核端口层本身使用的中断优先级。这些对所有Cortex-M端口都是通用的,并且不依赖于任何特定的库函数。*/
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY 不能设置为零 !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
即中断优先级设置范围为5~15(0xf)。如下对中断优先级进行设置
NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn; //外部中断4
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x06;//抢占优先级6
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; //子优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure); //配置
当然,如果中断函数中没有使用FreeRTOS的API,那么中断的优先级就不受限制
- 中断优先级分组
优先级分组:中断控制器(NVIC)允许定义每个中断优先级的比特被分割成定义中断的优先级比特和定义中断的次优先级比特。为简单起见,必须将所有位定义为抢占优先位。如果不是这样(如果某些位表示次优先级),下面的断言将失败。
因此在进行优先级分组时,所有位都是抢占优先级,没有次优先级。即中断分组模式4,
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
如果换成其它的,比如NVIC_PriorityGroup_3,程序进入中断后也会卡死。
部分内容参考:
巨人的肩膀