概述
1.概念
这里所说的堆栈,是针对单片机所说的“堆”与“栈”,指的是内存中一片特殊用途的区域。而不是数据结构中的堆栈(虽然其实规则一样)。
这里所说的内存,是指RAM,RAM包括SRAM,DRAM等。而不是什么手机内存卡之类。
这里所说的flash,指的是用作为ROM的存储器,保存代码与常量数据。而不是动画制作。。。
栈的生长方向:指的是入栈方向,从高地址向低地址生长叫做向下生长,或逆向生长;反过来就叫向上生长,或正向生长。STM32的栈是向下生长。
2.内存中的堆栈安排
确切地说,是keil mdk根据STM32的特性,对stm32的RAM甚至flash进行部署。
编译工程后,在生成的.map文件里可以看到具体的安排。双击工程界面的工程根目录文件夹图标,可以打开.map文件。如果找不到文件,可以在option->listing->linker listing 里勾选 Memory map;
map文件内的两部分Image Symbol Table与Memory Map of the image列出了RAM与ROM的内容,最后还有一些统计。
map文件跟下图有很大关系:(这里虽然我使用的是GD32,但跟STM32一样)
3.MAP文件与堆栈
网上你有可能会看到这些说法:
(1)栈区(stack):由编译器自动分配和释放,存放函数的参数与返回值、局部变量等,其操作方式类似于数据结构中的栈。
(2)堆区(heap):由程序员分配管理。
(3)全局区与静态区:存储全局变量和静态变量,其中初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。
(4)文字常量区:常量字符串存放。
(5)程序代码区:存放程序代码。
可能这样还是有点不明不白,那么打开map文件你就会很具体地看到这些。
Execution Region RW_IRAM1:程序运行时的内存分布
0X20000000是RAM开始地址。可以看到各段的分布。从低地址到高地址,分别为:data段,bss段,heap段,stack段。包含对应上面所说的(1)(2)(3)。
0X08000000是ROM(flash)开始地址。可以看到constdata(常量),和函数代码,对应上面的(4)(5);
其中,data指的是初始化不为0的全局或静态(static)变量。bss指的是没有初始化,或者初始化为0的全局或静态变量。一开始我也不理解什么初始化之类,感觉莫名其妙甚至自相矛盾。其实知道为什么这么安排就很容易理解了。
因为全局与静态变量的初始值,是需要保存下来,其基本可以分为三大类,一种是等于0的,一种是不等于0,还有一种是没有初始值的。这些都是需要记录下来保存在镜像文件里面,再烧录到单片机的flash里(当然非要写到ram也可以)。为了节省空间,就把等于0的变量和没有初始值的变量归为一类,都当做初始值等于0的变量处理。因为这些变量的初始值都为0,所以记录也方便,节省不少空间。比如定义一个500字节的全局数组,要是初始值已经定义,那么镜像文件也需要相应大小的空间记录下来。但是如果全部为0,或者没有定义初始值。那么,从原理上来说,只需记录数组长度,赋予BSS“属性”,就OK得。
程序在开始运行的时候,一般要做内存搬运的操作,比如将data段,bss段,heap段,stack段初始化为对应的值。
由此也可知,在keil mdk中,没有初始值的全局变量或者静态变量,其实等于0。但局部普通变量并不是,一定要初始化再使用。
上图是符号表中Global Symbols的一部分,可以看到内存开始地址0X20000000,放置的是SystemCoreClock这个变量,这个是系统时钟频率,初始时不为0,后面记上(.data)。后面的Boot_buf变量,大小为1024,标记为(.bss)。
上图是符号表中Local Symbols的一部分。可以看到另外一些变量符号,还能看到,constdata(常量)是保持着flash里(地址为0x08XX XXXX)。
最后
以上就是欣慰麦片为你收集整理的说说STM32的堆栈与内存的全部内容,希望文章能够帮你解决说说STM32的堆栈与内存所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复