目錄
前言
任務堆棧
堆棧溢出
任務堆棧溢出檢測機制
API
兩種堆棧溢出檢測方式
堆棧溢出鈎子函數
核心何時檢測任務堆棧溢出
任務堆棧溢出檢測存在的局限性
注意:本筆記釋出時可能忘記補充檢視dump方法,可使用TRACE32來檢視dump時的各個任務資訊,友善分析。
李柱明部落格:https://www.cnblogs.com/lizhuming/p/15487221.html
在 FreeRTOS 中,每個任務都擁有自己的堆棧,該堆棧的大小由建立任務時 xTaskCreate 函數的函數參數所決定。
當任務所使用的堆棧空間超出配置設定給它的空間時,則會發生堆棧溢出。
堆棧溢出可能修改超過合法通路位址範圍外的資料,嚴重時會導緻 Hardfault 令系統崩潰。
在 FreeRTOS 中,也提供了一些 API 函數用來檢測任務堆棧的使用情況:
<code>uxTaskGetStackHighWaterMark (TaskHandle_t xTask);</code> :
傳回自任務運作以來剩餘可用堆棧空間的最小值。
開啟方法:在 FreeRTOSConfig.h 頭檔案中使能宏:<code>#define INCLUDE_uxTaskGetStackHighWaterMark 1</code>
方式 1:
開啟方法:<code>#define configCHECK_FOR_STACK_OVERFLOW 1</code>
在任務切換是檢測任務棧指針是否越界,如果越界,在任務切換的時候觸發堆棧溢出鈎子函數。
方式 2:
開啟方法:<code>#define configCHECK_FOR_STACK_OVERFLOW 2</code>
在任務建立的時候将任務棧所有資料初始化為 0xA5,在任務切換時檢測任務棧底 16 個位元組是否都為 0xa5。
任務上下文切換的時候做檢測:
代碼說明:因為在 FreeRTOS 源碼 tasks.c 檔案中可以查到 taskCHECK_FOR_STACK_OVERFLOW 在 void vTaskSwitchContext( void )函數中被調用了。
滞後性:任務堆棧溢出時并不能馬上檢測到問題,因為任務堆棧溢出在任務上下文切換的時候才做檢測。

根據兩種方式的原理及執行任務堆棧溢出的位置得出包括但不限于以下情境會檢測不到任務堆棧溢出:
任務執行的過程中出現過棧溢出,但任務切換前棧指針又恢複到了正常水準。(方式 1)
任務棧末尾的 16 個位元組沒有用到,即不會被修改,但是任務棧已經溢出了。(方式 2)
任務棧溢出後,把系統中的重要資料修改了導緻系統直接進入 Hardfault。(方式 1、2)
該方式進入了 Hardfault,就不能直接判斷是任務堆棧溢出的問題。