栈的理解以及如何计算程序所需栈的大小并在IAR中设置栈
文章首发于浩瀚先森博客
#栈的理解
一个程序大体上讲都是由变量和函数组合而成,变量有全局变量和局部变量,还有函数间传值的参数以及返回值。
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大小,如下图