弄清楚如何為嵌入式應用程序和其中的任務確定堆棧的大小可能具有挑戰性。在許多情況下,開發人員會選擇一個他們認為應該足夠的值,這些估計有時有點短,大部分時間是粗略估計,很少出現。雖然嵌入式開發人員在整個開發周期中應該監控他們的堆棧使用情況,但有時開發人員應該執行最壞情況的堆棧分析,例如:
它們在 RAM 上運行得非常危險
需要提交新的代碼版本
他們正在最終確定用于生產的固件
在這篇文章中,我將討論開發人員可以執行最壞情況堆棧分析的三種不同方式。
技巧 1 – 手工計算
在過去,嵌入式軟件開發人員過去不得不手動計算他們的堆棧使用情況,這可能是一項棘手的工作。為了手動計算堆棧使用量,開發人員需要知道:
他們要進行多少次函數調用
在每個函數中將存儲在堆棧中的局部變量
將存儲在堆棧中的返回地址的大小
將存儲在堆棧中的局部變量的大小
如果在執行期間發生中斷,中斷幀將有多大
可能發生的嵌套中斷數
正如你可以想象的那樣,找到所有這些值并在進行更改時繼續跟蹤它們可能非常耗時且容易出錯,這就是為什么不再推薦這種方法的原因,但嵌入式開發人員嘗試一次以更深入地了解其他技術正在做什么仍然很有用。
技巧 2 – 使用靜態代碼分析器
許多靜態代碼分析器可用于估計最壞情況下的堆棧使用情況。在代碼分析期間,該工具將確定函數深度以及我們之前列出的許多項目。使用靜態分析器的好處在于它不僅執行堆棧分析,而且還檢查代碼的潛在問題。它在幾秒鐘內運行,這使開發人員無需手動計算堆棧使用情況。
雖然使用靜態代碼分析器來獲取最壞情況下的堆棧使用情況是一個不錯的方法,但開發人員需要注意幾個潛在問題。這些包括:
取消引用函數指針不計為函數調用
不考慮中斷幀
了解你的工具如何處理這些項目非常重要。為了獲得準確的結果,在靜態代碼分析期間,必須經常使用宏或編譯器符號有條件地將函數指針編譯成函數調用。然后,你還必須添加你認為的中斷堆棧使用情況。小問題,但在任何分析中都需要理解。
技術#3 – 測試和測量
對于最壞情況堆棧分析,嵌入式開發人員經常提倡的技術是測試和測量系統。許多開發環境現在都有執行OS-Aware調試的工具,這些工具將密切監視RTOS性能,包括應用程序運行時的最大堆棧使用量。下圖中可以看到一個很好的示例,該示例來自使用ThreadX的Renesas Synergy平臺的e2 Studio。
如你所見,每個線程(任務)都與內存位置、堆棧指針和最大堆棧使用量一起列出。我們甚至可以看到堆棧分配了多少內存。這不僅為開發人員提供了一種很好的方式來密切關注他們的堆棧使用情況,而且還可以確定他們的最大堆棧使用量是多少。
開發人員確實需要小心呈現給他們的最大值。重要的是,在他們的系統處于最大壓力下時進行讀數。對于基于RTOS的應用程序,中斷幀通常存儲在系統堆棧中,因此我們無需考慮調整每個線程的大小以有足夠的內存來應對中斷風暴。
結論
無論你使用哪種技術來確定你的堆棧使用情況,稍微加大堆棧大小仍然是一個好習慣。有可能在測試期間從未實現過最壞的情況,這可能會在系統在現場時將系統設置為堆棧溢出。
在本文中,我們研究了幾種可用于計算最壞情況堆棧使用情況的技術。開發人員還可以使用其他幾種方法,正如我們所看到的,使用現代工具在整個開發周期中監控堆棧使用情況非常容易。建議嵌入式開發人員在編寫軟件時,相應地監控和調整堆棧大小,以實現最高效的系統。