• 【FreeRTOS(三)】任务状态


    任务状态

    freeRTOS任务的状态有四种:运行、就绪、阻塞、挂起

    • 运行态(runnnig):当任务正在运行,此时的状态被称为运行态,即CPU的使用权被这个任务占用;
    • 挂起态(suspended):任务被暂时停止,通过调用挂起函数(vTaskSuspend())可以把指定任务挂起,任务挂起后暂时不会运行,只有调用恢复函数(xTaskResume())才可以退出挂起状态;
    • 阻塞态(blocked):任务在等待信号量、消息队列、事件标准组、系统延时时,被称为阻塞态,如果等待的事件到了,就会自动退出阻塞态,准备运行;
    • 就绪态(ready):任务已经具备了运行条件(没有被挂起或阻塞),但是又更高优先级或同优先级的任务正在运行,所以需要等待的状态。

    在这里插入图片描述

    一般任务创建完成后,进入就绪态;处于就绪态的任务,如果没有更高优先级或同优先级的任务正在运行,它会自动进入运行态;如果有更高优先级的任务要运行,或者同优先级的任务要轮流运行,它会从运行态返回到就绪态;如果任务需要等待某个事件,或者任务自己进入了系统延时,则会进入阻塞态;当等待的事件达到后,任务又会进入就绪态。

    注意事项:在阻塞状态中,任务可以等待两种类型的事件:

    • 时间相关的事件。
      • 可以是等待一段时间,比如等3秒钟。使用vTaskDelay函数实现,等待的时间到了任务就会变为就绪态
      • 也可以是等到某个绝对的时间点。使用vTaskDelayUntil函数实现,等到了某个时间点任务就会进入就绪态
    • 同步事件,由其他任务或者中断产生,比如任务A给任务B发送数据,或者任务A等待用户按下按键。同步事件的来源很多,如下:
      • 队列(queue)
      • 二进制信号量(binary semaphores)
      • 互斥量(mutexes)
      • 递归互斥量、递归锁(recursive muxtexes)
      • 事件组(event groups)
      • 任务通知(task notifications)

    任务挂起 vTaskSuspend

    挂起任务,当挂起一个任务时,不管优先级是多少,不需要占用任何微控制器处理器时间。调用vTaskSuspend不会累积——即:在统一任务中调用vTaskSuspend两次,但只需调用一次vTaskResume来是挂起的任务就绪。

    void vTaskSuspend( xTaskHandle pxTaskToSuspend);
    
    • 1
    parameterdescription
    pxTaskToSuspend处理需要挂起的任务。传递NULL将挂起调用此函数的任务。
    return

    取消任务挂起 vTaskResume

    取消挂起的任务。 必须是调用 vTaskSuspend后挂起的任务,才有可能通过调用 vTaskResume重新运行。

    void vTaskResume(xTaskHandle pxTaskToResume);
    
    • 1
    parameterdescription
    pxTaskToResume就绪的任务的句柄
    return

    挂起任务调度器 vTaskSuspendAll

    挂起任务调度器,挂起任务调度器可以防止发生上下文切换,但保留启用中断的状态。如果一个中断在调度程序挂起时请求上下文切换,那么该请求被保持为挂起状态,并且只有在任务调度器恢复(非挂起)时才执行。注意一下:

    • 在挂起任务调度器时,其他FreeRTOS API函数是不能被调用的,自己的函数可以被调用。
    • 注意系统看门狗喂狗
    void vTaskSuspendAll(void);
    
    • 1
    parameterdescription
    None
    return

    取消挂起任务调度器 xTaskResumeAll

    在使用 vTaskSuspendAll 挂起任务调度器后,使用此函数可恢复任务调度器。

    BaseType_t xTaskResumeAll(void);
    
    • 1
    parameterdescription
    None
    return是否恢复

    代码示例:任务挂起、取消任务挂起

    创建两个优先级为1的任务,再将task1挂起,延时3秒后取消挂起

    #include 
    #include "sdkconfig.h"
    #include "freertos/FreeRTOS.h"
    #include "freertos/task.h"
    #include "esp_system.h"
    #include "esp_spi_flash.h"
    
    void task1(void *pvParam)
    {
        while (1)
        {
            printf("task1!\n");
            vTaskDelay(1000 / portTICK_PERIOD_MS);
        }
    }
    
    void task2(void *pvParam)
    {
        while (1)
        {
            printf("task2!\n");
            vTaskDelay(1000 / portTICK_PERIOD_MS);
        }
    }
    
    void app_main(void)
    {
        TaskHandle_t pxTask = NULL;
    
        xTaskCreate(task1, "task1", 4096, NULL, 1, pxTask);
        xTaskCreate(task2, "task2", 4096, NULL, 1, NULL);
    
        vTaskSuspend(pxTask);
       
        vTaskDelay(3000 / portTICK_PERIOD_MS);
    
        vTaskResume(pxTask);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    代码示例:挂起任务调度器、取消挂起任务调度器

    创建两个优先级为1的任务,进入task1,准备for循环时,挂起任务调度器,防止其他任务干扰,待for循环结束时,取消挂起任务调度器

    #include 
    #include "sdkconfig.h"
    #include "freertos/FreeRTOS.h"
    #include "freertos/task.h"
    #include "esp_system.h"
    #include "esp_spi_flash.h"
    
    void task1(void *pvParam)
    {
    
        printf("Test begin!\n");
        vTaskSuspendAll();
    
        for(int i = 0; i < 9999; i++)
        {
            for(int j = 0; j < 9999; j++)
            {
                ;
            }
        }
    
        xTaskResumeAll();
        printf("Test end\n");
    
        vTaskDelete(NULL);
    }
    
    void task2(void *pvParam)
    {
        while (1)
        {
            printf("task2!\n");
            vTaskDelay(1000 / portTICK_PERIOD_MS);
        }
    }
    
    void app_main(void)
    {
        xTaskCreate(task1, "task1", 4096, NULL, 1, NULL);
        xTaskCreate(task2, "task2", 4096, NULL, 1, NULL);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
  • 相关阅读:
    iOS基础开发介绍
    DOM中的diff算法详解
    小项目----音乐在线播放器
    网络安全方向系统学习指南
    MAC 配置 Maven
    【C++函数的进化】函数指针,模板,仿函数,lambda表达式
    解读谷歌Pathways架构(二):向前一步是OneFlow
    typescript87-react中状态和事件
    使用 ADO.NET 创建简单的数据应用程序
    百度地图在vue中的使用
  • 原文地址:https://blog.csdn.net/K3169/article/details/128071866