CPU工作的時(shí)候,各個(gè)任務(wù)運(yùn)行會(huì)占用CPU的資源,在Windows系統(tǒng)中我們可以通過(guò)任務(wù)管理器來(lái)看各任務(wù)(進(jìn)程)占用系統(tǒng)資源的情況。
那么,FreeRTOS怎么實(shí)現(xiàn)這個(gè)功能呢?
我們翻閱FreeRTOS官網(wǎng),查詢(xún)API文檔,在內(nèi)核控制函數(shù)部分找到了相關(guān)的函數(shù)。
文檔指出實(shí)現(xiàn)運(yùn)行時(shí)間功能需要配置外設(shè)定時(shí)器,即32板載定時(shí)器,計(jì)時(shí)器頻率應(yīng)為滴答計(jì)時(shí)器(1ms)的至少10倍。
傳入參數(shù)為pcWriteBUffer,其實(shí)是一個(gè)char類(lèi)型的數(shù)組用以存儲(chǔ)相關(guān)信息。
我們現(xiàn)在工程上調(diào)用這個(gè)函數(shù)。
char informationbuff[400];
void Get_info(void * pvParameters)
{
//vTaskGetRunTimeStats(informationbuff);
while(1)
{
if(KEY_Scan(0)==1)//按下按鍵1
{
memset(informationbuff,0,400);//清空數(shù)組內(nèi)容
vTaskGetRunTimeStats(informationbuff);//獲得運(yùn)行時(shí)間
printf("%s\r\n",informationbuff);//打印運(yùn)行時(shí)間
}
vTaskDelay(10);
}
}
上述任務(wù)的作用為檢測(cè)按鍵,如果按鍵按下即嘗試獲得運(yùn)行狀態(tài),并打印運(yùn)行狀態(tài)。
出現(xiàn)了如下錯(cuò)誤,顯示我們未定義該函數(shù),我們利用Ctrl+F全局尋找這個(gè)函數(shù)定義在哪里。
FreeRTOS\FreeRTOS.axf: Error: L6218E: Undefined symbol vTaskGetRunTimeStats (referred from main.o).
F:\Code\STM32Code\STM32F407_FreeRtos\FreeRTOS\FreeRTOS\Source\tasks.c(4539) : void vTaskGetRunTimeStats( char * pcWriteBuffer )
F:\Code\STM32Code\STM32F407_FreeRtos\FreeRTOS\FreeRTOS\Source\tasks.c(4552) : * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part
F:\Code\STM32Code\STM32F407_FreeRtos\FreeRTOS\FreeRTOS\Source\tasks.c(4557) : * vTaskGetRunTimeStats() has a dependency on the sprintf() C library
F:\Code\STM32Code\STM32F407_FreeRtos\FreeRTOS\FreeRTOS\Source\tasks.c(4567) : * through a call to vTaskGetRunTimeStats().
第一行內(nèi)容,即為函數(shù)定義的位置,我們跳轉(zhuǎn)過(guò)去查看其情況。
#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configUSE_TRACE_FACILITY == 1 ) )
void vTaskGetRunTimeStats( char * pcWriteBuffer )
{
TaskStatus_t * pxTaskStatusArray;
UBaseType_t uxArraySize, x;
configRUN_TIME_COUNTER_TYPE ulTotalTime, ulStatsAsPercentage;
省略后續(xù)內(nèi)容(防止說(shuō)水字?jǐn)?shù))
我們看到了函數(shù)模型以及相關(guān)注釋?zhuān)瑥念^中我們可以看出需要相關(guān)的宏定義,分別是configGENERATE_RUN_TIME_STATS、configUSE_STATS_FORMATTING_FUNCTIONS、configUSE_TRACE_FACILITY。
我們?cè)贔reeRTOSconfig.h文件(頭文件都行,方便管理)中添加使能這三個(gè)宏。
再次運(yùn)行,依舊報(bào)錯(cuò),從報(bào)錯(cuò)內(nèi)容來(lái)看,提醒我們?nèi)绻麑onfigGENERATE_RUN_TIME_STATS使能的話(huà),我們也必須定義portCONFIGURE_TIMER_FOR_RUN_TIME_STATS這個(gè)啟動(dòng)函數(shù),以及后面的一條報(bào)錯(cuò),我們必須定義portGET_RUN_TIME_COUNTER_VALUE時(shí)間的返回值。
#ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS
(import) #error If configGENERATE_RUN_TIME_STATS is defined then portCONFIGURE_TIMER_FOR_RUN_TIME_STATS must also be defined. portCONFIGURE_TIMER_FOR_RUN_TIME_STATS should call a port layer function to setup a peripheral timer/counter that can then be used as the run time counter time base.
#endif /* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS */
#ifndef portGET_RUN_TIME_COUNTER_VALUE
#ifndef portALT_GET_RUN_TIME_COUNTER_VALUE
(import) #error If configGENERATE_RUN_TIME_STATS is defined then either portGET_RUN_TIME_COUNTER_VALUE or portALT_GET_RUN_TIME_COUNTER_VALUE must also be defined. See the examples provided and the FreeRTOS web site for more information.
#endif /* portALT_GET_RUN_TIME_COUNTER_VALUE */
#endif /* portGET_RUN_TIME_COUNTER_VALUE *
啟動(dòng)函數(shù)即為外部定時(shí)器啟動(dòng)函數(shù),返回值則是一個(gè)數(shù)用以計(jì)算時(shí)間。
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() configTIM_START()//定時(shí)器1提供時(shí)間統(tǒng)計(jì)的時(shí)基,頻率為10K,即周期為100us
#define portGET_RUN_TIME_COUNTER_VALUE() FreeRTOSRunTime//時(shí)基
extern volatile unsigned long long FreeRTOSRunTime;
我們定義這兩個(gè)宏,本來(lái)這個(gè)括號(hào)是沒(méi)加上去的,后來(lái)發(fā)現(xiàn)其調(diào)用的時(shí)候是代括號(hào)的,所以定義宏的時(shí)候不帶括號(hào)就會(huì)出錯(cuò)
此外我們定義了long long 類(lèi)型的變量用以存儲(chǔ)我們的時(shí)間,加上extern表示這個(gè)變量的實(shí)際定義并不在頭文件中,之所以加上volatile是因?yàn)槲覀兊淖兞繒?huì)在不同的文件以及中斷中被修改(這種修改屬于意外修改),加上volatile標(biāo)志給系統(tǒng)提前吱會(huì)一聲。
之后,我們?nèi)UBEMX啟動(dòng)我們的定時(shí)器。
定時(shí)器我們選擇定時(shí)器1,時(shí)鐘源選擇內(nèi)部時(shí)鐘,分頻系數(shù)由于我們的單片機(jī)主頻是168MHZ,因此我們選擇168分頻,這樣子定時(shí)器頻率即為1MHZ,溢出值我們選擇為50,通過(guò)這樣的設(shè)置我們定時(shí)器的頻率就是20KHZ,是滴答定時(shí)器時(shí)鐘的20倍。
FreeRTOSRunTime也可以定義在這里。
之后我們將剛才宏定義的啟動(dòng)函數(shù)進(jìn)行定義,內(nèi)容則是重置計(jì)數(shù)器并啟動(dòng)定時(shí)器。
完成這步之后,我們還需要在主函數(shù)中啟用定時(shí)器1 的中斷并且編寫(xiě)相應(yīng)的中斷服務(wù)函數(shù),其內(nèi)容為FreeRTOSRunTime遞增。
/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == htim1.Instance)
{
FreeRTOSRunTime++;
}
}
/* USER CODE END 4 */
之后我們運(yùn)行程序觀(guān)察串口的輸出。
這樣子我們就可以打印出各個(gè)程序運(yùn)行時(shí)間以及占用系統(tǒng)資源的占比了。
-
cpu
+關(guān)注
關(guān)注
68文章
10769瀏覽量
210425 -
WINDOWS
+關(guān)注
關(guān)注
3文章
3509瀏覽量
88201 -
定時(shí)器
+關(guān)注
關(guān)注
23文章
3226瀏覽量
114144 -
FreeRTOS
+關(guān)注
關(guān)注
12文章
483瀏覽量
61849 -
STM32F407
+關(guān)注
關(guān)注
15文章
187瀏覽量
29288
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論