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

基于STM32堆栈的经验分享

[复制链接]
攻城狮Melo 发布时间:2023-3-26 16:36
对于了解一点汇编编程的人,就可以知道,堆栈是内存中一段连续的存储区域,用来保存一些临时数据。堆栈操作由PUSH、POP两条指令来完成。而程序内存可以分为几个区:
7 c, a- b! y( ~! T  `栈区(stack)9 e" E6 C+ ]5 j; r6 R0 C; O# s
堆区(Heap)- e; h+ w, Q& Q& D, D5 o' Q* i
全局区(static)4 E" b9 q% i& \5 n$ L* \* v! R
文字常亮区程序代码区( M$ \- k1 `( k* L; W( R
程序编译之后,全局变量,静态变量已经分配好内存空间,在函数运行时,程序需要为局部变量分配栈空间,当中断来时,也需要将函数指针入栈,保护现场,以便于中断处理完之后再回到之前执行的函数。
2 j. d3 N' M5 f7 t  U* n; R- U2 @4 _# {
栈是从高到低分配,堆是从低到高分配。- P" W6 l4 n+ A" T% g, y# b2 x' j

: C+ N* A( @# K$ ]8 J  ]

8 X6 |2 P4 r) h0 r* K4 x普通单片机与STM32单片机中堆栈的区别- _+ g: e# W9 ^- z! C
普通单片机启动时,不需要用bootloader将代码从ROM搬移到RAM。但是STM32单片机需要。
; a/ e: J  w0 C  k- `/ n. J! [' }, W4 S' N
这里我们可以先看看单片机程序执行的过程,单片机执行分三个步骤:) h  W$ y# u7 t( @# X
取指令
" x6 M- [9 J; i9 C* E分析指令1 c* V" l* Q- m" v4 J  w
执行指令% i( F9 f6 Y; V4 u2 n- {
3 _7 r4 L6 K% R
根据PC的值从程序存储器读出指令,送到指令寄存器。然后分析执行执行。这样单片机就从内部程序存储器去代码指令,从RAM存取相关数据。- B1 }& e. c$ W$ @$ T

0 h1 q0 p4 s" X! S1 I  FRAM取数的速度是远高于ROM的,但是普通单片机因为本身运行频率不高,所以从ROM取指令慢并不影响。- Z4 ?/ m$ I/ r- W9 y0 }3 J8 _: S' O' V
+ Q! ]0 T5 H$ \
而STM32的CPU运行的频率高,远大于从ROM读写的速度。所以需要用bootloader将代码从ROM搬移到RAM。" d5 [6 V4 q( ?+ V) B2 K2 ~% K
: h& X. I# r; Q, `
使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。# b8 A  {- i7 O" I: s# h

. A0 W2 w; o+ V0 a/ Y其实堆栈就是单片机中的一些存储单元,这些存储单元被指定保存一些特殊信息,比如地址(保护断点)和数据(保护现场)。% |  v8 w! D) ?# N# |' L; P8 I; |

. n8 l2 w4 I9 t" e3 ]* F& \如果非要给他加几个特点的话那就是:
' P0 O1 Z1 y3 z( C' t' I# F这些存储单元中的内容都是程序执行过程中被中断打断时,事故现场的一些相关参数。如果不保存这些参数,单片机执行完中断函数后就无法回到主程序继续执行了。
0 W5 C& U& @6 O& g0 d, t3 B这些存储单元的地址被记在了一个叫做堆栈指针(SP)的地方。5 H. t" n- ^2 s* d3 x, C. Z. V  g3 F
6 |  w7 f0 Q" r8 c  J% U' [
结合STM32的开发讲述堆栈# M0 H) E# q3 g5 [
从上面的描述可以看得出来,在代码中是如何占用堆和栈的。可能很多人还是无法理解,这里再结合STM32的开发过程中与堆栈相关的内容来进行讲述。, ?- G2 I* D* ~% c
& M- c# S0 x" D4 L
如何设置STM32的堆栈大小?+ }* m7 X9 V  C- ^  H5 z
在基于MDK的启动文件开始,有一段汇编代码是分配堆栈大小的。
* W+ X' K+ _5 W" f$ U9 ~* q1 f, i* r
503b2762a351aa94932dffab1708c8a6.jpg 1 v8 f; i6 r; u; V% u
* P6 b! _6 X9 Z# {  a
这里重点知道堆栈数值大小就行。还有一段AREA(区域),表示分配一段堆栈数据段。数值大小可以自己修改,也可以使用STM32CubeMX数值大小配置,如下图所示。
9 |% [, z) O1 \2 r* \) f! A- J0 {4 S4 Q* N/ \
e6b7a00dfcaf74c9e3452b18367a8422.jpg 9 l7 `6 g7 ^( L5 Q" `) P) p+ v1 U
/ {% y7 w& _$ g/ v
' v- m. c; t% x4 b
STM32F1默认设置值0x400,也就是1K大小。
6 I/ [! j$ ~) u, O: o6 z$ Q
1 z( R, U6 ^3 y8 _0 Y- B3 l& ]8 y
cc2628fbe642d0be7e58fc5be36103a0.png # `5 }6 E- k* A" X; B
6 A* F% i; c' V( m0 H# ?% u
函数体内局部变量:
. M' N, Q+ C/ O9 I: q9 u0 h6 a/ g2 q0 f$ b- v- K" R% b! h% G% Q9 M
bd20f913c505b04041a031fa77b67070.png 5 t/ N! W' |+ r, |* C
4 ~: d6 K" l' D% u& f6 E* n  G
局部变量总共占用了256*4 + 1字节的栈空间。所以,在函数内有较多局部变量时,就需要注意是否超过我们配置的堆栈大小。( ~/ B! B" j% m( ]' W1 U' C0 o8 Q

! j8 t$ F2 C  v1 k8 w  @1 q$ Z函数参数:

9 a( Y- J& w4 V/ k# e  ]% o5 c* m# ~7 W6 }
ea5ed9c8b9eddeb89df76f988d3ad810.png ; e, b: l3 k* `: g/ C& ^1 h

$ e3 l4 k' ~( C8 v这里要强调一点:传递指针只占4字节,如果传递的是结构体,就会占用结构大小空间。提示:在函数嵌套,递归时,系统仍会占用栈空间。+ b4 V1 F5 U. k; ~
3 u5 \7 h5 v1 w
堆(Heap)的默认设置0x200(512)字节。2 V7 y" g0 |& L
. h1 z! y( [6 n5 D' }
e0c660804c46e5cdb98f8f8ec14f5d56.png & q& A1 m0 U8 [& e3 n

4 M3 O! y! y1 s& k$ ]4 n$ n9 r0 v" N: T大部分人应该很少使用malloc来分配堆空间。虽然堆上的数据只要程序员不释放空间就可以一直访问,但是,如果忘记了释放堆内存,那么将会造成内存泄漏,甚至致命的潜在错误。
5 `' I9 r+ x3 `. I3 E. n& S
# g: j2 k/ M) t$ b8 t* y

7 M8 C! ^  n; G; N0 a+ t# oMDK中RAM占用大小分析2 h5 X! a! @9 e6 b/ k
经常在线调试的人,可能会分析一些底层的内容。这里结合MDK-ARM来分析一下RAM占用大小的问题。在MDK编译之后,会有一段RAM大小信息:
, w0 Q. d6 W' ?' }
5 @4 c) A5 V' v% y# p8 b
ad57b1adafcb897808c1a36c4d5ef252.png % i8 @" Z% |# |* d" d
! q5 s+ j+ [" A0 A# ?2 F
这里4+6=1640,转换成16进制就是0x668,在进行在调试时,会出现:
: g* P2 G' s2 }$ D0 z
+ L2 x$ I( k# G+ E$ l9 K- U8 D
42bbf2b1be24899a20d21d82ee4bf1a2.jpg * I- ]+ Y. A4 @8 W( M
: }  U. Y5 }. `$ y$ u: [7 v
这个MSP就是主堆栈指针,一般我们复位之后指向的位置,复位指向的其实是栈顶:6 b3 z& [( Q+ ^* z6 o- b' d. m( y

# G, m% X5 t% e! I 1376b8f115b5a29b448f3393b7aa3ac1.jpg
5 _9 M4 `, J2 N. {* e/ |1 D
& Z& n  n5 x7 N2 |  c
而MSP指向地址0x20000668是0x20000000偏移0x668而得来。具体哪些地方占用了RAM,可以参看map文件中【Image Symbol Table】处的内容:
0 W; Z: d- U5 c+ i  A4 d# x' u$ K7 f) D: U9 u* M
79204b82f2ec3e0dc506ccb26e2b6bd0.jpg
" w. ~$ y8 F7 B) ?% Q: S6 _' n0 S6 b" T* d

% T% L: n5 z1 ~' W& N————————————————
* D/ I  O% V" O1 D版权声明:被大佬糊弄的只会点灯的小菜鸡
+ v9 T! }2 ~, s; m! _$ d# B如有侵权请联系删除3 Y& ^) c, l0 G9 t+ z

6 K& A+ ^% B0 Z# Z6 L% j- r2 b8 V( ]" {3 d: z: S4 c" v
4 c$ ?7 Q* G4 y0 T, V8 z
赞 收藏 评论0 发布时间:2023-3-26 16:36

举报

0个回答

所属标签

相似技术帖

官网相关资源

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