
学习STM32单片机的时候,总是能遇到“堆栈”这个概念。分享本文,希望对你理解堆栈有帮助。 对于了解一点汇编编程的人,就可以知道,堆栈是内存中一段连续的存储区域,用来保存一些临时数据。堆栈操作由PUSH、POP两条指令来完成。而程序内存可以分为几个区:
普通单片机与STM32单片机中堆栈的区别 普通单片机启动时,不需要用bootloader将代码从ROM搬移到RAM。这里我们可以先看看单片机程序执行的过程,单片机执行分三个步骤:
RAM取数的速度是远高于ROM的,但是普通单片机因为本身运行频率不高,所以从ROM取指令慢并不影响。0 D; C; S' U7 y1 D 而STM32的CPU运行的频率高,远大于从ROM读写的速度。所以需要用bootloader将代码从ROM搬移到RAM。 使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。* { b. I, J8 @) X W% Z 其实堆栈就是单片机中的一些存储单元,这些存储单元被指定保存一些特殊信息,比如地址(保护断点)和数据(保护现场)。( w/ r" J l% v8 V" V/ \ 如果非要给他加几个特点的话那就是:
+ Y7 Y, R( c6 l( ~: B2 x 结合STM32的开发讲述堆栈6 A+ _: }2 u/ a5 ^- ? 从上面的描述可以看得出来,在代码中是如何占用堆和栈的。可能很多人还是无法理解,这里再结合STM32的开发过程中与堆栈相关的内容来进行讲述。 如何设置STM32的堆栈大小? 在基于MDK的启动文件开始,有一段汇编代码是分配堆栈大小的。) _3 Q2 `5 U: l9 ~( ~& u 2 b; c; t; B) G4 B6 Q0 V 8 O6 s2 x9 f/ K% p ![]() ( W; N! z/ a, \/ U) c* w5 S; c9 F& [5 _ 这里重点知道堆栈数值大小就行。还有一段AREA(区域),表示分配一段堆栈数据段。数值大小可以自己修改,也可以使用STM32CubeMX数值大小配置,如下图所示。 ![]() STM32F1默认设置值0x400,也就是1K大小。) `! n4 ]' c5 D/ Y Stack_Size EQU 0x400 6 ]) H8 r0 X+ K 3 B1 b9 U( o* d. D" a . }, L# n4 i8 N2 A4 c 函数体内局部变量:7 B' m# S% u9 l) L ? z$ I1 H4 T void Fun(void){ char i; int Tmp[256]; //...} 局部变量总共占用了256*4 + 1字节的栈空间。所以,在函数内有较多局部变量时,就需要注意是否超过我们配置的堆栈大小。- J/ W7 h6 X6 m! ]$ z$ f8 I 7 v' h+ I# ?. [4 m# u1 [- g 函数参数: void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init) 这里要强调一点:传递指针只占4字节,如果传递的是结构体,就会占用结构大小空间。提示:在函数嵌套,递归时,系统仍会占用栈空间。 ( {4 Q/ l% Y t6 ~3 x 堆(Heap)的默认设置0x200(512)字节。 Heap_Size EQU 0x200 大部分人应该很少使用malloc来分配堆空间。虽然堆上的数据只要程序员不释放空间就可以一直访问,但是,如果忘记了释放堆内存,那么将会造成内存泄漏,甚至致命的潜在错误。 7 ?+ }) r7 i4 Q1 v3 O/ Y 6 t$ P' c3 i, i1 b& b; k MDK中RAM占用大小分析 经常在线调试的人,可能会分析一些底层的内容。这里结合MDK-ARM来分析一下RAM占用大小的问题。在MDK编译之后,会有一段RAM大小信息: 3 V4 _8 d3 e9 P8 [; a ![]() 8 t& S$ T! G: R: t8 Y 6 I8 y! u8 `% B5 V9 l/ F" l 这里4+6=1640,转换成16进制就是0x668,在进行在调试时,会出现: ![]() 这个MSP就是主堆栈指针,一般我们复位之后指向的位置,复位指向的其实是栈顶: ![]() * G F7 p" f7 R6 l! ?; p 而MSP指向地址0x20000668是0x20000000偏移0x668而得来。具体哪些地方占用了RAM,可以参看map文件中【Image Symbol Table】处的内容:9 G% N; l4 T4 ~ ![]() + r( o. j+ F) r 6 q. o8 K3 Y* s3 b* J* y 转载自:STM32嵌入式开发" g" }/ u2 p7 \$ N) @' n# b& ~ |
【2025·STM32峰会】GUI解决方案实训分享1-对LVGL咖啡机例程的牛刀小试以及问题排查
OpenBLT移植到STM32F405开发板
为什么要先开启STM32外设时钟?
【STM32MP157】从ST官方例程中分析RPMsg-TTY/SDB核间通信的使用方法
【经验分享】STM32实例-RTC实时时钟实验④-获取RTC时间函数与中断服务函数
STM32 以太网 MAC Loopback 的实现
STM32功能安全设计包,助力产品功能安全认证
基于STM32启动过程startup_xxxx.s文件经验分享
HRTIM 指南
ST 微控制器电磁兼容性 (EMC) 设计指南