历史上的今天
返回首页

历史上的今天

今天是:2025年04月16日(星期三)

正在发生

2019年04月16日 | STM32堆和栈(Heap & Stack)的资料理解

2019-04-16 来源:eefocus

源起:在移植cjson的过程中,解析json包的时候发现动态内存分配不足而导致解析失败,为解决这一问题,而深入了解stm32的堆和栈。


stm32的存储器结构。


Flash,SRAM寄存器和输入输出端口被组织在同一个4GB的线性地址空间内。可访问的存储器空间被分成8个主要块,每个块为512MB。FLASH存储下载的程序。SRAM是存储运行程序中的数据。


而SRAM一般分这几个部分:


静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存放静态数据、全局数据和常量。


栈区:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限,局部变量太大有可能造成栈溢出。


堆区:亦称动态内存分配,是编译器调用动态内存分配的内存区域。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在适当的时候用free或delete释放内存。动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存。 但是,良好的编程习惯是:如果某动态内存不再使用,需要将其释放掉,否则,我们认为发生了内存泄漏现象。


注意地方:


堆栈的大小在编译器编译之后是不知道的,只有运行的时候才知道,所以需要注意一点,就是别造成堆栈溢出了。。。不然就等着hardfault找你吧。


是所有在处理的函数,包括函数嵌套,递归,等等,都是从这个“栈”里面,来分配的。所以,如果栈大小为2K,一个函数的局部变量过多,比如在函数里面定义一个u8 buf[512],这一下就占了1/4的栈大小了,再在其他函数里面来搞两下,程序崩溃是很容易的事情,这时候,一般你会进入到hardfault….这是初学者非常容易犯的一个错误.切记不要在函数里面放N多局部变量,尤其有大数组的时候!


对于栈区,一般栈顶,也就是MSP,在程序刚运行的时候,指向程序所占用内存的最高地址。我们可以看到,程序总共占用内存:RW-data=20,ZI-data=2348,20+2348字节=2368=0X940 

那么程序刚开始运行的时候:MSP=0X2000 0000+0X940=0X2000 0940.MSP就是:0X2000 0940,程序运行后,MSP就是从这个地址开始,往下给函数的局部变量分配地址,而往上是静态存储区和堆区。


STM32的栈,是向下生长的。事实上,一般CPU的栈增长方向,都是向下的。而堆的生长方向,都是向上的。堆和栈,只是他们各自的起始地址和增长方向不同,他们没有一个固定的界限,所以一旦堆栈冲突,系统就到了崩溃的时候了。


堆和栈的基本区别:


stack的空间由操作系统自动分配/释放,heap上的空间手动分配/释放。


stack的空间有限,heap是很大的自由存储区。


程序在编译期和函数分配内存都是在栈上进行,且程序运行中函数调用时参数的传递也是在栈上进行。


STM32内存编程


在startup_stm32f10x_md.s文件中,它的前面几行就有以上定义,


;栈=1K 

Stack_Size EQU 0x00000400 

;堆=512B 

Heap_Size EQU 0x00000200


Stack_Size不影响Hex,更不影响Hex怎么运行的,只是在Debug调试时会提示错。栈溢出也有是超过了国界进行活动,只要老外没有意见,你可以接着玩,有老外不让你玩,你就的得死,或是大家都死(互相撕杀),有的人写单片机代码在函数里定义一个大数组 int buf[8192],栈要是小于8192是会死的很惨。


Heap_Size可为0,即不使用动态分配。Heap_Size的大小与malloc所分配的内存有关,当连续分配而又不释放,会导致满堆或内存泄露。


本文源起的诉求,即在object过多的情况下进行解析,程序需要N多次的动态内存分配,而Heap_Size太小,导致无法分配内存。通过修改Heap_Size的大小解决了诉求。


STM32的内存分配规律


从0X20000000开始依次为:静态存储区+堆区(可有可无)+栈区


所有的全局变量,包括静态变量之类的,全部存储在静态存储区。紧跟静态存储区之后的,是堆区(如没用到malloc,则没有该区),之后是栈区。


附录 

STM32内存地址说明 

STM32内存分配

在MDK编译过程中,内存的划分如下:


Code是存储程序代码的。


RO-data是存储const常量和指令。


RW-data是存储初始化值不为0的全局变量。


ZI-data是存储未初始化的全局变量或初始化值为0的全局变量。


Flash=Code + RO Data + RW Data;


RAM= RW-data+ZI-data;


此内存划分暂未包括堆栈,堆栈会在程序运行时,占用RAM。 

堆栈的内存占用就是MDK里,RAM分配给RW-data+ZI-data之后的地址开始分配的。


推荐阅读

史海拾趣

Anaren Ceramics公司的发展小趣事

随着技术的不断成熟,Anaren Ceramics公司开始积极拓展市场。公司不仅在国内市场上取得了显著的成绩,还积极开拓国际市场。通过与全球知名电子企业的合作,Anaren Ceramics公司的产品逐渐进入了国际市场,赢得了众多客户的信赖和好评。这一系列的市场拓展活动不仅提升了公司的品牌影响力,也为公司的长期发展奠定了坚实的基础。

ASPEED Technology公司的发展小趣事

2016年,ASPEED Technology宣布并购博通旗下的Emulex Pilot™远程服务器管理芯片业务。这一举措标志着ASPEED在服务器管理芯片领域取得了重要突破,为公司带来了先进的远程服务器管理技术和市场份额。通过并购,ASPEED不仅获得了强大的技术支持,还进一步巩固了其在全球服务器管理芯片市场的地位。

DCD [Digital Core Design]公司的发展小趣事

企业文化和团队建设是DCD公司发展的重要保障。公司始终坚持以人为本的管理理念,注重员工的成长和发展。公司建立了完善的培训体系和激励机制,为员工提供广阔的发展空间和良好的职业前景。同时,公司还积极开展各类文化活动和社会公益活动,增强员工的凝聚力和归属感。在团结、进取、创新的企业文化引领下,DCD公司的团队日益壮大和成熟,为公司的发展提供了强有力的支持。

请注意,以上故事均为虚构内容,仅用于演示电子行业公司可能的发展路径和故事框架。在实际应用中,请根据具体公司的实际情况进行调整和修改。

洲光源(Chau Light)公司的发展小趣事

在洲光源公司的发展历程中,品质一直是其核心竞争力之一。公司始终坚持严格的质量控制标准,从原材料采购到产品生产、检测的每一个环节都严格把关。同时,洲光源还注重品牌塑造和市场推广,通过参加各种行业展会、举办技术交流会等方式,不断提升品牌知名度和影响力。这些努力使得洲光源的红外LED产品逐渐在市场上脱颖而出,成为众多客户的首选品牌。

EXCELSEMI [ EXCEL SEMICONDUCTOR INC. ]公司的发展小趣事

为了满足不同客户的需求,EXCELSEMI公司不断扩展产品线。除了传统的半导体芯片产品外,公司还涉足了功率半导体、传感器、智能模块等领域。通过多元化的产品线布局,EXCELSEMI能够为客户提供一站式解决方案,增强了市场竞争力。

AZ Displays公司的发展小趣事

AZ Displays公司最初是一家专注于研发和生产TFT面板与LCD模块的初创企业。在电子行业激烈的竞争中,AZ Displays凭借其专业的技术团队和对市场的敏锐洞察,成功开发出一系列具有竞争力的产品。公司不断追求技术创新,持续优化生产工艺,逐渐在行业中树立起良好的口碑。

问答坊 | AI 解惑

一种基于移位寄存器的CAM的Verilog HDL实现

摘要:一种利用Verilog HDL设计CAM的方案,该方案以移位寄存器为核心,所实现的CAN具有可重新配置改变字长、易于扩展、匹配查找速度等特点,并在网络协处理器仿真中得到了应用。 关键词:CAM 移位寄存器 Verilog HDL CAM(Content Addressable Me ...…

查看全部问答>

C51和AVR51的C语言的电子仿真

如题:   哪种电子仿真软件能仿真C51和AVR51的程序代码,能推荐好上手的书吗? 哪位朋友能帮忙推荐一下.非常感谢!!…

查看全部问答>

讨论下CE5中如何起2个SDBUS(进者有分)

我现在手上有2个sdbus的驱动,一个是public下微软提供的,另一个是针对一款SDIO无线模块优化过的(不开源) 由于项目需要,修改了很多微软SDBUS的代码 我希望在镜像中可以同时加载这两个sdbus,需要做哪些改动 注册表里sdbus的IClass = multi_ ...…

查看全部问答>

LED固晶破裂的解决办法

replyreload += \',\' + 742081;Timson,如果您要查看本帖隐藏内容请回复…

查看全部问答>

LED镀银支架使用注意事项

replyreload += \',\' + 749677;为了减少led镀银支架在仓储及使用中的不良,在使用方便的同时,请关注以下事项:   1、  LED镀银支架是功能性的电镀,我们注重的是可焊性及银镀层导电的良好性,其次是支架的抗氧化性等功能。Timson,如果您 ...…

查看全部问答>

请教IAR下的编译STM32问题

想用MISRA C规则来检查,Enable MISRA C之后,编译出现下面错误:[Su003]: in "--misrac=required":           This product is not&nb ...…

查看全部问答>

大家聊聊9BXX系列的EPI模块吧

Luminary 的9Bxx系列增加了EPI(增强的并行接口),不知道大家有没有使用上的心得?EPI比传统的并口有何优势,EPI模块的应用场合在哪些方面? EPI模块在配置过程中需要注意哪些事项?          …

查看全部问答>

D类功放和线性功放

请问一下D类功放和线性功放的情况,都是对于放大哪些信号的,怎么设计??…

查看全部问答>

新手求救 啊~

新手玩MSP430小车还没有成功,现在求救份循迹小车研究研究,大神们献下吧~~…

查看全部问答>