前言
注意:本筆記釋出時可能忘記補充檢視dump方法,可使用TRACE32來檢視dump時的各個任務資訊,方便分析。
李柱明部落格:https://www.cnblogs.com/lizhuming/p/15487221.html
任務堆疊
在 FreeRTOS 中,每個任務都擁有自己的堆疊,該堆疊的大小由建立任務時 xTaskCreate 函式的函式引數所決定。
堆疊溢位
當任務所使用的堆疊空間超出分配給它的空間時,則會發生堆疊溢位。
堆疊溢位可能修改超過合法訪問地址範圍外的資料,嚴重時會導致 Hardfault 令系統崩潰。
任務堆疊溢位檢測機制
API
在 FreeRTOS 中,也提供了一些 API 函式用來檢測任務堆疊的使用情況:
-
uxTaskGetStackHighWaterMark (TaskHandle_t xTask);
:- 返回自任務執行以來剩餘可用堆疊空間的最小值。
- 開啟方法:在 FreeRTOSConfig.h 標頭檔案中使能巨集:
#define INCLUDE_uxTaskGetStackHighWaterMark 1
兩種堆疊溢位檢測方式
-
方式 1:
- 開啟方法:
#define configCHECK_FOR_STACK_OVERFLOW 1
- 在任務切換是檢測任務棧指標是否越界,如果越界,在任務切換的時候觸發堆疊溢位鉤子函式。
- 開啟方法:
-
方式 2:
- 開啟方法:
#define configCHECK_FOR_STACK_OVERFLOW 2
- 在任務建立的時候將任務棧所有資料初始化為 0xA5,在任務切換時檢測任務棧底 16 個位元組是否都為 0xa5。
- 開啟方法:
堆疊溢位鉤子函式
void vApplicationStackOverflowHook(TaskHandle_t xTask, signed char *pcTaskName)
{
// 溢位後的操作
}
核心何時檢測任務堆疊溢位
任務上下文切換的時候做檢測:
- 程式碼說明:因為在 FreeRTOS 原始碼 tasks.c 檔案中可以查到 taskCHECK_FOR_STACK_OVERFLOW 在 void vTaskSwitchContext( void )函式中被呼叫了。
- 滯後性:任務堆疊溢位時並不能馬上檢測到問題,因為任務堆疊溢位在任務上下文切換的時候才做檢測。
任務堆疊溢位檢測存在的侷限性
根據兩種方式的原理及執行任務堆疊溢位的位置得出包括但不限於以下情境會檢測不到任務堆疊溢位:
-
任務執行的過程中出現過棧溢位,但任務切換前棧指標又恢復到了正常水平。(方式 1)
-
任務棧末尾的 16 個位元組沒有用到,即不會被修改,但是任務棧已經溢位了。(方式 2)
-
任務棧溢位後,把系統中的重要資料修改了導致系統直接進入 Hardfault。(方式 1、2)
- 該方式進入了 Hardfault,就不能直接判斷是任務堆疊溢位的問題。