ESP32 FreeRTOS-任务优先级(3)

本文介绍ESP32-FreeRTOS中任务优先级的概念及其调整方法,包括如何获取和设置任务优先级,并通过示例代码展示不同优先级设置下任务的执行顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

提示:好记性不如烂笔头。本博客作为学习笔记,有错误的地方希望指正

ESP32-FreeRTOS序列:

ESP32 FreeRTOS-任务的创建与删除 (1)
ESP32 FreeRTOS-任务输入参数(2)
ESP32 FreeRTOS-任务优先级(3)
ESP32 FreeRTOS-调试任务实用工具(4)

前言:

  参考资料:FreeRTOS API参考
  第一篇的时候我们介绍了任务的创建,第二篇的时候我们讲述了创建任务的时候可以给任务传入一些参数,这篇我们继续来对创建任务函数中的参数分析,这里主要讲述的是任务优先级。
xTaskCreate API原型:

BaseType_t xTaskCreate(    TaskFunction_t pvTaskCode,
                            const char * const pcName,
                            configSTACK_DEPTH_TYPE usStackDepth,
                            void *pvParameters,
                            UBaseType_t uxPriority,
                            TaskHandle_t *pxCreatedTask
                          );

  在往里面找我们找到typedef unsigned int UBaseType_t;这样任务优先级的参数类型,是一个整形的数据类型。对于freeRTOS的任务优先级和UCOSII他们的有些不一样,FreeRTOS的任务优先级的最大数从0-(configMAX_PRIORITIES - 1),FreeRTOS中优先级的数值越大,即优先级别越大,ucos操作系统中任务的优先级数字越小,优先级越大。这个configMAX_PRIORITIES的值是在FreeRTOSConfig.h文件中有配置,最大值ESP32中默认为25,最大值根据用户需求可以自行设置。
  此外一个任务的优先级我们可以通过API来获取它当前的优先级,还可以设置它的优先级。

一、获取任务优先级

获取任务优先级API

UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask );

  INCLUDE_uxTaskPriorityGet必须定义为1,才能使该函数可用。更多信息请参见RTOS配置文档。获取任意任务的优先级。
参数:
  xTask要查询的任务句柄。传递NULL句柄会导致返回调用任务的优先级。
返回:
  xTask的优先级。
使用示例:

void vAFunction( void )
 {
 TaskHandle_t xHandle;

     // Create a task, storing the handle.
     xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );

     // ...

     // Use the handle to obtain the priority of the created task.
     // It was created with tskIDLE_PRIORITY, but may have changed
     // it itself.
     if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY )
     {
         // The task has changed its priority.
     }

     // ...

     // Is our priority higher than the created task?
     if( uxTaskPriorityGet( xHandle ) < uxTaskPriorityGet( NULL ) )
     {
         // Our priority (obtained using NULL handle) is higher.
     }
 }

二、设置任务优先级

设置任务优先级 API

void vTaskPrioritySet( TaskHandle_t xTask,UBaseType_t uxNewPriority );

  INCLUDE_vTaskPrioritySet必须定义为1,才能使该函数可用。更多信息请参见RTOS配置文档。设置任意任务的优先级。
  如果所设置的优先级高于当前正在执行的任务,则在函数返回之前将发生上下文切换。
参数:
  xTask正在设置优先级的任务句柄。NULL句柄设置调用任务的优先级。uxNewPriority任务要设置的优先级。
  优先级被断言小于configMAX_PRIORITIES。如果configASSERT未定义,优先级将静默地封顶为(configMAX_PRIORITIES - 1)。
使用示例

 void vAFunction( void )
 {
 TaskHandle_t xHandle;
     // Create a task, storing the handle.
     xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
     // ...
     // Use the handle to raise the priority of the created task.
     vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 )
     // ...
     // Use a NULL handle to raise our priority to the same value.
     vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 );
 }

三、综合示例

  我的这个示例中没有开启宏定义的时候APP_task_One默认的优先级是3。

  • 不开启动宏定义时,APP_task_Two的也是3,这个时候两个任务是按照时间片来执行的,谁先创建就先执行谁,不开启宏定义的时候就是APP_task_Two先执行,因它在先创建。
  • 开启APP_task_One_Priorty_Two宏定义的时候就是先执行APP_task_Two,因为此时它的任务优先级的数值(3>2)
  • 当开启APP_task_One_Priorty_Four的时候就是先执行APP_task_One,这个时候APP_task_One 的优先级的数值比APP_task_Two高(4>3);
  • 当开启APP_task_Six_Set_Priorty的时候,默认APP_task_One的优先级和APP_task_Two一样,但是APP_task_Two先创建,即它先执行,执行3s以后我们设置了APP_task_One的优先级为6,(6>3),即后面都是APP_task_One的优先级大于APP_task_Two的优先级,后面就会先执行APP_task_One的任务。
/**
 * @file 3_TaskPriority.c
 * @author WSP
 * @brief 
 * @version 0.1
 * @date 2022-10-06
 * 
 * @copyright Copyright (c) 2022
 * 
 */
#include "System_Include.h"

const static char * TAG = "Task_Parameter";
//  APP_task 任务的一些变量
TaskHandle_t APP_task_One_handle = NULL;
TaskHandle_t APP_task_Two_handle = NULL;

// 根据宏定义来修改测试代码中不同部分
#define APP_task_Six_Set_Priorty    1

/**
 * @brief APP_task
 * @param arg 任务传入的参数
 * @return NULL
 */
void APP_task_One(void * arg)
{
    while (1){
        vTaskDelay(1000/portTICK_PERIOD_MS);
        ESP_LOGI(TAG,"APP_task_One");
    }
}
/**
 * @brief APP_task
 * @param arg 任务传入的参数
 * @return NULL
 */
void APP_task_Two(void *arg)
{
    while (1){
        vTaskDelay(1000/portTICK_PERIOD_MS);
        ESP_LOGI(TAG,"APP_task_Two");
    }
}
/**
 * @brief   创建函数初始化
 * @param   NULL
 * @return  NULL
 */
void Priority_Task_Init(void)
{
    // 创建任务二
    xTaskCreate(APP_task_Two,               // 创建任务
                "APP_task_Two",             // 创建任务名
                2048,                       // 任务堆栈
                NULL,                       // 任务参数
                3 ,                         // 任务优先级
                &APP_task_Two_handle);      // 任务句柄

    // 创建任务一
    xTaskCreate(APP_task_One,               // 创建任务
                "APP_task_One",             // 创建任务名
                2048,                       // 任务堆栈
                NULL,
            #if APP_task_One_Priorty_Two    // 任务优先级 2 低优先级,高优先级先执行(数值越大优先级越高)
                2,                         
            #elif APP_task_One_Priorty_Four // 任务优先级 4 低优先级,高优先级先执行(数值越大优先级越高)
                4,  
            #else
                3,                          // 默认3   两个任务一样的优先级 谁先创建谁先输出 按照时间片刻来执行                
            #endif
                &APP_task_One_handle);      // 任务句柄 

    vTaskDelay(3000/portTICK_PERIOD_MS);    // 延时等待
    ESP_LOGI(TAG,"APP_task_Two priorty:%d",uxTaskPriorityGet(APP_task_One_handle));
#if APP_task_Six_Set_Priorty                // 设置任务优先级   
    vTaskPrioritySet(APP_task_One_handle,6);// 设置任务优先级    
    ESP_LOGI(TAG,"APP_task_Two priorty:%d",uxTaskPriorityGet(APP_task_One_handle));
#endif
}

### ESP32 中 IDF 框架的任务优先级配置及其影响 在ESP32的IDF框架中,任务优先级是一个重要的参数,它决定了不同任务之间的调度顺序。通过合理设置任务优先级可以优化系统的响应时间和资源利用率。 #### 创建带优先级任务 创建具有特定优先级的新FreeRTOS任务可以通过`xTaskCreatePinnedToCore()`函数来完成。此函数允许指定任务的核心以及其优先级: ```c // 定义任务入口函数原型 void my_task(void *pvParameters); // 创建并启动新任务 const uint8_t core_id = 0; // 绑定到核心0或1 const UBaseType_t priority = 5; // 设置任务优先级 const char* task_name = "mytask"; // 任务名称 const configSTACK_DEPTH_TYPE stack_depth = 2048; xTaskCreatePinnedToCore( my_task, /* Task function */ task_name, /* Name of task */ stack_depth, /* Stack size (configMINIMAL_STACK_SIZE units) */ NULL, /* Parameter passed as input to the task */ priority, /* Priority of the task */ NULL, /* Task handle. Set this parameter to NULL unless you need it later on.*/ core_id /* Core ID where the task will run*/ ); ``` 当多个任务竞争CPU时间片时,高优先级任务会抢占低优先级任务的时间片[^1]。 #### 修改现有任务优先级 除了在创建时设定外,在运行期间也可以调整已有任务优先级。这可通过调用`vTaskPrioritySet()`实现: ```c TaskHandle_t xHandle; UBaseType_t uxNewPriority = 7; // 获取当前正在执行的任务句柄 xHandle = xTaskGetCurrentTaskHandle(); // 更改该任务优先级别为新的值 vTaskPrioritySet(xHandle, uxNewPriority); ``` 需要注意的是频繁更改任务优先级可能会引起系统不稳定,因此建议仅在必要情况下才这样做。 #### 影响因素分析 - **实时性能**:适当提高某些关键路径上的任务优先级有助于改善整个应用程序对于外部事件反应的速度。 - **资源争用**:如果两个以上相同级别的进程试图访问同一共享资源,则可能导致死锁现象发生;此时应考虑引入信号量机制加以控制。 - **功耗管理**:长时间处于活跃状态下的高优先进程可能增加设备能耗水平,不利于电池供电产品设计。 总之,在ESP-IDF环境中精心规划各组件间的关系,并依据实际应用场景分配合理的优先权等级能够有效提升嵌入式软件的整体表现力和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值