FreeRTOS的任务挂起与恢复

1.任务的挂起与恢复的API函数

API函数

描述

vTaskSuspend()

挂起任务

vTaskResume()

恢复被挂起的任务

xTaskResumeFromISR()

在中断中恢复被挂起的任务

挂起:挂起任务类似暂停,可恢复; 删除任务,无法恢复。

恢复:恢复被挂起的任务

FromISR”:带FromISR后缀是在中断函数中专用的API函数

任务挂起函数介绍

void vTaskSuspend(TaskHandle_t xTaskToSuspend)

形参

描述
xTaskToSuspend

待挂起任务的任务句柄

此函数用于挂起任务,使用时需将宏 INCLUDE_vTaskSuspend  配置为 1

无论优先级如何,被挂起的任务都将不再被执行,直到任务被恢复

当传入的参数为NULL,则代表挂起任务自身(当前正在运行的任务)

任务恢复函数介绍(任务中恢复)

任务中恢复被挂起函数:void vTaskResume(TaskHandle_t xTaskToResume)

形参

描述

xTaskToResume

待恢复任务的任务句柄

使用该函数注意宏:INCLUDE_vTaskSuspend必须定义为 1

任务无论被 vTaskSuspend() 挂起多少次,只需在任务中调用  vTakResume() 恢复一次,就可以继续运行。且被恢复的任务会进入就绪态!

任务恢复函数介绍(中断中恢复)

中断中恢复被挂起函数: BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume

形参描述

xTaskToResume

待恢复任务的任务句柄

函数:xTaskResumeFromISR返回值描述如下:

返回值

描述
pdTRUE

任务恢复后需要进行任务切换

pdFALSE

任务恢复后不需要进行任务切换

使用该函数注意宏:INCLUDE_vTaskSuspend INCLUDE_xTaskResumeFromISR 必须定义为 1

该函数专用于中断服务函数中,用于解挂被挂起任务

中断服务程序中要调用freeRTOSAPI函数则中断优先级不能高于FreeRTOS所管理的最高优先级

2.任务挂起和恢复API函数解析

任务挂起函数内部实现

1、获取所要挂起任务的控制块

通过传入的任务句柄,判断所需要挂起哪个任务,NULL代表挂起自身

2、移除所在列表

将要挂起的任务从相应的状态列表和事件列表中移除(就绪或阻塞列表)

3、插入挂起任务列表

将待挂起任务的任务状态列表项插入到挂起态任务列表末尾

4、判断任务调度器是否运行

在运行,更新下一次阻塞时间,防止被挂起任务为下一次阻塞超时任务

5、判断待挂起任务是否为当前任务

如果挂起的是任务自身,且调度器正在运行,需要进行一次任务切换

调度器没有运行,判断挂起任务数是否等于任务总数,是:当前控制块赋值为NULL,否:寻找下一个最高优先级任务

任务恢复函数内部实现

1、恢复任务不能是正在运行任务

2、判断任务是否在挂起列表中

是:就会将该任务在挂起列表中移除, 将该任务添加到就绪列表中

3、判断恢复任务优先级

判断恢复的任务优先级是否大于当前正在运行的 是的话执行任务切换

3.任务挂起与恢复实验

将设计四个任务:

start_task:用来创建其他的三个任务

task1:实现LED0500ms闪烁一次

task2:实现LED1500ms闪烁一次

task3:判断按键按下逻辑,KEY0按下,挂起task1,按下KEY1在任务中恢复task1

按下KEY2,在中断中恢复task1(外部中断线实现)

/* START_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define START_TASK_PRIO         1
#define START_TASK_STACK_SIZE   128
TaskHandle_t    start_task_handler;
void start_task( void * pvParameters );

/* TASK1 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK1_PRIO         2
#define TASK1_STACK_SIZE   128
TaskHandle_t    task1_handler;
void task1( void * pvParameters );

/* TASK2 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK2_PRIO         3
#define TASK2_STACK_SIZE   128
TaskHandle_t    task2_handler;
void task2( void * pvParameters );

/* TASK3 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK3_PRIO         4
#define TASK3_STACK_SIZE   128
TaskHandle_t    task3_handler;
void task3( void * pvParameters );
/******************************************************************************************************/


/**
 * @brief       FreeRTOS例程入口函数
 * @param       无
 * @retval      无
 */
void freertos_demo(void)
{    
    xTaskCreate((TaskFunction_t         )   start_task,
                (char *                 )   "start_task",
                (configSTACK_DEPTH_TYPE )   START_TASK_STACK_SIZE,
                (void *                 )   NULL,
                (UBaseType_t            )   START_TASK_PRIO,
                (TaskHandle_t *         )   &start_task_handler );
    vTaskStartScheduler();
}


void start_task( void * pvParameters )
{
    taskENTER_CRITICAL();               /* 进入临界区 */
    xTaskCreate((TaskFunction_t         )   task1,
                (char *                 )   "task1",
                (configSTACK_DEPTH_TYPE )   TASK1_STACK_SIZE,
                (void *                 )   NULL,
                (UBaseType_t            )   TASK1_PRIO,
                (TaskHandle_t *         )   &task1_handler );
                
    xTaskCreate((TaskFunction_t         )   task2,
                (char *                 )   "task2",
                (configSTACK_DEPTH_TYPE )   TASK2_STACK_SIZE,
                (void *                 )   NULL,
                (UBaseType_t            )   TASK2_PRIO,
                (TaskHandle_t *         )   &task2_handler );
                
    xTaskCreate((TaskFunction_t         )   task3,
                (char *                 )   "task3",
                (configSTACK_DEPTH_TYPE )   TASK3_STACK_SIZE,
                (void *                 )   NULL,
                (UBaseType_t            )   TASK3_PRIO,
                (TaskHandle_t *         )   &task3_handler );
    vTaskDelete(NULL);
    taskEXIT_CRITICAL();                /* 退出临界区 */
}

/* 任务一,实现LED0每500ms翻转一次 */
void task1( void * pvParameters )
{
    uint32_t task1_num = 0;
    while(1)
    {
        printf("task1_num:%d\r\n",++task1_num);
        LED0_TOGGLE();
        vTaskDelay(500);
    }
}

/* 任务二,实现LED1每500ms翻转一次 */
void task2( void * pvParameters )
{
    uint32_t task2_num = 0;
    while(1)
    {
        printf("task2_num:%d\r\n",++task2_num);
        LED1_TOGGLE();
        vTaskDelay(500);
    }
}

/* 任务三,判断按键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);
    }
}

本文参考正点原子手把手教你学FreeRTOS实时系统视频学习

  • 16
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值