STM32的Code/RO/RW/ZI区、Flash/Ram的占用情况、堆栈大小的设置

发布者:SereneJourney最新更新时间:2020-01-12 来源: eefocus关键字:STM32  Flash  Ram  堆栈大小 手机看文章 扫描二维码
随时随地手机看文章

以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种以上的内存管理程序供我们选用。

关键字:STM32  Flash  Ram  堆栈大小 引用地址:STM32的Code/RO/RW/ZI区、Flash/Ram的占用情况、堆栈大小的设置

上一篇:关于stm32的堆、栈、内存管理以及外扩ram的使用总结
下一篇:STM32堆和栈(Heap & Stack)及SRAM存储使用

推荐阅读最新更新时间:2024-11-17 04:40

基于STM32利用按键点亮LED灯
基于STM32利用按键点亮LED灯的基本步骤: (1)打开stm32CubeMX,创建新工程文件 (2)选择需要的芯片,本次实验采用的是STM32F411RETx (3)黄色代表可被使用的引脚,绿色代表已被确定功能的引脚。左侧设置栏中的红色部分表示:IO口复用造成的重叠,以至不能继续使用。 (4)选好芯片,设置好相关系数参量后,选择与keil5相对应的MDK—ARM V5。 源程序: 1.按键按下LED灯点亮 int main { if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13) == 0){ HAL_Delay(10); //延时去抖
[单片机]
stm32控制舵机DS3115转动
一、舵机DS3115 一般来讲,舵机主要由以下几个部分组成, 舵盘、减速齿轮组、位置反馈电位计5k、直流电机、控制电路板等。 工作原理:控制电路板接受来自信号线的控制信号(具体信号待会再讲),控制电机转动,电机带动一系列齿轮组,减速后传动至输出舵盘。舵机的输出轴和位置反馈电位计是相连的,舵盘转动的同时,带动位置反馈电位计,电位计将输出一个电压信号到控制电路板,进行反馈,然后控制电路板根据所在位置决定电机的转动方向和速度,从而达到目标停止。 舵机的基本结构是这样,但实现起来有很多种。例如电机就有有刷和无刷之分,齿轮有塑料和金属之分,输出轴有滑动和滚动之分,壳体有塑料和铝合金之分,速度有快速和慢速之分,体积有大中小三种之分等等,组合不
[单片机]
<font color='red'>stm32</font>控制舵机DS3115转动
STM32的PWM输入模式设置并用DMA接收数据
环境: 主机:WIN7 开发环境:MDK4.72 MCU:STM32F103 说明: 项目中需要进行红外学习,如果采用输入捕获的方式,因为定时器只能捕获上升沿或者下降沿,所以只能获得周期,而不能得到具体的红外波的高低电平的时间.所以采用PWM输入的方式进行捕获. 采用的是PA8脚,对应TIM1的通道1. 源代码: /********************************************************************* * 函数 ***********************************************************
[单片机]
STM32之TFT触摸屏(ILI9320):通过LCD_ShowChar显示
使用TFT触摸屏时,想要对字符串,图形或者数字进行显示时,发现他们的库函数中都有一个最重要的函数LCD_ShowChar,貌似目前很少有人分析这个函数,虽然简单但是还是有点绕的。 先贴一下这个函数的代码,由于函数显示分为叠加显示和非叠加显示,原理类似,所以只分析非叠加方式的部分应该就都懂了。 void LCD_ShowChar(u16 x,u16 y,u8 num,u8 size,u8 mode) { u8 temp,t1,t; u16 y0=y; u16 colortemp=POINT_COLOR; num=num-' ';//得到偏移后的值 if(!mode) //非叠加方式
[单片机]
<font color='red'>STM32</font>之TFT触摸屏(ILI9320):通过LCD_ShowChar显示
关于STM32的USART_GetFlagStatus和USART_GetITStatus解析(异步通信)
前言 STM32固件库中提供了串口收发的标志位函数,包括USART_GetFlagStatus(…,…);和USART_GetITStatus(…,…);,两者容易混淆,重点区别就在于:前者返回值是中断标志位状态(读SR寄存器),后者返回值是中断发生与否的判断(读CR寄存器),以下主要对这两个函数进行分析。 一、USART_GETFlagStatus(…,…) /** * @brief Checks whether the specified USART flag is set or not. * @param USARTx: Select the USART or the UART peripheral. *
[单片机]
关于<font color='red'>STM32</font>的USART_GetFlagStatus和USART_GetITStatus解析(异步通信)
STM32驱动FLASH(W25Q128)
1、W25Q128 是华邦公司推出的一款 SPI 接口的 NOR Flash 芯片,其存储空间为 128Mbit,相当于 16M 字节。 W25Q128 可以支持 SPI 的模式 0 和模式 3,也就是 CPOL=0/CPHA=0 和CPOL=1/CPHA=1 这两种模式。 2、写入数据时,需要注意以下两个重要问题: ①、Flash 写入数据时和 EEPROM 类似,不能跨页写入,一次最多写入一页,W25Q128的一页是 256 字节。 写入数据一旦跨页,必须在写满上一页的时候,等待 Flash 将数据从缓存搬移到非易失区,重新再次往里写。 ②、Flash 有一个特点,就是可以将 1 写成 0,但是不能将 0 写成 1,要想将 0
[单片机]
<font color='red'>STM32</font>驱动<font color='red'>FLASH</font>(W25Q128)
stm32 串口通信数据乱码
最近在写stm32的标准库的串口通讯程序,本来很简单的串口通讯,却硬生生被上位机接收到乱码的问题折磨了好久,反复百度了好几次,始终没搜到正确解决方法,不过最后终于在https://www.eeworld.com.cn/mcu/2018/ic-news081240692.html这篇帖子上找到了答案。虽然最后问题和这位大佬不太一样,但是我也是它列出的几个情况之一——外部时钟问题。正如这位大佬所说,串口通信用的是外部时钟,而在stm32f10x.h/stm32f4xx.h中的HSE的设置值HSE_VALUE默认是25MHz。因为官方的开发板是用的25MHz,但是有些开发板用的是8MHz,所以这个地方没改的话就可能出现乱码。我把这里一改,
[单片机]
<font color='red'>stm32</font> 串口通信数据乱码
ST 最新STM32 Primer开发工具可玩Maze和Breakout
完整、独立、预编程的评估工具套件,既有充满趣味性的功能介绍,又有严肃的开发工具,可以链接到在线开发社区 中国,2007年10月15日 — 意法半导体(纽约证券交易所代码:STM)今天推出了一套价格低廉的开发工具,这款代号为STM32 Primer开发工具是一套完整的学习与娱乐相结合的趣味性应用开发工具,用于ST的STM32系列基于具有突破性的ARM Cortex-M3内核的闪存微控制器。这套工具包含一个创新的用户界面、多个游戏和向新用户介绍该系列产品的产品入门功能,以及用于高级开发和编程的Raisonance软件工具。 STM32 Primer是一个手持评估开发工具,力图通过简单和有趣的介绍,让用户了解STM32的强大功能。紧
[新品]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved