FreeRTOS实时操作系统(一)RTOS的基本概念
FreeRTOS实时操作系统(二)任务创建与任务删除(HAL库)
继续跟着正点原子学习FreeRTOS之任务挂起与恢复
挂起任务类似暂停任务,不是删除任务。
利用的API函数:
挂起任务:vTaskSuspend()
恢复被挂起的任务:vTaskResume()
在中断中恢复被挂起的任务:xTaskResumeFromISR() (一般带FromISR后缀是在中断函数中专用的API函数)
1.任务挂起:
void vTaskSuspend(TaskHandle_t xTaskToSuspend)
传回的参数是任务句柄,当是NULL时,挂起当前正在运行的任务。
使用时需将宏 INCLUDE_vTaskSuspend 配置为1。
无论优先级如何,被挂起的任务都将不再被执行,直到任务被恢复 。
2.任务恢复:
void vTaskResume(TaskHandle_t xTaskToResume)
传回参数是待恢复的任务句柄,任务即使被 vTaskSuspend() 挂起多次,只需在任务中调用 vTakResume() 一次,就可以继续运行,且被恢复的任务会进入就绪态。
使用时,宏INCLUDE_vTaskSuspend必须定义为 1
3.中断中任务恢复:
BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume)
参数是待恢复任务的句柄
返回值:
pdTRUE | 任务恢复后需要进行任务切换 |
---|---|
pdFALSE | 任务恢复后不需要进行任务切换 |
任务切换是指恢复的任务优先级比目前的高,需要调用一个函数来实现抢占。
使用时需要将宏INCLUDE_vTaskSuspend 和 INCLUDE_xTaskResumeFromISR 必须定义为1,HAl库不知道为啥要放在FreeRTOS.h文件,现在还不是很懂。
中断服务程序中要调用freeRTOS的API函数,中断优先级不能高于FreeRTOS所管理的最高优先级
使用起来很简单:
/* 任务三,判断按键KEY0,按下KEY0删除task1 */
void task3( void * pvParameters )
{
uint8_t key = 0;
while(1)
{
key = key_scan(0);
if(key == KEY0_PRES)
{
printf("挂起task1\r\n");
vTaskSuspend(task1_handler);
}else if(key == KEY1_PRES)
{
printf("在任务中恢复task1\r\n");
vTaskResume(task1_handler);
}
vTaskDelay(10);
}
}
注意1:
上面是FreeRTOS管理的优先级,我们使用的外部中断要比5-15数值之间,优先级上看是小于等于FreeRTOS管理的最高优先级。
官网说明链接:在 ARM Cortex-M Core 上运行 RTOS
注意2:
在官网中说明了:
HAl库中,自动就是设置对的:
下面以正点原子的程序为例子:
void extix_init(void)
{
GPIO_InitTypeDef gpio_init_struct;
key_init();
gpio_init_struct.Pin = KEY2_INT_GPIO_PIN;
gpio_init_struct.Mode = GPIO_MODE_IT_FALLING; /* 下降沿触发 */
gpio_init_struct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(KEY2_INT_GPIO_PORT, &gpio_init_struct); /* KEY2配置为下降沿触发中断 */
HAL_NVIC_SetPriority(KEY2_INT_IRQn, 5, 0); /* 抢占5,子优先级0 */
HAL_NVIC_EnableIRQ(KEY2_INT_IRQn); /* 使能中断线2 */
}
/**
* @brief 中断服务程序中需要做的事情
在HAL库中所有的外部中断服务函数都会调用此函数
* @param GPIO_Pin:中断引脚号
* @retval 无
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
delay_ms(20); /* 消抖 */
switch(GPIO_Pin)
{
BaseType_t xYieldRequired;//重点
case KEY2_INT_GPIO_PIN:
if (KEY2 == 0)
{
xYieldRequired = xTaskResumeFromISR(task1_handler);//重点
printf("在中断中恢复task1\r\n");//重点
portYIELD_FROM_ISR(xYieldRequired);//重点
}
break;
default : break;
}
}
用的是按键外部中断的例子,需要注意的是外部中断初始化的时候,中断优先级设置的是5。
这里需要注意,我们需要对返回值判断是否需要切换任务,但是无需我们自己判断:
如上图所示portYIELD_FROM_ISR()函数会自己判断当前值,是否执行任务切换。