STMCU小助手
发布时间:2022-10-31 22:13
学习STM32单片机的时候,总是能遇到“堆栈”这个概念。分享本文,希望对你理解堆栈有帮助。 对于了解一点汇编编程的人,就可以知道,堆栈是内存中一段连续的存储区域,用来保存一些临时数据。堆栈操作由PUSH、POP两条指令来完成。而程序内存可以分为几个区:
普通单片机与STM32单片机中堆栈的区别 普通单片机启动时,不需要用bootloader将代码从ROM搬移到RAM。这里我们可以先看看单片机程序执行的过程,单片机执行分三个步骤:
RAM取数的速度是远高于ROM的,但是普通单片机因为本身运行频率不高,所以从ROM取指令慢并不影响。 而STM32的CPU运行的频率高,远大于从ROM读写的速度。所以需要用bootloader将代码从ROM搬移到RAM。 使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。 其实堆栈就是单片机中的一些存储单元,这些存储单元被指定保存一些特殊信息,比如地址(保护断点)和数据(保护现场)。/ ?- o# R. @$ h) d 如果非要给他加几个特点的话那就是:
- h* O9 ~0 A) B }9 k2 D* ` 结合STM32的开发讲述堆栈2 T7 y$ O4 X& A; P X% H/ n 从上面的描述可以看得出来,在代码中是如何占用堆和栈的。可能很多人还是无法理解,这里再结合STM32的开发过程中与堆栈相关的内容来进行讲述。 如何设置STM32的堆栈大小?0 \4 r0 ?! h# k3 i2 f5 A/ e 在基于MDK的启动文件开始,有一段汇编代码是分配堆栈大小的。 R7 b2 } m7 F 4 ?- t+ ?* M4 ^
\5 x3 E. c' M6 Z3 m 这里重点知道堆栈数值大小就行。还有一段AREA(区域),表示分配一段堆栈数据段。数值大小可以自己修改,也可以使用STM32CubeMX数值大小配置,如下图所示。 0 L% V) F( b0 G/ {+ f
STM32F1默认设置值0x400,也就是1K大小。 6 F' K e" M& I) a) f 9 L: m/ l& [7 h9 S. u) ^ Stack_Size EQU 0x400 8 B* Z) ]3 x+ Z 函数体内局部变量:4 a' Q, `( N! J9 \ void Fun(void){ char i; int Tmp[256]; //...} 局部变量总共占用了256*4 + 1字节的栈空间。所以,在函数内有较多局部变量时,就需要注意是否超过我们配置的堆栈大小。+ w+ X4 Q- U- N7 W! m9 e . p* ]6 ?$ G" Y& | 8 |: c0 U1 p. r% G/ P j6 u: k0 ` 函数参数:7 R5 u6 C; ?1 j( V: r2 u void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init) 这里要强调一点:传递指针只占4字节,如果传递的是结构体,就会占用结构大小空间。提示:在函数嵌套,递归时,系统仍会占用栈空间。( T4 J/ Q4 `5 s r2 {! g $ V: H7 z7 b& |& n% g$ q 堆(Heap)的默认设置0x200(512)字节。 Heap_Size EQU 0x200, a- {' N/ G) [9 {% w: R" W ; h' j" k! r+ @4 [; t 大部分人应该很少使用malloc来分配堆空间。虽然堆上的数据只要程序员不释放空间就可以一直访问,但是,如果忘记了释放堆内存,那么将会造成内存泄漏,甚至致命的潜在错误。 7 F* |# D! U0 Z% H9 e 3 U8 A; q" W* N; v MDK中RAM占用大小分析 经常在线调试的人,可能会分析一些底层的内容。这里结合MDK-ARM来分析一下RAM占用大小的问题。在MDK编译之后,会有一段RAM大小信息:/ M( Z* g1 R& J6 T& P 1 Y r! O; v- i8 R' \! A$ d9 P
) w& H. k7 t3 x/ G$ u7 T+ e 这里4+6=1640,转换成16进制就是0x668,在进行在调试时,会出现:* X' F# [2 \# r1 p6 L8 Y8 f& B
这个MSP就是主堆栈指针,一般我们复位之后指向的位置,复位指向的其实是栈顶: " Y" [4 `7 N% l6 p4 H
) n t( e5 d6 v9 v, I6 W$ s ! ~6 ^8 P9 X3 _& `! { 而MSP指向地址0x20000668是0x20000000偏移0x668而得来。具体哪些地方占用了RAM,可以参看map文件中【Image Symbol Table】处的内容: " p& _/ w2 ?1 s+ Z6 e
f1 X4 G" q x( L+ r" l1 M 转载自:STM32嵌入式开发* O! [0 R$ a- C, q |
【STM32H735G-DK 测评】STM32H735G-DK External Loder 编译和测试
Keil-MDK 在线调试设置断点的高级用法
请教下STM32N6570 怎么把分辨率改成320x240并可以全屏显示
【福利三:逢7发帖赢大礼】想要充分利用STM32H743VI片内的RAM空间(但并不顺利)
基于stm32平台上的IC-MU磁绝对值编码器SPI通讯和码盘数据处理
使用STM32 MCU和MPU连接PDM数字麦克风
分享STM32资料-采用 STM32U031R8 MCU 的 STM32 Nucleo-64 开发板,官方资料,数据手册等资料
HRTIM 指南
使用 STM32 的 DWT 单元监控内存
DAC,COMP,HRTIM Fault 功能的使用
微信公众号
手机版