提示:好記性不如爛筆頭。本部落格作為學習筆記,有錯誤的地方希望指正
ESP32-FreeRTOS序列:
ESP32 FreeRTOS-任務的建立與删除 (1)
ESP32 FreeRTOS-任務輸入參數(2)
ESP32 FreeRTOS-任務優先級(3)
ESP32 FreeRTOS-調試任務實用工具(4)
文章目錄
- ESP32-FreeRTOS序列:
- 前言:
- 一、擷取任務優先級
- 二、設定任務優先級
- 三、綜合示例
前言:
參考資料: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
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
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
}