历史上的今天
返回首页

历史上的今天

今天是:2025年02月26日(星期三)

正在发生

2020年02月26日 | stm32的堆和栈

2020-02-26 来源:eefocus

关于堆和栈已经是程序员的一个月经话题,大部分有是基于os层来聊的。


那么,在赤裸裸的单片机下的堆和栈是什么样的分布呢?以下是网摘:


刚接手STM32时,你只编写一个


int main()


{


while(1);


}


BUILD://Program Size: Code=340 RO-data=252 RW-data=0 ZI-data=1632


编译后,就会发现这么个程序已用了1600多的RAM,要是在51单片机上,会心疼死了,这1600多的RAM跑哪儿去了,


分析map,你会发现是堆和栈占用的,在startup_stm32f10x_md.s文件中,它的前面几行就有以上定义,


这下该明白了吧。


Stack_Size EQU 0x00000400


Heap_Size EQU 0x00000200


以下引用网上资料 理解堆和栈的区别


(1)栈区(stack):由编译器自动分配和释放,存放函数的参数值、局部变量的值等,其操作方式类似


于数据结构中的栈。


(2)堆区(heap):一般由程序员分配和释放,若程序员不释放,程序结束时可能由操作系统回收。分配


方式类似于数据结构中的链表。


(3)全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态


变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系


统自动释放。


(4)文字常量区:常量字符串就是存放在这里的。


(5)程序代码区:存放函数体的二进制代码。


例如:


int a=0; //全局初始化区


char *p1; //全局未初始化区


main()


{


int b; //栈


char s[]=”abc”; //栈


char *p3= “1234567”; //在文字常量区Flash


static int c =0 ; //静态初始化区


p1= (char *)malloc(10); //堆区


strcpy(p1,”123456”); //”123456”放在常量区


}


所以堆和栈的区别:


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


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


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


1.堆和栈大小


定义大小在startup_stm32f2xx.s


Stack_Size EQU 0x00000400


AREA STACK, NOINIT, READWRITE, ALIGN=3 

Stack_Mem SPACE Stack_Size 

__initial_sp


; Heap Configuration 

; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> 

;


Heap_Size EQU 0x00000200


AREA HEAP, NOINIT, READWRITE, ALIGN=3 

__heap_base


2.堆和栈位置


通过MAP文件可知


HEAP 0x200106f8 Section 512 startup_stm32f2xx.o(HEAP) 

STACK 0x200108f8 Section 1024 startup_stm32f2xx.o(STACK)


__heap_base 0x200106f8 Data 0 startup_stm32f2xx.o(HEAP) 

__heap_limit 0x200108f8 Data 0 startup_stm32f2xx.o(HEAP) 

__initial_sp 0x20010cf8 Data 0 startup_stm32f2xx.o(STACK)


显然 Cortex-m3资料可知:__initial_sp是堆栈指针,它就是FLASH的0x8000000地址前面4个字节(它根据堆栈大小,由编译器自动生成)


显然堆和栈是相邻的。 

这里写图片描述


3.堆和栈空间分配


栈:向低地址扩展


堆:向高地址扩展


显然如果依次定义变量


先定义的栈变量的内存地址比后定义的栈变量的内存地址要大


先定义的堆变量的内存地址比后定义的堆变量的内存地址要小


4.堆和栈变量


栈:临时变量,退出该作用域就会自动释放


堆:malloc变量,通过free函数释放


另外:堆栈溢出,编译不会提示,需要注意


如果使用了HEAP,则必须设置HEAP大小。 

如果是STACK,可以设置为0,不影响程序运行。 

IAR STM8定义STACK,是预先在RAM尾端分配一个字节的区域作为堆栈预留区域。 

当程序静态变量,全局变量,或者堆与预留堆栈区域有冲突,编译器连接的时候就会报错。 

你可以吧STACK设置为0,并不影响运行。(会影响调试,调试会报堆栈溢出警告)。 

其实没必要这么做。 

一般程序,(在允许范围内)设置多少STACK,并不影响程序真实使用的RAM大小, 

(可以试验,把STACK设置多少,编译出来的HEX文件都是一样), 

程序还是按照它原本的状态使用RAM,把STACK设置为0,并不是真实地减少RAM使用。 

仅仅是欺骗一下编译器,让程序表面上看起来少用了RAM。 

而设置一定size的STACK,也并不是真的就多使用了RAM,只是让编译器帮你 

检查一下,是否能够保证有size大小的RAM没有被占用,可以用来作为堆栈。 

以上仅针对IAR STM8.


从以上网摘来看单片机的堆和栈是分配在RAM里的,有可能是内部也有可能是外部,可以读写;


栈:存函数的临时变量,即局部变量,函数返回时随时有可能被其他函数栈用。所以栈是一种分时轮流使用的存储区,


  编译器里定义的Stack_Size,是为了限定函数的局部数据活动的范围,操过这么范围有可以跑飞,也就是栈溢出;


 Stack_Size不影响Hex,更不影响Hex怎么运行的,只是在Debug调试时会提示错。栈溢出也有是超过了国界进行


 活动,只要老外没有意见,你可以接着玩,有老外不让你玩,你就的得死,或是大家都死(互相撕杀),有的人写


单片机代码在函数里定义一个大数组 int buf[8192],栈要是小于8192是会死的很惨。


堆:存的是全局变量,这变量理论上是所有函数都可以访问的,全局变量有的有初始值,但这个值不是存在RAM里的,是


 存在Hex里,下载到Flash里,上电由代码(编译器生成的汇编代码)搬过去的。有的人很“霸道”,上电就霸占已一块很


大的RAM(Heap_Size),作为己有(malloc_init),别人用只能通过他们管家借(malloc),用完还得换(free)。所以  


一旦有“霸道”的人出现是编译器里必须定义Heap_Size,否则和他管家借也没有用。


总之:堆和栈有存在RAM里,他两各分多少看函数需求,但是他两的总值不能超过单片机硬件的实际RAM尺寸,否则只能


到海里玩(淹死了)或是自己打造船接着玩(外扩RAM)。

推荐阅读

史海拾趣

EICHHOFF公司的发展小趣事

EICHHOFF公司成立于XX世纪XX年代,当时由创始人XXX在德国的一个小镇上开设了一个小型的电子元件加工厂。由于XXX对电子技术的热爱和对市场需求的敏锐洞察,他专注于生产高质量的连接器和其他电子组件。在初创阶段,EICHHOFF的产品主要供应给当地的电子制造商和维修店。随着口碑的逐渐传播和产品质量的不断提升,公司开始接到来自更广泛地区的订单。

为了应对不断增长的市场需求,EICHHOFF公司逐步扩大了生产规模,并引入了先进的生产设备和技术。同时,公司也注重人才培养和团队建设,吸引了一批有才华的工程师和技术人员加入。这些努力使得EICHHOFF在电子行业中逐渐崭露头角。

圣邦微电子(Fangtek)公司的发展小趣事

EICHHOFF公司成立于XX世纪XX年代,当时由创始人XXX在德国的一个小镇上开设了一个小型的电子元件加工厂。由于XXX对电子技术的热爱和对市场需求的敏锐洞察,他专注于生产高质量的连接器和其他电子组件。在初创阶段,EICHHOFF的产品主要供应给当地的电子制造商和维修店。随着口碑的逐渐传播和产品质量的不断提升,公司开始接到来自更广泛地区的订单。

为了应对不断增长的市场需求,EICHHOFF公司逐步扩大了生产规模,并引入了先进的生产设备和技术。同时,公司也注重人才培养和团队建设,吸引了一批有才华的工程师和技术人员加入。这些努力使得EICHHOFF在电子行业中逐渐崭露头角。

Dialog Semiconductor(戴乐格半导体)公司的发展小趣事

Dialog Semiconductor在电源转换技术方面取得了重要突破。公司成功将氮化镓(GaN)技术应用于电源转换器中,推出了基于氮化镓技术的电源转换产品。氮化镓技术以其高速和低功耗的特点,为电源转换器带来了更高的效率和更小的尺寸。这一技术突破不仅推动了Dialog Semiconductor自身的发展,也为整个电子行业带来了重要的影响。

HANBIT Electronics公司的发展小趣事

Dialog Semiconductor一直专注于能源管理领域,致力于提供高效的电源管理解决方案。公司推出了多种高效的电源管理芯片,这些芯片能够显著延长电池寿命并提高设备效率。特别是在移动设备领域,Dialog Semiconductor的电源管理芯片被广泛应用于智能手机、平板电脑等设备中,为用户提供了更长的使用时间和更好的使用体验。

DDP Engineered LED Solutions公司的发展小趣事

DDP Engineered LED Solutions公司自创立之初,便以技术创新作为公司发展的核心动力。在公司成立的早期,研发团队深入LED照明领域,通过不断实验和改进,成功开发出了一系列高效、稳定的LED照明产品。这些产品不仅具有出色的照明效果,而且具有较长的使用寿命和较低的能耗,迅速在市场上获得了认可。随着技术的不断迭代,DDP不断推出符合市场需求的创新产品,逐渐在电子行业LED照明领域崭露头角。

Ford Aerospace & Communications Corp公司的发展小趣事

进入21世纪,随着物联网和人工智能技术的快速发展,福特汽车公司再次站在了行业的前沿。它致力于研发智能互联汽车技术,通过车载设备与互联网的深度融合,实现车辆与车辆、车辆与基础设施之间的实时通信和协同工作。这一举措不仅提升了驾驶的安全性和效率,也为未来的自动驾驶技术奠定了基础。虽然这些技术更多地关注于汽车本身,但它们也体现了福特在电子通信和智能技术方面的持续探索和创新能力。

请注意,以上故事均为虚构,旨在根据福特汽车公司的历史和技术背景构建可能的发展路径。实际上,福特汽车公司并未直接成立名为“Ford Aerospace & Communications Corp”的子公司。

问答坊 | AI 解惑

优秀论文

本帖最后由 paulhyde 于 2014-9-15 09:41 编辑 很不错的材料 , 不是原创 仅供分享  …

查看全部问答>

关于百万高清数字摄像机的问与答

1.  什么是数字摄像机? 答:数字摄像机也被称为百万高清IP摄像机,与模拟摄像机相比,它前端所采用的百万像素感光器将光信号转换并输出数字视频信号,然后由DSP处理器将数字视频压缩后通过网络输出。而模拟摄像机前端采用隔行扫描CMOS/ ...…

查看全部问答>

职场感悟20条

1.闲谈莫论人非,不要觉得这样可以排解你心中的郁闷,错!总有一天这个人会知道你说的这些话。他永远都不会原谅你的!更何况你的那个听众又会怎么想呢? 2.不要张扬别人的短处,平时也不要炫耀自己的长处,韬光养晦,涵养自己的德行。厚积薄发, ...…

查看全部问答>

[请教]和某位哥们一样,请教在C8051F上存储消息

应用情况是这样: 1. 每一个数据大概100Byte 需要在T秒(固定值)存储大概500条数据,只需要一次即可 2. 数据之间有一定的规律,但是大部分数据内部是不同的 我对C8051F单片机的理解: 1. 外扩内存是可以的,C8051F均有复用和非复用的EMIF接口, ...…

查看全部问答>

问个问题 银行叫号机的控制核心是什么?

请问,银行叫号机的控制核心是什么? 操作系统是什么? 借地方求教一下…

查看全部问答>

使用PB创建ATM平台

要使用PB创建ATM平台,我自己是刚接触PB,不知道该添加哪些组件; 哪位大虾指点一下哈? 谢谢!!!…

查看全部问答>

vxworks下怎么开发ISP1760(作为USB主机端控制器)的USB驱动程序

    isp1760通过io与CPU连接,vxworks下的USB host驱动是针对PCI设备的,请问怎么修改vxworks的USB host驱动,使其能使用ISP1760     谢谢!!…

查看全部问答>

谁装了ce6.0 r3,麻烦传个文件给我。。。

WINCE600\\PUBLIC\\IE\\OAK\\IESAMPLE_EXR\\UI\\iesample_exr.rc 这个文件被我误改了导致现在编译ie_exr过不去了,谁传给我,谢谢…

查看全部问答>

请教等效阻抗

在网上下载的电路相关学习资料,学习到电路短路判断这一块时。遇到等效阻抗这一概念。根据学习资料上给出的电阻值,其等效阻抗=并联电路的电阻值。但是我看电路图上给出的量电阻的位置处于一条直线上,很矛盾。所以发帖请教各位老师。希望能得到等 ...…

查看全部问答>