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