FreeRtos原始碼分析之vTaskList和vTaskGetRunTimeStats等除錯函式(五)
技術標籤:筆記
一、概述
在使用FreeRtos進行開發的過程中,我們通常需要了解系統的執行狀態、記憶體、CPU使用情況等資訊,來確保系統能夠長期穩定的執行。FreeRtos提供了許多這樣的介面,我們也可以通過閱讀FreeRtos相關的原始碼自己編寫需要的Debug介面。
通常我們需要用到的一些系統資訊為:
- 當前任務的剩餘記憶體;
- 當前任務歷史最小記憶體;
- 系統總的剩餘記憶體;
- 系統執行的總時間;
- 單個任務的執行時間;
- 每個任務佔用的CPU時間;
二、獲取系統資訊的相關函式
2.1、vTaskList
函式原型:void vTaskList( char * pcWriteBuffer );
函式功能:獲取系統中所有任務的任務名、任務狀態、優先順序、最小剩餘堆疊、建立序號相關資訊;
void PrintSysInfo(void)
{
char *buf = NULL;
char *fmt = "======================================\r\n\
name\tstatus\tpri\tmin-stack\tnum\r\n\
======================================\r\n";
buf = pvPortMalloc(512);
if(NULL == buf)return;
sprintf(buf,"%s" ,fmt);
vTaskList(buf+strlen(fmt));
d_printf("%s\r\n",buf);
vPortFree(buf);
}
列印結果:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-0watrBnC-1612168202907)(en-resource://database/622:1)]
status表示任務的執行狀態,有五種:
- x 執行狀態
- R Redy就緒狀態
- B Block阻塞狀態
- S Suspend掛起狀態
- D Deletedr任務已經被刪除
min-stack表示系統歷史剩餘最小堆疊,單位是字,比如33表示33*4=132byte。這個值越接近於0,任務記憶體溢位的可能性就越大;FreeRtos在建立任務的時候會將分配給任務的記憶體全部初始化為0xa5,如果某段記憶體被使用過,那麼其中的值就會被改變,FreeRtos獲取記憶體剩餘空間的原始碼如下:
static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte )
{
uint32_t ulCount = 0U;
/*任務的記憶體在任務建立時會被填充為tskSTACK_FILL_BYTE,在任務執行時會被填充為其它內容*/
while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE )
{
pucStackByte -= portSTACK_GROWTH;
ulCount++;
}
/*返回值的單位為字而不是位元組*/
ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */
return ( configSTACK_DEPTH_TYPE ) ulCount;
}
num表示任務建立的序號,一般按照任務的建立順序編號。
2.2、vTaskGetRunTimeStats
函式原型: void vTaskGetRunTimeStats( char * pcWriteBuffer );
函式功能:獲取每個任務的執行時間,並統計每個任務佔用CPU的時間;
示例:
void PrintSysTimeInfo(void)
{
#if configGENERATE_RUN_TIME_STATS
char *buf = NULL;
char *fmt = "======================================\r\n\
任務名\t執行時間\tcpu佔用率\r\n\
======================================\r\n";
buf = pvPortMalloc(512);
if(NULL == buf)return;
sprintf(buf,"%s",fmt);
vTaskGetRunTimeStats(buf+strlen(fmt));
d_printf("%s\r\n",buf);
vPortFree(buf);
#endif
}
列印結果:
從結果中可以看出,系統中一共有四個任務,其中空閒任務IDLE執行的時間最長,為10902ms,佔用了98%的CPU執行時間。
FreeRtos預設是不支援這個功能的,如果想要使用這個功能,就需要自己使用硬體定時器來實現。使用前應該實現以下三個巨集:
#define configGENERATE_RUN_TIME_STATS 1//開啟執行時間統計功能
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS configureTimerForRunTimeStats//初始化硬體定時器
#define portGET_RUN_TIME_COUNTER_VALUE getRunTimeCounterValue//獲取定時器的計數值
2.3、uxTaskGetStackHighWaterMark
函式原型:UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
函式功能:獲取指定任務歷史最小剩餘堆疊,返回的值越小,任務越容易記憶體溢位
2.4、eTaskGetState
函式原型:eTaskState eTaskGetState( TaskHandle_t xTask );
函式功能:獲取任務狀態
2.5、uxTaskPriorityGet
函式原型:UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask )
函式功能:獲取任務優先順序
2.6、xTaskGetTickCount
函式原型:TickType_t xTaskGetTickCount( void )
函式功能:獲取任務的系統節拍數,使用者可以根據這個值計算系統執行的總時間,但是需要注意TickType_t的資料型別,當系統時鐘節拍是1ms時,系統執行一個多月後時間會溢位。
2.7、uxTaskGetTaskNumber
函式原型:UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask )
函式功能:獲取任務建立的序號,任務在建立時通常會按照建立順序給任務一個編碼,比如第一個建立的任務序號為1,第二個為2,以此類推。這個值也可以通過vTaskSetTaskNumber函式來修改。
FreeRtos帶註釋原始碼Gitee地址:https://gitee.com/zBlackShadow/FreeRtos10.4.3.git