【RTOS】FreeRTOS中的任務堆棧溢出檢測機制


前言

注意:本筆記發佈時可能忘記補充查看dump方法,可使用TRACE32來查看dump時的各個任務信息,方便分析。

李柱明博客://www.cnblogs.com/lizhuming/p/15487221.html

任務堆棧

在 FreeRTOS 中,每個任務都擁有自己的堆棧,該堆棧的大小由創建任務時 xTaskCreate 函數的函數參數所決定。

堆棧溢出

當任務所使用的堆棧空間超出分配給它的空間時,則會發生堆棧溢出。

堆棧溢出可能修改超過合法訪問地址範圍外的數據,嚴重時會導致 Hardfault 令系統崩潰。

任務堆棧溢出檢測機制

API

在 FreeRTOS 中,也提供了一些 API 函數用來檢測任務堆棧的使用情況:

  • uxTaskGetStackHighWaterMark (TaskHandle_t xTask);

    • 返回自任務運行以來剩餘可用堆棧空間的最小值。
    • 開啟方法:在 FreeRTOSConfig.h 頭文件中使能宏:#define INCLUDE_uxTaskGetStackHighWaterMark 1

兩種堆棧溢出檢測方式

  1. 方式 1:

    1. 開啟方法:#define configCHECK_FOR_STACK_OVERFLOW 1
    2. 在任務切換是檢測任務棧指針是否越界,如果越界,在任務切換的時候觸發堆棧溢出鉤子函數。
  2. 方式 2:

    1. 開啟方法:#define configCHECK_FOR_STACK_OVERFLOW 2
    2. 在任務創建的時候將任務棧所有數據初始化為 0xA5,在任務切換時檢測任務棧底 16 個位元組是否都為 0xa5。

堆棧溢出鉤子函數

void vApplicationStackOverflowHook(TaskHandle_t xTask, signed char *pcTaskName)
{
    // 溢出後的操作
}

內核何時檢測任務堆棧溢出

任務上下文切換的時候做檢測:

  • 代碼說明:因為在 FreeRTOS 源碼 tasks.c 文件中可以查到 taskCHECK_FOR_STACK_OVERFLOW 在 void vTaskSwitchContext( void )函數中被調用了。
  • 滯後性:任務堆棧溢出時並不能馬上檢測到問題,因為任務堆棧溢出在任務上下文切換的時候才做檢測。

任務堆棧溢出檢測存在的局限性

根據兩種方式的原理及執行任務堆棧溢出的位置得出包括但不限於以下情境會檢測不到任務堆棧溢出:

  1. 任務執行的過程中出現過棧溢出,但任務切換前棧指針又恢復到了正常水平。(方式 1)

  2. 任務棧末尾的 16 個位元組沒有用到,即不會被修改,但是任務棧已經溢出了。(方式 2)

  3. 任務棧溢出後,把系統中的重要數據修改了導致系統直接進入 Hardfault。(方式 1、2)

    • 該方式進入了 Hardfault,就不能直接判斷是任務堆棧溢出的問題。