历史上的今天
返回首页

历史上的今天

今天是:2025年01月12日(星期日)

2020年01月12日 | STM32的Code/RO/RW/ZI区、Flash/Ram的占用情况、堆栈大小的设置

2020-01-12 来源:eefocus

以cortex-M3为例,例如STM32F103


这篇文章要讲2个问题:


1、编译出的程序(指令)、变量的存放位置、大小?

2、在代码和keil中,“堆、栈”两者的大小如何设置?


keil编译完成后,会有提示,形如:


Program Size: Code=1148 RO-data=424 RW-data=20 ZI-data=1636  


其中:

① Code为代码,本质上就是一大堆ARM指令;

② RO为只读的数据,例如,char *name = "TOM";//TOM三个字符就存放在ROM中作为RO-DATA;又如,为了减小sin的计算量,把sin的各个值直接制作成表,const float sinVal[]= {.....};

③ RW为非初始化的全局和静态变量占用的RAM大小,同时还要占用等量的ROM大小用于存放这些非0变量的初值;

④ ZI为0初始化的内存区的大小(该区域3个用途:0初始化的全局和静态变量+堆区+栈区)。


下面是keil自动生成的.map文件中的信息:

Flash的占用量就是上图中ROM Size的大小,它包含了①+②+③的大小【ARM指令代码+只读数据+非0初始化变量的初值】

RAM的占用量包含上述③+④的大小,也即【非0初始化变量、0初始化RAM(又分为0初始化静态变量区+堆区+栈区)】


我们用jflash或者其他软件打开hex文件,看一下前四个字节:

0x2000678-0x2000000=0x678=1656,而观察一下前文编译出的信息,正好1656 = RW-data(1636) +  ZI-data(20)的大小,这就证明了RAM的大小确实=RW+ZI的大小。


注:hex文件的前4个字节为主堆栈指针MSP的初值。


在STM32的启动文件(.s汇编文件)中,一开始我们会看到 Stack_Size、Heap_Size 这两个汇编宏定义:

Stack指的是栈,栈是由堆栈指针MSP/PSP自动管理的,理论上初始化时给堆栈指针赋值为RAM的最高地址即可,但是用keil编译时,keil并不是按RAM的最高地址生成的HEX前4字节(也即MSP的初值),而是按照:全局和静态变量的容量+Heap_Size+Stack_Size三者之和,作为HEX文件的前4字节。


设置某块芯片的RAM的总大小,是在keil的这个地方设的:

其实讲道理,我觉得keil还是把这个值+RAM起始地址(0x2000000)作为MSP的初值更好,只不过keil不是这么做的,keil仅仅是把这个值用作编译检测:检查全局和局部静态变量(含0初始化和非0初始化两部分)所占的空间+堆区+栈区,它们所占空间之和是否超过了上图红框里的这个值,如果超了就编译报错。这就是上面红框里的值唯一的作用。


根据这段理论,我们也就知道了启动文件中Stack_Size该设为多少了,只要【全局变量+局部静态变量+Heap_Size+Stack_Size】的大小不超过芯片的RAM容量即可。


keil编译时,会把C库函数支持的malloc、free所需的内存指向heap内存区,并且当我们不断的malloc吃内存堆时,malloc函数会检测程序已吃掉的内存堆是否超过了Heap_Size,超了的话就会返回NULL。


keil是这样为【全局变量 + 局部静态变量 + Heap_Size + Stack_Size】分配内存的:

上面论述的是,使用C库函数提供的mallloc时,内存堆heap的使用情形,如果我们不打算使用C库提供的动态内存分配,而打算使用自己写的内存堆管理程序,甚至干脆不打算使用动态内配功能,这些情况下,请直接把Heap_Size设为0。


 


最后总结一下Stack_Size的设置方法:①在keil中正确设置芯片的RAM大小, ②确定堆区Heap_Size的大小,这个值可以通过调试自己估计出来,如果不使用C库的malloc的话,直接设为0,③把Stack_Size设的越大越好,只要编译不报错,就把Stack_Size往尽可能大了配。over


 


PS:自己写的动态内存管理程序,本质上就是申请一个大数组,自己管理这个数组而已,相当于自己写一套malloc/free函数,很多操作系统中有这样的例子,比如freeRtos、ucos等,这些操作系统都提供了好多种动态内存管理方法,最简单的一种,跟切火腿似的,malloc出来之后就释放不掉了,直到把这个大数组切完拉倒,看似很low的内存管理方法,实际上在很多小型项目上却用起来很方便。更好的内存管理程序,那自然是支持动态切,还要支持把动态释放的空间合并起来,以便把刚才合并起来的空间再次malloc,这些更好的内存管理程序,用起来更方便,但是同时,这种功能强大的内存管理程序自身也会占掉很多RAM / ROM / CPU资源,矛盾利弊共存。到底要使用简单的内存管理还是高级的内存管理,要看项目需求,一般嵌入式操作系统会提供4种以上的内存管理程序供我们选用。

推荐阅读

史海拾趣

Curtis Industries公司的发展小趣事

Curtis Industries公司成立于20世纪初期,当时电子行业正处于起步阶段。创始人凭借对技术的热爱和对市场的敏锐洞察力,决定投身于电子行业。在初创阶段,公司面临了诸多困难,如资金紧张、技术难题等。然而,创始人始终坚信自己的理念,带领团队日夜兼程地研发新产品,不断寻求突破。正是这份坚定与坚持,为公司的发展奠定了坚实的基础。

BH Electronics公司的发展小趣事

随着国内市场的饱和,BH Electronics开始寻求国际化发展的道路。公司高层经过深入调研和分析,决定进军欧洲市场。为了适应当地市场的需求和文化习惯,BH Electronics在欧洲设立了研发中心和营销团队,积极推广公司的产品和服务。通过不懈的努力,BH Electronics成功在欧洲市场打开了局面,实现了国际化发展的战略目标。

中科银河芯(GXCAS)公司的发展小趣事
输入信号的电压范围决定了三极管何时截止、何时饱和导通。
FARNELL公司的发展小趣事

为了保持在电子行业中的领先地位,FARNELL公司积极寻求创新与合作。公司与多家知名电子元器件制造商建立了长期合作关系,共同研发新产品、新技术。同时,FARNELL公司还致力于为客户提供定制化的解决方案,满足不同客户的需求。这种创新与合作的精神使FARNELL公司在电子行业中保持了持续的发展动力。

Aristo-Craft/ L M P Inc公司的发展小趣事

品质是公司的生命线。Aristo-Craft/L M P Inc一直注重品质管理,从原材料采购到生产过程的每一个环节都进行严格把控。公司建立了完善的质量管理体系,并通过了多项国际质量认证。同时,公司还注重品牌建设,通过广告宣传、参加行业活动等方式提高品牌知名度和美誉度。

Hisetec Electronic Co Ltd公司的发展小趣事

背景:人才是企业发展的第一资源。Hisetec Electronic Co Ltd公司始终将人才战略作为企业发展的核心战略之一。

发展:公司建立了完善的人才培养、引进和激励机制,积极吸引国内外优秀人才加盟。同时,公司还加强与高校和科研机构的合作,共同培养高素质的电子专业人才。此外,公司还注重员工的职业发展和企业文化建设,营造了良好的工作环境和氛围。这些举措为Hisetec公司的可持续发展提供了有力的人才保障。

请注意,以上故事均为虚构,旨在展示电子行业企业可能的发展路径和策略。实际上,Hisetec Electronic Co Ltd公司的具体发展历程和故事可能有所不同。

问答坊 | AI 解惑

LED灯寿命与驱动电源关系

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

查看全部问答>

Intel82551网卡大包(65535 bytes)不通问题

小弟正在做MPC8377的板子,板载一片Intel82551 PCI网卡,还有Intel82574 pci-e网卡,vxworks的版本是6.6,之前我是使用命令行编译的,这两个网卡的大包(65535字节)都不通.后来,使用workbench编译,通过比较prjParams.h文件,添加了大包的相关组件后, 82574 ...…

查看全部问答>

wince 4.2 ie升级问题

在wince 4.2 的引用过程中碰到如下几个问题,由于版本过老,很难找到资料,望高手指点 1.原IE是4.0,需要升级到6.0,网上很难找到IE升级包,有没有什么方法可以解决呢?主要是用在远程监控的IE访问,要安装插件(诚风的远程监控 硬盘录像机),有 ...…

查看全部问答>

请大家帮帮忙,怎么才能在PB5.0与开发板之间建立内核调试关系。急!!!

请大家帮帮忙,怎么才能在PB5.0与开发板之间建立内核调试关系。 我希望能够在开发板启动的时候,PB5.0能够对WinCE5.0镜像进行单步调试,断点调试。 很急呀!!!…

查看全部问答>

求教wince6 R3环境silverlight开发

目前在wince6 R3环境下开发Silverlight程序,计划采用DirectDraw作为2D加速方式。处理器为pxa310,是支持DirectDraw的2D硬件加速的。 按照msdn上的介绍配置好环境变量,SYSGEN_XAML_RUNTIME,BSP_XRPLUGIN_DDRAW and BSP_XRPLUGIN_OPENGL。在系统b ...…

查看全部问答>

WincE组件问题

各位大虾:     问:WinCE中是否含有如下组件:     类似于WinXP 中的设备管理器,我可以查看系统拥有哪些设备?是否启用等。     等..........     谢.............…

查看全部问答>

请问制作交叉编译环境需要的linux-2.6.x去哪里找?

我下了个uclinux-dist-200608...tar.gz,里面的linux-2.6.x不好用,编译gcc的时候会找不到头文件,我看了下arm-elf声称的头文件中小而且东西齐全,我该怎样去制作这个头文件,对了我的板子lpc22xx,有什么下补丁的地方吗?…

查看全部问答>

在XILINX中,如何防止寄存器被优化?

我在XST综合时,未接输出端口的寄存器被优化掉了,但我需要保留这些寄存器以获得一些功耗方面的信息。    请问如果约束优化,使这些寄存器得以保存下来呢??   等待高手解答!!!!!!!!!!!!!!!!…

查看全部问答>

lm3s811 uart

uart1 需要自己搭外设。 看着datasheet配置完uart1 还是不行。到后来才发现 板子上的uart0 “对应”PC机上的虚拟串口在这里写下来,让有出现同样情况的朋友们明白下·~共同学习~~…

查看全部问答>

msp430使用心得

真正使用430是这次换工作以后,新项目是用430单片机来实现的,主要是430的微功耗功能,确实让我感受到这款单片机的强大。以前做项目采用c8051单片机,功能在10mA左右,认为这种功耗已经很小了,接触430后才感觉到TI对MCU的设计的水平,能够很好的把 ...…

查看全部问答>