文章首發於浩瀚先森博客
#棧的理解
一個程序大體上講都是由變量和函數組合而成,變量有全局變量和局部變量,還有函數間傳值的參數以及返回值。
Stack是為了程序運行過程中臨時保存所需數據而在內存里分配的一小塊空間。保存的數據類型一般情況下包括以下幾種:
1. 函數中聲明的局部變量以及參數
2. 函數返回值
3. 中斷時CPU 寄存器值
4. 函數運行后返回的地址
比方說下面的例子,函數里聲明的局部變量保存在stack里面,在該函數中調用其他函數的時候其他函數中的局部變量也會添加到stack里保存。

從IAR編譯器里確定Stack。
在IAR編譯器里通過使用Stack Windows來確認stack的使用量和stack中保存的值。(View->Stack->Stack Window)
用Bar Graph形式來查看stack的話stack中的數據和地址等信息都能查看的到。

* 上面為了確定stack最大使用量,通過菜單Tools->Options->Stack中的 Enable graphical stack display and stack usage tracking 選項來檢查。
#如何設定stack大小
Stack的大小是由開發者直接設置,編譯時由編譯器分配空間。
Stack大小分配不足的話保存的變量要么overwrite,要么程序異常終止。相反,如果空間分配太大又浪費。
所以程序里要需要多大的stack空間必須准確的計算把握。
在IAR Compiler里提供了預測stack大小的stack使用量分析功能(stack usage analysis)。
(Project Option -> Linker -> Advanced -> Enable stack usage analysis)

stack使用量在map文件里可以查看得到,前提是你要打開生成map文件的功能,如下:

編譯程序后,map文件在project output文件夾下

打開map文件可以看到stack usage情況,如下:

程序里使用最大的stack大小為108bytes,中斷使用的stack大小為40bytes和16bytes。 所以程序里要設置比108+400+16大的stack空間才型。
CSTACK Size >= maxstack("Program entry") + totalstack("interrupt") + safety margin(100);
類似上面情況 需要分配108 + 40 + 16 + 100 = 264Byte 的stack空間。
#設置stack大小
程序需要的stack大小前面已經計算出來了,那么怎么設置呢?
如下圖,在項目的Linker選項里設置。
Linker的 Config選項卡里點擊Edit變更設置。

Stack/Heap Sizes選項卡里變更CSTACK的大小.

或者是用文本編輯器打開icf文件直接修改stack大小,如下圖

