Freertos學習:04-任務的調試函數


--- title: rtos-freertos-04-任務的調試函數 EntryName: rtos-freertos-04-task-debug date: 2020-06-22 08:49:06 categories: tags: - debug - freertos ---

章節概述:

任務應用函數是一組輔助類函數,一般用於調試信息輸出、獲取任務句柄、獲取任務狀態、操作任務標簽值等等。

概覽

uxTaskPriorityGet():查詢某個任務的優先級
vTaskPrioritySet():改變某個任務的任務優先級
uxTaskGetSystemState():獲取系統中任務狀態
vTaskGetInfo():獲取某個任務信息
xTaskGetApplicationTaskTag():獲取某個任務的標簽(Tag)值
xTaskGetCurrentTaskHandle():獲取當前正在運行的任務的任務句柄
xTaskGetHandle():根據任務名字查找某個任務的句柄
xTaskGetIdleTaskHandle():獲取空閑任務的任務句柄
uxTaskGetStackHighWaterMark():獲取任務的堆棧的歷史剩余最小值,FreeRTOS 中叫做“高水位線”
eTaskGetState():獲取某個任務的壯態,這個壯態是 eTaskState 類型
pcTaskGetName():獲取某個任務的任務名字
xTaskGetTickCount():獲取系統時間計數器值
xTaskGetTickCountFromISR():在中斷服務函數中獲取時間計數器值
xTaskGetSchedulerState():獲取任務調度器的壯態,開啟或未開啟
uxTaskGetNumberOfTasks():獲取當前系統中存在的任務數量
vTaskList():以一種表格的形式輸出當前系統中所有任務的詳細信息
vTaskGetRunTimeStats():獲取每個任務的運行時間
vTaskSetApplicationTaskTag():設置任務標簽(Tag)值
SetThreadLocalStoragePointer():設置線程本地存儲指針
GetThreadLocalStoragePointer():獲取線程本地存儲指針

獲取任務系統狀態

UBaseType_t uxTaskGetSystemState(
    TaskStatus_t * constpxTaskStatusArray,
    const UBaseType_tuxArraySize,
    unsigned long * constpulTotalRunTime );

描述:該函數向TaskStatus_t結構體填充相關信息,系統中每一個任務的信息都可以填充到TaskStatus_t結構體數組中,數組大小由uxArraySize指定。

在文件FreeRTOSConfig.h中,宏configUSE_TRACE_FACILITY必須設置為1,此函數才有效。

參數解析:

  • pxTaskStatusArray:指向TaskStatus_t類型的結構體數組。這個數組至少要包含1個元素。RTOS控制的任務數量可以使用API函數uxTaskGetNumberOfTasks()獲取。
  • uxArraySize:參數pxTaskStatusArray指向的數組大小,也就是該數組的索引數目。
  • pulTotalRunTime:如果在文件FreeRTOSConfig.h中設置宏configGENERATE_RUN_TIME_STATS為1,則該函數將總運行時間寫入*pulTotalRunTime中。pulTotalRunTime可以設置為NULL,表示忽略總運行時間。

返回值:被填充的TaskStatus_t結構體數量。這個值應該等於通過調用API函數uxTaskGetNumberOfTasks()返回的值,但如果傳遞給uxArraySize參數的值太小,則返回0。

注意:注意,這個函數僅用來調試用,調用此函數會掛起所有任務,直到函數最后才恢復掛起的任務,因此任務可能被掛起很長時間。

結構體TaskStatus_t定義如下:

typedef struct xTASK_STATUS
{
   /* 任務句柄*/
   TaskHandle_t xHandle;
 
   /* 指針,指向任務名*/
   const signed char *pcTaskName;
 
   /* 任務ID,是一個獨一無二的數字*/
   UBaseType_t xTaskNumber;
 
   /* 任務當前的狀態(運行、就緒、掛起等等)*/
   eTaskState eCurrentState;
 
   /* 任務運行(或繼承)的優先級。*/
   UBaseType_t uxCurrentPriority;
 
   /* 當任務因繼承而改變優先級時,該變量保存任務最初的優先級。僅當configUSE_MUTEXES定義為1有效。*/
   UBaseType_t uxBasePriority;
 
   /* 分配給任務的總運行時間。僅當宏configGENERATE_RUN_TIME_STATS為1時有效。*/
   unsigned long ulRunTimeCounter;
 
   /* 從任務創建起,堆棧剩余的最小數量,這個值越接近0,堆棧溢出的可能越大。 */
   unsigned short usStackHighWaterMark;
}TaskStatus_t;

例子:

/*本例演示如是使用uxTaskGetSystemState()函數來獲取運行時間信息,並將其轉化為程序員更易識別的字符格式,這些轉化后的字符保存到pcWriteBuffer中。*/
void vmyTaskGetRunTimeStats()
{
   TaskStatus_t*pxTaskStatusArray;
   volatileUBaseType_t uxArraySize, x;
   unsignedlong ulTotalRunTime, ulStatsAsPercentage;

 
   /* 獲取任務總數目*/
  uxArraySize = uxTaskGetNumberOfTasks ();
 
   /*為每個任務的TaskStatus_t結構體分配內存,也可以靜態的分配一個足夠大的數組 */
  pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ));
 
   if(pxTaskStatusArray != NULL )
   {
      /*獲取每個任務的狀態信息 */
     uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, 
                                        uxArraySize, 
                                        NULL);//&ulTotalRunTime );
 
      /* 百分比計算 */
     //ulTotalRunTime /= 100UL;
 
      /* 避免除零錯誤 */
      if(1)//ulTotalRunTime > 0 )
      {
         /* 將獲得的每一個任務狀態信息部分的轉化為程序員容易識別的字符串格式*/
        for( x = 0; x < uxArraySize; x++ )
         {
           /* 計算任務運行時間與總運行時間的百分比。*/
           //ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter /ulTotalRunTime;
 
           if(1) // ulStatsAsPercentage > 0UL )
           {
              sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n",
                                pxTaskStatusArray[ x ].pcTaskName,
                                pxTaskStatusArray[ x ].ulRunTimeCounter,
                                ulStatsAsPercentage );
           }
           else
           {
              /* 任務運行時間不足總運行時間的1%*/
              sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n",
                                pxTaskStatusArray[ x ].pcTaskName,
                                 pxTaskStatusArray[x ].ulRunTimeCounter );
           }
         }
      }
 
      /* 釋放之前申請的內存*/
     vPortFree( pxTaskStatusArray );
   }
}

獲取當前任務句柄

TaskHandle_t xTaskGetCurrentTaskHandle(void );

描述:

在文件FreeRTOSConfig.h中,宏INCLUDE_xTaskGetCurrentTaskHandle必須設置為1,此函數才有效。

參數解析:

返回值: 返回當前任務(調用該函數的任務)的句柄。

獲取空閑任務句柄

TaskHandle_t xTaskGetIdleTaskHandle(void );

描述:

在文件FreeRTOSConfig.h中,宏INCLUDE_xTaskGetIdleTaskHandle必須設置為1,此函數才有效。

返回值:返回空閑任務句柄。空閑任務在RTOS調度器啟動時自動創建。

獲取任務堆棧最大使用深度

UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );

描述:獲取任務的堆棧的歷史剩余最小值,FreeRTOS 中叫做“高水位線”。

任務的堆棧空間會隨着任務執行以及中斷處理而增長或縮小。該函數可以返回任務啟動后的最小剩余堆棧空間。換句話說,可以間接估算出一個任務最多需要多少堆棧空間。

在文件FreeRTOSConfig.h中,宏INCLUDE_uxTaskGetStackHighWaterMark 必須設置成1,此函數才有效。

參數解析:

xTask:任務句柄。NULL表示查看當前任務的堆棧使用情況。

返回值:返回最小剩余堆棧空間,以字為單位。比如一個32為架構處理器,返回值為1表示有4字節堆棧空間沒有使用過。如果返回值為0,則任務很可能已經發生了堆棧溢出。

例子:

void vTask1( void * pvParameters )
{
    UBaseType_t uxHighWaterMark;

    /* 入口處檢測一次 */
    uxHighWaterMark =uxTaskGetStackHighWaterMark( NULL );

    for( ;; )
    {
        /* 正常調用函數 */
        vTaskDelay( 1000 );

        /* 測量堆棧使用情況 */
        uxHighWaterMark =uxTaskGetStackHighWaterMark( NULL );
    }
}

獲取任務狀態

eTaskState eTaskGetState( TaskHandle_txTask );

描述:返回一個枚舉類型的任務狀態值。

在文件FreeRTOSConfig.h中,宏INCLUDE_eTaskGetState必須設置為1,此函數才有效。

參數解析:

xTask:任務句柄

返回值:

返回值 狀態
eReady 就緒
eRunning 運行
eBlocked 阻塞
eSuspended 掛起
eDeleted 刪除

獲取任務描述內容

char * pcTaskGetTaskName( TaskHandle_txTaskToQuery );

描述:獲取任務的名稱。

在文件FreeRTOSConfig.h中,宏INCLUDE_pcTaskGetTaskName必須設置成1,此函數才有效。

參數解析:xTaskToQuery:任務的句柄。NULL表示獲取當前任務的描述內容指針。

返回值:一個指針,指向任務名稱字符串。

獲取系統節拍次數

volatile TickType_t xTaskGetTickCount(void );

描述:

這個函數不能在ISR中調用;用volatile TickType_t xTaskGetTickCountFromISR( void )代替

返回值:返回從vTaskStartScheduler函數調用后的系統時鍾節拍次數。

獲取調度器狀態

BaseType_t xTaskGetSchedulerState( void);

描述:獲取調度器當前狀態。

在文件FreeRTOSConfig.h中,宏INCLUDE_xTaskGetSchedulerState或configUSE_TIMERS必須定義為1,此函數才有效。

返回值:返回值是以下常量之一(定義在task.h)

  • taskSCHEDULER_NOT_STARTED(未啟動)
  • taskSCHEDULER_RUNNING(正常運行)
  • taskSCHEDULER_SUSPENDED(掛起)

獲取任務總數

UBaseType_t uxTaskGetNumberOfTasks(void );

描述:獲取RTOS內核當前管理的任務總數。

返回值: 返回RTOS內核當前管理的任務總數。

包含所有就緒、阻塞和掛起狀態的任務。對於一個刪除的任務,如果它的堆棧空間還沒有被空閑任務釋放掉,則這個被刪除的任務也含在計數值中。

獲取所有任務詳情

void vTaskList( char *pcWriteBuffer );

描述:將每個任務的狀態、堆棧使用情況等以字符的形式保存到參數pcWriteBuffer指向的區域。vTaskList()函數調用usTaskGetSystemState()函數,然后將得到的信息格式化為程序員易讀的字符形式。輸出的內容例子如下圖所示,圖中State一欄中,B表示阻塞、R表示就緒、D表示刪除(等待清除內存)、S表示掛起或阻塞。

在文件FreeRTOSConfig.h中,宏configUSE_TRACE_FACILITY和configUSE_STATS_FORMATTING_FUNCTIONS必須定義為1,此函數才有效。

參數解析:保存信息的緩沖區(格式為ASCII);要足夠大,以容納生成的報告,每個任務大約需要40個字節。

注意:調用這個函數會掛起所有任務,這一過程可能持續較長時間,因此本函數僅在調試時使用。

獲取任務運行時間

void vTaskGetRunTimeStats( char*pcWriteBuffer );

描述:用於統計每個任務的運行時間。

參數解析:保存任務的運行時間信息(格式為ASCII);要足夠大,以容納生成的報告,每個任務大約需要40個字節。

注意:調用這個函數會掛起所有任務,這一過程可能持續較長時間,因此本函數僅在調試時使用。

要使用這個函數必須滿足一些條件,那就是必須有一個用於時間統計的定時器或計數器,這個定時器或計數器的精度要至少大於10倍的系統節拍周期。

這個定時器或計數器的配置以及獲取定時時間是由兩個宏定義實現的,這兩個宏一般在文件FreeRTOSConfig.h中定義。

  • 配置定時器或計數器的宏為portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(),
  • 獲取定時時間的宏為portGET_RUN_TIME_COUNTER_VALUE。

必須在文件FreeRTOSConfig.h中將宏configGENERATE_RUN_TIME_STATS和configUSE_STATS_FORMATTING_FUNCTIONS設置為1,此API函數才有效。

例子:

char RunTimeInfo[400];      //保存任務運行時間信息

//FreeRTOS時間統計所用的節拍計數器
volatile unsigned long long FreeRTOSRunTimeTicks;

//初始化TIM3使其為FreeRTOS的時間統計提供時基
void vConfigureTimeForRunTimeStats(void)
{
    //定時器3初始化,定時器時鍾為72M,分頻系數為72-1,所以定時器3的頻率
    //為72M/72=1M,自動重裝載為50-1,那么定時器周期就是50us
    FreeRTOSRunTimeTicks = 0;
    TIM3_Int_Init(50-1,72-1);   //初始化TIM3,包括對應的中斷代碼
}

unsigned long long getRunTimeCounterValue(void)
{
    return FreeRTOSRunTimeTicks;
}

void TIM3_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中斷
    {
        TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //清除中斷標志位
        FreeRTOSRunTimeTicks++;
    }
}

void RunTimeStats_task(void *pvParameters)
{
    while(1)
    {
        {
            memset(RunTimeInfo,0,400);              //信息緩沖區清零
            vTaskGetRunTimeStats(RunTimeInfo);      //獲取任務運行時間信息
            printf("任務名\t\t\t運行時間\t運行所占百分比\r\n");
            printf("%s\r\n",RunTimeInfo);
        }
        vTaskDelay(2000);
    }
}

在文件FreeRTOSConfig.h中,定義下列代碼:

extern void vConfigureTimerForRunTimeStats( void );
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vConfigureTimerForRunTimeStats()
#define portGET_RUN_TIME_COUNTER_VALUE() getRunTimeCounterValue()


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM