使用freeRTOS時,創(chuàng)建的每一個任務(wù)都需要分配任務(wù)的堆??臻g,這些堆??臻g一般都是使用者根據(jù)任務(wù)的情況大致分配的。使用者往往不能直接知道分配的任務(wù)堆??臻g是否足夠任務(wù)運(yùn)行使用,有時候可能會不夠,在運(yùn)行過程中就出現(xiàn)了堆棧溢出,導(dǎo)致程序出現(xiàn)各種各樣的奇怪問題,出現(xiàn)問題之后可能一時半會還難以找出來。
這種情況如果能有一種檢測手段能夠知道任務(wù)在運(yùn)行過程中堆棧的使用情況或者剩余情況,那就可以很好的把握任務(wù)堆棧的情況,也可以在一開始就避免堆棧溢出這樣的問題發(fā)生,將來項(xiàng)目產(chǎn)品上線了也避免了這樣的風(fēng)險存在!
值得開心的是,freeRTOS真的有提供這樣的檢測堆棧剩余量的功能。下面介紹怎么使用freeRTOS的任務(wù)堆棧的剩余量的方法。
1、允許堆棧檢測 API 的使用
freeRTOS中堆棧使用剩余量的檢測使用的是 uxTaskGetStackHighWaterMark ,使用這個函數(shù)需要先將一個宏定義為 1 才能使用堆棧檢測功能。
打開 FreeRTOSConfig.h 文件,找到宏
INCLUDE_uxTaskGetStackHighWaterMark 并將其值定為 1,如下:
#define INCLUDE_uxTaskGetStackHighWaterMark 1
這個宏定義為 1 之后再文件 task.c 中就可以看到函數(shù) uxTaskGetStackHighWaterMark 生效了,說明這個函數(shù)已經(jīng)是可以使用的狀態(tài)了。
2、uxTaskGetStackHighWaterMark 函數(shù)的說明
freeRTOS 中任務(wù)堆棧的檢測函數(shù)的函數(shù)原型如下:
UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )
{
TCB_t * pxTCB;
uint8_t * pucEndOfStack;
UBaseType_t uxReturn;
pxTCB = prvGetTCBFromHandle( xTask );
#if portSTACK_GROWTH < 0
{
pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
}
#else
{
pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
}
#endif
uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack );
return uxReturn;
}
函數(shù)描述:
函數(shù)參數(shù):
xTask:需要檢查的堆棧情況的任務(wù)句柄。這個句柄在創(chuàng)建任務(wù)時就可以知道的。
注意:將 xTask 設(shè)置為 NULL 的話檢測的就是調(diào)用這個函數(shù)的任務(wù)堆棧情況。
函數(shù)返回值:
自創(chuàng)建 xTask 這個任務(wù)以來,已存在的最小可用堆??臻g量(以字為單位)。即返回的值是以字為單位的堆棧剩余量(例如,在 32 位機(jī)器上,返回值 1 表示任務(wù)堆棧中未使用的堆棧還剩余 4 個字節(jié))。如果返回值為零,則該任務(wù)可能堆棧已經(jīng)溢出。如果返回值接近零,則任務(wù)接近堆棧溢出。
特別注意:
freeRTOS中還有一個 uxTaskGetStackHighWaterMark2() ,這個是 uxTaskGetStackHighWaterMark() 的另外一個版本,它返回一個用戶可定義的類型,主要用在一些 8 位架構(gòu)上數(shù)據(jù)類型寬度有限制的MCU中。
3、堆棧剩余量檢測的使用方法
3.1、任務(wù)自己檢測自己的堆棧情況
如果 UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) 的參數(shù) xTask 設(shè)置為NULL,則哪個任務(wù)調(diào)用這個函數(shù)檢測的就是哪個任務(wù)的堆棧情況,如下:
void vTask1( void * pvParameters )
{
UBaseType_t uxHighWaterMark;
// 檢測任務(wù)使用前的堆棧情況
uxHighWaterMark = uxTaskGetStackHighWaterMark( NULL );
for( ;; )
{
... // 其他代碼
...
...
vTaskDelay( 1000 );
// 檢測任務(wù)運(yùn)行之后的堆棧剩余情況
uxHighWaterMark = uxTaskGetStackHighWaterMark( NULL );
}
}
3.2、使用任務(wù)單獨(dú)檢測任務(wù)的堆棧情況
可以使用一個任務(wù)單獨(dú)進(jìn)行項(xiàng)目中的任務(wù)堆棧的情況進(jìn)行檢測,如下:
void TaskStackDetect_Task1( void * pvParameters )
{
UBaseType_t uxHighWaterMark;
for( ;; )
{
uxHighWaterMark = uxTaskGetStackHighWaterMark( 任務(wù)句柄1 );
print(uxHighWaterMark);
uxHighWaterMark = uxTaskGetStackHighWaterMark( 任務(wù)句柄2 );
print(uxHighWaterMark);
uxHighWaterMark = uxTaskGetStackHighWaterMark( 任務(wù)句柄3 );
print(uxHighWaterMark);
......
uxHighWaterMark = uxTaskGetStackHighWaterMark( 任務(wù)句柄n );
print(uxHighWaterMark);
vTaskDelay( 1000 );
}
}
3.3、使用軟件定時器檢測任務(wù)堆棧的情況
檢測堆棧的剩余情況也可以使用freeRTOS中提供的軟件定時器服務(wù),創(chuàng)建一個軟件定時器,然后在軟件定時器的回調(diào)函數(shù)里面定時進(jìn)行檢測即可,原理和使用一個任務(wù)檢測是一樣的。如下:
void TaskStackDetect_Callback(TimerHandle_t pxTimer)
{
UBaseType_t uxHighWaterMark;
uxHighWaterMark = uxTaskGetStackHighWaterMark( 任務(wù)句柄1 );
print(uxHighWaterMark);
uxHighWaterMark = uxTaskGetStackHighWaterMark( 任務(wù)句柄2 );
print(uxHighWaterMark);
uxHighWaterMark = uxTaskGetStackHighWaterMark( 任務(wù)句柄3 );
print(uxHighWaterMark);
......
uxHighWaterMark = uxTaskGetStackHighWaterMark( 任務(wù)句柄n );
print(uxHighWaterMark);
}
-
堆棧
+關(guān)注
關(guān)注
0文章
182瀏覽量
19753 -
FreeRTOS
+關(guān)注
關(guān)注
12文章
484瀏覽量
62139 -
空間
+關(guān)注
關(guān)注
2文章
48瀏覽量
13629
發(fā)布評論請先 登錄
相關(guān)推薦
評論