STM32 堆栈知识

发布者:mu22最新更新时间:2017-09-19 来源: eefocus关键字:STM32  堆栈知识 手机看文章 扫描二维码
随时随地手机看文章

在STM32平台上编写如下代码:

int main()

{

while(1);

}

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

编译后,就会发现这么个程序已用了1600多的RAM,这1600多的RAM跑哪儿去了,分析map,你会发现是堆和栈占用的,在startup_stm32f10x_md.s文件中,它的前面几行就有以上定义。

Stack_Size   EQU   0x00000400

Heap_Size   EQU   0x00000200

 PS:

在Keil中编译工程成功后,在下面的Bulid Ouput窗口中会输出下面这样一段信息:
Program Size: Code=340 RO-data=252 RW-data=0 ZI-data=1632 

其代表的意思如下:
Code :是程序中代码所占字节大小
RO-data :程序中所定义的指令和常量大小 (个人理解 :Read Only)
RW-data :程序中已初始化的变量大小 (个人理解”:Read/Write)
ZI-Data :程序中未初始化的变量大小 (个人理解 :Zero Initialize)


ROM(Flash) size = Code+RO-data+RW-data;

RAM size = RW-data+ZI-data

可以通过.map查看占用的flash和ram大小


堆和栈的区别:

(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个字节(它根据堆栈大小,由编译器自动生成)

显然堆和栈是相邻的。

image

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)。


关键字:STM32  堆栈知识 引用地址:STM32 堆栈知识

上一篇:STM32F10x 启动代码分析
下一篇:STM32 大小端序 与 堆栈及其增长方向分析

推荐阅读最新更新时间:2024-03-16 15:37

STM32为什么要有SysTick
STM32为什么要有SysTick?STM32里面有很多tim定时器,为什么还要有SysTick呢? 系统时基定时器 这个定时器是专用于实时操作系统,也可当成一个标准的递减计数器。它具有下述特性: ● 24位的递减计数器 ● 自动重加载功能 ● 当计数器为0时能产生一个可屏蔽系统中断 ● 可编程时钟源 这个里面的定时器是24位的,普廷的TIM定时器最多也就是16位的,如果想做长时间的延时,这个是不二的选择
[单片机]
STM32 ST-LINK Utility安装及使用
TM32 ST-LINK Utility集成开发环境的安装比较简单(基本上就是一路Next下去)。还是按照常规安装教程(截图)讲述一下吧,以上面下载的“STM32 ST-LINK Utility v4.0.0 setup.exe”软件为例讲述。 1.解压软件,双击“STM32 ST-LINK Utility v4.0.0.exe”,进入准备安装(解压)过程。 2.进入安装向导,点击“Next”。 3.同意许可,点击“Yes”。 4.选择安装路径(这里默认),点击“Next”。 5.进入安装过程,不到一分钟时间。 6.安装最后提示“安装驱动”,点击“下一步”,最后点击“完成”安装完成。 7.点击“F
[单片机]
<font color='red'>STM32</font> ST-LINK Utility安装及使用
STM32串口多机通信
从设备采用漏极开路方式级联,从设备的串口TX必须配置为漏极开路,不能是推挽方式,如果配置成推挽方式,会导致灌电流过大,低电平低不下去问题 STM32 的UART数据寄存器是9位,数据传输先传低位(LSB) --实际应用发现9位数据大时候有丢包错包问题?? 利用USART可以进行多机处理器通信,其原理就是使从机处于静默模式,由主机在需要的时候发送指令唤醒从机,并传输数据。STM32静默模式特点:1、所有接收状态位都不会被设置;2、所有的接收中断都被禁止;3、USART_CR1寄存器中的RWU位被置1,RUW可以硬件自动控制或者在某些条件下由软件写。 连接方法很简单,主机的TX输出与从机的RX端口直接相连,从机TX端口要经过与
[单片机]
分享STM32定时器输出比较模式的理解
初学STM32,我这个地方卡了很久,现在终于有些明白了,现在把我的理解写下与大家共享,如果有不对的地方,还请指出。 TIM_OCMode选择定时器模式。该参数取值见下表: TIM_OCInitStructure.TIM_Pulse = CCR1_Val; //设置跳变值,当计数器计数到这个值时,电平发生跳变 TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIMx在CCR1上的预装载寄存器 TIM_ARRPreloadConfig(TIM3, ENABLE); //使能TIMx在ARR上的预装载寄存器 OCxREF就是一个参考信号,并且约定:OCxREF=1,称O
[单片机]
分享<font color='red'>STM32</font>定时器输出比较模式的理解
关于STM32中RTC的校准方法
实现RTC 校准的核心之一是库文件Stm321f0x_bkp.c中的void BKP_SetRTCCalibrationValue (uint8_t CalibrationValue) 函数。谈到RTC校准的相关参考文档包括AN2604.pdf,AN2821.pdf和AN2821.zip。这三个文档都可以从STM32官方网站下载。 按照AN2604.pdf描述的原理,RTC 的校准值应在0-127之间。可实现的校准误差对应为0-121ppm。相当于每30天跑快的秒数为0-314s。 这里应注意的一个关键问题是,RTC只能对跑快进行校准,不能对跑慢进行校准。如果手表晶振的标称频率是32768Hz,设其可能的误差范围是 2Hz,则实
[单片机]
STM32上电以后GPIO默认是Floating input
真实案例1: 用开发板STM32的PD13来测试,直接裸露的管脚。 硬件连接我手上发光二极管的比较长的一端也就是 + 极,开发板找GND连接二极管较短的一端也就是 - 极。 #define TSBUZGPIO GPIOD #define TSBUZGPIOPIN GPIO_Pin_13 #define TS_BUZ_H() GPIO_SetBits(TSBUZGPIO ,TSBUZGPIOPIN) #define TS_BUZ_L() GPIO_ResetBits(TSBUZGPIO ,TSBUZGPIOPIN) void TS_Buz_Init(void) { GPIO
[单片机]
<font color='red'>STM32</font>上电以后GPIO默认是Floating input
STM32+ESP8266+MQTT协议连接腾讯物联网开发平台
一、环境介绍 单片机采用:STM32F103C8T6 上网方式:采用ESP8266,也可以使用其他设备代替,只要支持TCP协议即可。比如:GSM模块、有线网卡等。 开发软件:keil5 物联网平台: 腾讯IOT物联网物联网平台。腾讯的物联网平台比起其他厂家的物联网平台更加有优势,腾讯物联网平台可以将数据推到微信小程序上,用户可以直接使用小程序绑定设备,完成与设备之间交互,现在用户基本都会使用微信,所以使用起来非常方便。 本文章配套使用的STM32设备端完整源代码下载地址: https://download.csdn.net/download/xiaolong1126626497/18785807 STM
[单片机]
STM32+ESP8266+MQTT协议连接腾讯物联网开发平台
STM32 FSMC总线与TFT8080接口对接分析
1. FSMC协议分析 如下为ILI9325的8080接口的协议 从图中可以看出8080接口的协议大概流程是:先发出片选信号,然后发出命令使能或者数据使能信号,待数据建立完成后,在读写信号的上升沿写入数据或者读出数据。 CS(片选信号):低电平片选有效,高电平失能(默认为高:失能) RS(数据/命令):低电平写命令,高电平写数据(默认为高:写数据)FSMC默认为低。。。。 RD(读信号) :低电平有效,上升沿写入数据,高电平失能(默认为高,失能) WR(写信号) :低电平有效,上升沿写入数据,高电平失能(默认为高,失能) FSMC写SRAM模式如下: FSMC对于类RAM存储器的读操作过程一般是:先发出片选信号、读写信号和地
[单片机]
<font color='red'>STM32</font> FSMC总线与TFT8080接口对接分析
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved