你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

详解STM32单片机的堆栈

[复制链接]
STMCU小助手 发布时间:2022-10-31 22:13
学习STM32单片机的时候,总是能遇到“堆栈”这个概念。分享本文,希望对你理解堆栈有帮助。    对于了解一点汇编编程的人,就可以知道,堆栈是内存中一段连续的存储区域,用来保存一些临时数据。堆栈操作由PUSH、POP两条指令来完成。而程序内存可以分为几个区:
  • 栈区(stack)
  • 堆区(Heap)
  • 全局区(static)
  • 文字常亮区程序代码区) t5 E' y( i7 v, o( h
    程序编译之后,全局变量,静态变量已经分配好内存空间,在函数运行时,程序需要为局部变量分配栈空间,当中断来时,也需要将函数指针入栈,保护现场,以便于中断处理完之后再回到之前执行的函数。    栈是从高到低分配,堆是从低到高分配。
# c, [3 A2 `8 z. k' V普通单片机与STM32单片机中堆栈的区别* N* {. j* ?; v, t4 K9 k
    普通单片机启动时,不需要用bootloader将代码从ROM搬移到RAM。
这里我们可以先看看单片机程序执行的过程,单片机执行分三个步骤:
  • 取指令
  • 分析指令
  • 执行指令
    ! k. l5 l( F3 l8 Y  B9 H
    根据PC的值从程序存储器读出指令,送到指令寄存器。然后分析执行执行。这样单片机就从内部程序存储器去代码指令,从RAM存取相关数据。
6 E! d7 D! F  a4 v% x$ j# X/ s1 \1 w    RAM取数的速度是远高于ROM的,但是普通单片机因为本身运行频率不高,所以从ROM取指令慢并不影响。2 ?! S0 _9 G9 n' S
    而STM32的CPU运行的频率高,远大于从ROM读写的速度。所以需要用bootloader将代码从ROM搬移到RAM。
+ H  ?/ [  \) ?! a  使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。5 H. ], M, }. c0 J
    其实堆栈就是单片机中的一些存储单元,这些存储单元被指定保存一些特殊信息,比如地址(保护断点)和数据(保护现场)。2 ]' I* P# e/ ~# |
    如果非要给他加几个特点的话那就是:
  • 这些存储单元中的内容都是程序执行过程中被中断打断时,事故现场的一些相关参数。如果不保存这些参数,单片机执行完中断函数后就无法回到主程序继续执行了。
  • 这些存储单元的地址被记在了一个叫做堆栈指针(SP)的地方。! y+ t4 s- @  _1 y. A5 Y
: T: _4 \1 k2 A  |( v

# i; M9 W6 \3 t8 [% @/ Y& |结合STM32的开发讲述堆栈
: `7 X- z7 t% y    从上面的描述可以看得出来,在代码中是如何占用堆和栈的。可能很多人还是无法理解,这里再结合STM32的开发过程中与堆栈相关的内容来进行讲述。2 `8 v0 E* `$ L# Z; u
    如何设置STM32的堆栈大小?# Q2 A0 Z# R- k* f, s8 R
    在基于MDK的启动文件开始,有一段汇编代码是分配堆栈大小的。0 q" J9 O7 L  h0 O

# O9 N7 j3 O" D5 \, |/ f2 g4 w

8 C5 E8 j! `0 V, `/ F0 l; y! G 微信图片_20221031215329.png 9 W3 v! l! A* O% o2 V0 y- m& S

" N& u3 ]$ d0 @" ^: n, V+ R0 n- \
+ U/ \, A6 u3 s) H: a  U/ ?) z/ s
    这里重点知道堆栈数值大小就行。还有一段AREA(区域),表示分配一段堆栈数据段。数值大小可以自己修改,也可以使用STM32CubeMX数值大小配置,如下图所示。, v1 c) O0 k4 x! |' G$ V2 E

9 u, a6 [8 v! T% b4 C0 _, o

+ C4 }/ N3 l) m, a7 j( [ 微信图片_20221031215326.png ; y* x7 m3 T) U4 x0 v
+ ?1 s- D( {: O$ p# f# S

8 Y4 s( _0 h+ `& s& _    STM32F1默认设置值0x400,也就是1K大小。
: v- o& L$ B2 L) x" \: |  _
& l, N7 @! ?( V0 P. t
% y% f  `+ _, z; [3 p: u6 N7 P
Stack_Size EQU 0x400 ' f& s( u: ~: e' C. n6 L

+ @& b( x+ D! e  m+ g8 y1 q& P

8 ~) N. o$ |7 J$ O9 T   函数体内局部变量:
4 V* |" }, p. j+ U" V# |1 p
void Fun(void){ char i; int Tmp[256]; //...}    局部变量总共占用了256*4 + 1字节的栈空间。所以,在函数内有较多局部变量时,就需要注意是否超过我们配置的堆栈大小。0 E" |( l. |3 ]% o* n( V

) r2 A* i" ^5 C' N

8 w3 W% E" W! l; t/ K& u% w" u+ T    函数参数:
7 v/ H: b! z8 X7 `$ ~% k
void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)    这里要强调一点:传递指针只占4字节,如果传递的是结构体,就会占用结构大小空间。提示:在函数嵌套,递归时,系统仍会占用栈空间。
# v! b9 }% V6 r1 P6 F( Y5 [9 S! d% m* S3 y
# P; L( Y9 c) g
    堆(Heap)的默认设置0x200(512)字节。$ _# O$ i* G* e7 t) {. l* u2 r
Heap_Size EQU 0x200' X" C- u7 L  h3 E$ \- c

" V! S/ F9 ]4 o% A  T6 F" |: J( c

2 Y/ j* f  e, m( H, {    大部分人应该很少使用malloc来分配堆空间。虽然堆上的数据只要程序员不释放空间就可以一直访问,但是,如果忘记了释放堆内存,那么将会造成内存泄漏,甚至致命的潜在错误。
7 c5 J0 b  J+ X8 p2 P9 r' [. _
6 {  `, m1 V& k8 {% `6 m

# D+ a/ ]3 |8 [, ~MDK中RAM占用大小分析
8 S* o" m$ S9 p   经常在线调试的人,可能会分析一些底层的内容。这里结合MDK-ARM来分析一下RAM占用大小的问题。在MDK编译之后,会有一段RAM大小信息:
0 W# x" y+ g3 j% z5 ~8 Q3 O: \
5 ~* {1 z2 X% z# p2 h& E

8 B1 @3 O' O, c: M# l9 { 微信图片_20221031215322.png     6 b3 Z& d6 D2 ^& V
0 \* S7 j2 y3 u9 s# w

1 ^! u' b* [* h: b- f这里4+6=1640,转换成16进制就是0x668,在进行在调试时,会出现:) P  e+ y# |% l( c2 p
, U# f. q' z) Y
微信图片_20221031215319.png
5 G0 v3 u- g! O3 z& ~0 p( L; _/ \, x8 `* L5 p* d- w- P- N
. j" _2 @- R1 o. u/ E9 ~
    这个MSP就是主堆栈指针,一般我们复位之后指向的位置,复位指向的其实是栈顶:7 h" S4 H7 m* r+ h: c
) U9 Q5 X! z- C% {
( N" @8 c. Z& V, Y
微信图片_20221031215316.png    
' g$ n& v' p9 i, a7 o4 {. \) C% S/ q

+ E$ e6 a- h  Q! i& s而MSP指向地址0x20000668是0x20000000偏移0x668而得来。具体哪些地方占用了RAM,可以参看map文件中【Image Symbol Table】处的内容:7 F2 ^" P/ F: [, ^

( n, I& X5 D! a; B$ z# c 微信图片_20221031215312.png # A+ B; n7 j* F' k  E2 i& k
6 U6 v) k) j$ p$ N+ \' a

& Y$ H/ ]0 d* E' y8 }& u! N% ~转载自:STM32嵌入式开发
3 y' B# R: k! }& h
赞 收藏 评论0 发布时间:2022-10-31 22:13

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版