FreeRTOS — 任務棧大小確定及其溢出檢測


以下內容轉載自安富萊電子:http://forum.armfly.com/forum.php

給任務分配多大的棧空間,一直是初學者比較頭疼的問題, 下面就主要講解如何解決此問題。

1  任 務 棧 大 小 的 確 定

  在基於 RTOS 的應用設計中,每個任務都需要自己的棧空間,應用不同,每個任務需要的棧大小也是不同的。將如下的幾個選項簡單的累加就可以得到一個粗略的棧大小:

一般來說,用戶可以事先給任務分配一個大的棧空間,然后通過調試的方法打印任務棧的使用情況,運行一段時間就會有個大概的范圍了。這種方法比較簡單且實用些。

 

 

2 、什 么 是 棧 溢  出

棧溢出 — 簡單的說就是用戶分配的棧空間不夠用了,溢出了。舉一個簡單的實例,棧生長方向從高地址向低地址生長(M4 和 M3 是這種方式)。

 

(1) 上圖標識 1 的位置是 RTOS 的某個任務調用了函數 test()前的 SP 棧指針位置。

(2) 上圖標識 2 的位置是調用了函數 test 需要保存返回地址到棧空間。這一步不是必須的,對於 M3和 M4 內核是先將其保存到 LR 寄存器中,如果 LR 寄存器中有保存上一級函數的返回地址,需要將 LR 寄存器中的內容先入棧。

(3) 上圖標識 3 的位置是局部變量 int i 和 int array[10]占用的棧空間,但申請了棧空間后已經越界了。這個就是所謂的棧溢出了。如果用戶在函數 test 中通過數組 array 修改了這部分越界區的數據且這部分越界的棧空間暫時沒有用到或者數據不是很重要,情況還不算嚴重,但是如果存儲的是關鍵數據,會直接導致系統崩潰。

 

(4) 上圖標識 4 的位置是局部變量申請了棧空間后,棧指針向下偏移(返回地址+變量 i+10 個數組元素)*4 =48 個字節。

(5) 上圖標識 5 的位置可能是其它任務的棧空間,也可能是全局變量或者其它用途的存儲區,如果 test函數在使用中還有用到棧的地方就會從這里申請,這部分越界的空間暫時沒有用到或者數據不是很重要,情況還不算嚴重,但是如果存儲的是關鍵數據,會直接導致系統崩潰。

3 、FreeRTOS的 棧 溢 出 檢 測 機 制

 FreeRTOS 提供了兩種棧溢出檢測機制,這兩種檢測都是在任務切換時才會進行:

 方法一

  在任務切換時檢測任務棧指針是否過界了,如果過界了,在任務切換的時候會觸發棧溢出鈎子函數。

  void vApplicationStackOverflowHook( TaskHandle_t xTask,signed char *pcTaskName );

用戶可以在鈎子函數里面做一些處理。這種方法不能保證所有的棧溢出都能檢測到。比如任務在執行的過程中出現過棧溢出。任務切換前棧指針又恢復到了正常水平,這種情況在任務切換的時候是檢測不到的。又比如任務棧溢出后,把這部分棧區的數據修改了,這部分棧區的數據不重要或者暫時沒有用到還好,但如果是重要數據被修改將直接導致系統進入硬件異常,這種情況下,棧溢出檢測功能也是檢測不到的。

  使用方法一需要用戶在 FreeRTOSConfig.h 文件中配置如下宏定義:

  #define configCHECK_FOR_STACK_OVERFLOW 1

 方法二

  任務創建的時候將任務棧所有數據初始化為 0xa5,任務切換時進行任務棧檢測的時候會檢測末尾的 16 個字節是否都是 0xa5,通過這種方式來檢測任務棧是否溢出了。相比方法一,這種方法的速度稍慢些,但是這樣就有效地避免了方法一里面的部分情況。不過依然不能保證所有的棧溢出都能檢測到,比如任務棧末尾的 16 個字節沒有用到,即沒有被修改,但是任務棧已經溢出了,這種情況是檢測不到的。另外任務棧溢出后,任務棧末尾的 16 個字節沒有修改,但是溢出部分的棧區數據被修改了,這部分棧區的數據不重要或者暫時沒有用到還好,但如果是重要數據被修改將直接導致系統進入硬件異常,這種情況下,棧溢出檢測功能也是檢測不到的。

  使用方法二需要用戶在 FreeRTOSConfig.h 文件中配置如下宏定義:

  #define configCHECK_FOR_STACK_OVERFLOW 2

  除了 FreeRTOS 提供的這兩種棧溢出檢測機制,還有其它的棧溢出檢測機制,可以在 Mircrium 官方發布的:這個博文中學習。

  鈎子函數

  鈎子函數的主要作用就是對原有函數的功能進行擴展,用戶可以根據自己的需要往里面添加相關的測試代碼,可以在 FreeRTOS 工程中檢索這個鈎子函數 vApplicationStackOverflowHook 所在的位置。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM