六、FreeRTOS之FreeRTOS的任务挂起和恢复函数介绍

本节需要掌握以下内容:

1,任务的挂起与恢复的API函数(熟悉)

2,任务挂起与恢复实验(掌握)

3,课堂总结(掌握)

一、任务的挂起与恢复的API函数(熟悉)

API函数

描述

vTaskSuspend()

挂起任务

vTaskResume()

恢复被挂起的任务

xTaskResumeFromISR()

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

 那么问题来了,挂起和删除的区别是什么呢?

  • 挂起:挂起任务类似暂停,可恢复; 删除任务,无法恢复
  • 恢复:恢复被挂起的任务
  • FromISR:带FromISR后缀是在中断函数中专用的API函数

1.1  任务挂起函数介绍

        void vTaskSuspend(TaskHandle_t xTaskToSuspend)

形参

描述

xTaskToSuspend

待挂起任务的任务句柄

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

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

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

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

        void vTaskResume(TaskHandle_t xTaskToResume)

形参

描述

xTaskToResume

待恢复任务的任务句柄

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

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

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

         BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume

形参

描述

xTaskToResume

待恢复任务的任务句柄

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

返回值

描述

pdTRUE

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

pdFALSE

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

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

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

注意:中断服务程序中要调用freeRTOSAPI函数则中断优先级不能高于FreeRTOS所管理的最高优先级  任务优先级数值越高 优先级越高  中断优先级数值越小 优先级越高

二、任务挂起与恢复实验(掌握)

2.1 实验目的

        学会使用FreeRTOS中的任务挂起与恢复相关API函数:vTaskSuspend( )

vTaskResume( )xTaskResumeFromISR( )

2.2、实验设计

        将设计四个任务:start_task、task1、task2、task3

   四个任务的功能如下:

  • start_task:用来创建其他的三个任务
  • task1:实现LED0每500ms闪烁一次
  • task2:实现LED1每500ms闪烁一次
  • task3:判断按键按下逻辑,KEY0按下,挂起task1,按下KEY1在任务中恢复task1
  • 按下KEY2,在中断中恢复task1(外部中断线实现)

2.3、参考代码

demo.c

/******************************************************************************************************/
/*FreeRTOS配置*/

/* 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);
    }
}

按下KEY2,在中断中恢复task1(外部中断线实现): 强烈推荐参考官网的例程!真的很方便https://www.freertos.org/zh-cn-cmn-s/RTOS.html,我真的不想网页自动翻译啊!这样我英语“八级”的水平怎么显现!!!哈哈哈,开玩笑!

六、FreeRTOS之FreeRTOS的任务挂起和恢复函数介绍_第1张图片

exit.c

extern TaskHandle_t    task1_handler;
/**
 * @brief       KEY2 外部中断服务程序
 * @param       无
 * @retval      无
 */
void KEY2_INT_IRQHandler(void)
{ 
    HAL_GPIO_EXTI_IRQHandler(KEY2_INT_GPIO_PIN);        /* 调用中断处理公用函数 清除KEY2所在中断线 的中断标志位,中断下半部在HAL_GPIO_EXTI_Callback执行 */
    __HAL_GPIO_EXTI_CLEAR_IT(KEY2_INT_GPIO_PIN);        /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
}

/**
 * @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");
            }
            if(xYieldRequired == pdTRUE)
            {
                portYIELD_FROM_ISR(xYieldRequired);
            }
            break;
        default : break;
    }
}

/**
 * @brief       外部中断初始化程序
 * @param       无
 * @retval      无
 */
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 */

}

 中断这部分一定要注意:请务必参考官网内核相关资料,链接如下:

RTOS for ARM Cortex-M

六、FreeRTOS之FreeRTOS的任务挂起和恢复函数介绍_第2张图片

六、FreeRTOS之FreeRTOS的任务挂起和恢复函数介绍_第3张图片

#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY         15                  /* 中断最低优先级 */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    5                   /* FreeRTOS可管理的最高中断优先级 */

因此 

六、FreeRTOS之FreeRTOS的任务挂起和恢复函数介绍_第4张图片

开源不易,希望大家点个赞吧

我太喜欢点赞了!

六、FreeRTOS之FreeRTOS的任务挂起和恢复函数介绍_第5张图片

你可能感兴趣的:(FreeRTOS实时操作系统,算法,嵌入式软件)