单片机常用的堆栈知识汇总
先来聊聊为什么要说这个吧,因为今天代码首先遇到在运行Freertos代码,只能运行一个task,另一个task无法运行,debug后,报hardfault错误,查询后,可能是堆栈分配异常。查阅资料后,修改代码,又遇到了代码No space in execution regions with .问题,单片机资源有限,报这个错误,是我之前并没有考虑过的,因此做出这个汇总,以便阅者和作者自查。
首先关于堆栈空间分配问题
这里0x400,默认是1024(1K)字节(Byte)大小。
讲到字节,我们就来聊聊一点基础知识:
1字节=8位(1 byte = 8bit)
1字=2字节(1 word = 2 byte)
char = uint_8 = 1字节
uint_16 = u16 = 2字节
int_32 = int = 4字节
来举个例子 char a[1024],也就是1024字节空间
接下来继续:
栈(stack)空间,用于局部变量,函数调时现场保护和返回地址,函数的形参等。
堆(heap)空间,主要用于动态内存分配,也就是说用 malloc,calloc, realloc 等函数分配的变量空间是在堆上。
全局区(static)
文字常亮区程序代码区
我们再来聊聊一点基础知识:
- stm32f103c8t6 小容量芯片 RAM容量为20KB,FLASH容量为64KB
使用CubeMX对该芯片创建一个工程,然后点击魔术棒可以看到:
它的内置ROM起始地址为0X0800 0000,大小为0X10000,也就是FLASH的大小为:0X10000个字节 = 65536个字节 = 64k个字节 = 64kBytes。
它的内置RAM起始地址为0X2000 0000,大小为0X5000,也就是RAM的大小为:0X5000个字节 = 20480个字节 = 20k个字节 = 20kBytes
接下来继续:
我们如何知道程序占用内存大小:
- 可以在编译时看到
Program Size: Code=23472 RO-data=852 RW-data=3252 ZI-data=16700
-
可以在MDK-ARM\XXX(你的项目名)找到.map文件<前提是你在魔术棒的Listing,勾选了.map文件生成>,具体如下:
==============================================================================
Total RO Size (Code + RO Data) 24324 ( 23.75kB) Total RW Size (RW Data + ZI Data) 19952 ( 19.48kB) Total ROM Size (Code + RO Data + RW Data) 24596 ( 24.02kB)
==============================================================================
以上名词我只捡我关注的简单解释下,详细解释看参考1。
-
RO_data:Read Only data,包括const关键字定义的变量,在flash区
-
RW_data:Read Write data,包括C语言中定义的全局变量中未初始化为0的数据,运行时在RAM区,不运行时在flash区
-
ZI_data:Zero Initialie data,即0初始化数据,即RW_data的0初始化变量,在RAM区
-
总结:Code + RO_data + RW_data(RO + RW)三种类型需要占用 Flash 空间(未运行时)。RAM不需要用到。
接下来是我们的堆和栈:
- ZI-data 的栈空间(Stack)及堆空间(Heap):在C语言中,函数内部定义的局部变量属于栈空间,进入函数的时候会向栈空间申请内存给局部变量,退出时释放局部变量,归还内存空间。而使用malloc动态分配的变量属于堆空间。在程序中的栈空间和堆空间都是属于ZI-data区域的,这些空间都会被初始值化为0值。编译器给出的ZI-data占用的空间值中包含了堆栈的大小(经实际测试,若程序中完全没有使用malloc动态申请堆空间,编译器会优化,不把堆空间计算在内)。
总结想要让一个程序正常运行。
- 芯片的 Flash 大小 要大于 Code + RO-data + RW-data 的大小;
- 芯片的 RAM 大小 要大于 RW-data + ZI_data 的大小。
且视他人之疑目如盏盏鬼火,大胆去走你的夜路。 ——By史铁生
参考1 :STM32深入系列01——内存简述(Flash和SRAM)https://blog.csdn.net/weixin_46253745/article/details/130032941
参考2: STM32 堆栈大小的设置及分析 https://blog.csdn.net/qq_27747359/article/details/109106895