提示:好记性不如烂笔头。本博客作为学习笔记,有错误的地方希望指正
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
}