0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

详解STM32堆栈

GReq_mcu168 来源:硬件攻城狮 作者:硬件攻城狮 2022-03-11 09:51 次阅读

学习STM32单片机的时候,总是能遇到“堆栈”这个概念。分享本文,希望对你理解堆栈有帮助。

对于了解一点汇编编程的人,就可以知道,堆栈是内存中一段连续的存储区域,用来保存一些临时数据。堆栈操作由PUSH、POP两条指令来完成。而程序内存可以分为几个区:

栈区(stack)

堆区(Heap)

全局区(static

文字常亮区程序代码

程序编译之后,全局变量,静态变量已经分配好内存空间,在函数运行时,程序需要为局部变量分配栈空间,当中断来时,也需要将函数指针入栈,保护现场,以便于中断处理完之后再回到之前执行的函数。
栈是从高到低分配,堆是从低到高分配。
普通单片机与STM32单片机中堆栈的区别
普通单片机启动时,不需要用bootloader将代码从ROM搬移到RAM

但是STM32单片机需要。

这里我们可以先看看单片机程序执行的过程,单片机执行分三个步骤:

取指令

分析指令

执行指令

根据PC的值从程序存储器读出指令,送到指令寄存器。然后分析执行执行。这样单片机就从内部程序存储器去代码指令,从RAM存取相关数据。

RAM取数的速度是远高于ROM的,但是普通单片机因为本身运行频率不高,所以从ROM取指令慢并不影响。

而STM32的CPU运行的频率高,远大于从ROM读写的速度。所以需要用bootloader将代码从ROM搬移到RAM。

使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。

其实堆栈就是单片机中的一些存储单元,这些存储单元被指定保存一些特殊信息,比如地址(保护断点)和数据(保护现场)。

如果非要给他加几个特点的话那就是:

这些存储单元中的内容都是程序执行过程中被中断打断时,事故现场的一些相关参数。如果不保存这些参数,单片机执行完中断函数后就无法回到主程序继续执行了。

这些存储单元的地址被记在了一个叫做堆栈指针(SP)的地方。

结合STM32的开发讲述堆栈

从上面的描述可以看得出来,在代码中是如何占用堆和栈的。可能很多人还是无法理解,这里再结合STM32的开发过程中与堆栈相关的内容来进行讲述。

如何设置STM32的堆栈大小?

在基于MDK的启动文件开始,有一段汇编代码是分配堆栈大小的。

d6e99b46-59c0-11ec-b2e9-dac502259ad0.png

这里重点知道堆栈数值大小就行。还有一段AREA(区域),表示分配一段堆栈数据段。数值大小可以自己修改,也可以使用STM32CubeMX数值大小配置,如下图所示。

d710eb4c-59c0-11ec-b2e9-dac502259ad0.png

STM32F1默认设置值0x400,也就是1K大小。

Stack_Size EQU 0x400

函数体内局部变量:

void Fun(void){ char i; int Tmp[256]; //...}

局部变量总共占用了256*4 + 1字节的栈空间。所以,在函数内有较多局部变量时,就需要注意是否超过我们配置的堆栈大小。

函数参数:

voidHAL_GPIO_Init(GPIO_TypeDef*GPIOx,GPIO_InitTypeDef *GPIO_Init)

这里要强调一点:传递指针只占4字节,如果传递的是结构体,就会占用结构大小空间。提示:在函数嵌套,递归时,系统仍会占用栈空间。

堆(Heap)的默认设置0x200(512)字节。

Heap_Size EQU 0x200

大部分人应该很少使用malloc来分配堆空间。虽然堆上的数据只要程序员不释放空间就可以一直访问,但是,如果忘记了释放堆内存,那么将会造成内存泄漏,甚至致命的潜在错误。

MDK中RAM占用大小分析

经常在线调试的人,可能会分析一些底层的内容。这里结合MDK-ARM来分析一下RAM占用大小的问题。在MDK编译之后,会有一段RAM大小信息:

d736d352-59c0-11ec-b2e9-dac502259ad0.png

这里4+6=1640,转换成16进制就是0x668,在进行在调试时,会出现:

d74b3360-59c0-11ec-b2e9-dac502259ad0.png

这个MSP就是主堆栈指针,一般我们复位之后指向的位置,复位指向的其实是栈顶:

d75dbd46-59c0-11ec-b2e9-dac502259ad0.png

而MSP指向地址0x20000668是0x20000000偏移0x668而得来。具体哪些地方占用了RAM,可以参看map文件中【Image Symbol Table】处的内容:

d76af862-59c0-11ec-b2e9-dac502259ad0.png

审核编辑 :李倩

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • STM32
    +关注

    关注

    2239

    文章

    10671

    浏览量

    348738
  • 堆栈
    +关注

    关注

    0

    文章

    171

    浏览量

    19520

原文标题:详解STM32堆栈

文章出处:【微信号:mcu168,微信公众号:硬件攻城狮】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    stm32是怎么获取大小的+ucos iii

    是能在KEIL UV4上成功运行的,初步怀疑是的分配有问题(因为ucosiii中要用malloc动态分配内存),所以我想知道stm32是如何获取
    发表于 03-28 15:46

    STM32堆栈增长方向问题

    STM32堆栈增长方向是从高地址往低地址增长的,这样的话底应该是高地址咯。而下图的底却是低地址,查了很多资料,感觉都很矛盾。像INT8UOSTaskCreateExt 的第三个参
    发表于 04-20 04:36

    哪位大神可以详细介绍ATtiny13堆栈指针?

    ATtiny13堆栈指针
    发表于 11-10 08:30

    详解STM32单片机的堆栈

    ,程序需要为局部变量分配空间,当中断来时,也需要将函数指针入,保护现场,以便于中断处理完之后再回到之前执行的函数。 是从高到低分配,是从低到高分配。普通单片机与
    发表于 01-12 11:30

    freertos与STM32如何分配堆栈空间

    freertos与STM32分析、全局区、常量区、代码区、RAM、ROM,及如何分配堆栈空间基于STM32分析
    发表于 08-03 06:36

    C语言单片机堆栈的区别是什么?

    C语言单片机堆栈的区别是什么?
    发表于 10-13 08:09

    怎样去设置STM32堆栈空间的大小呢

    怎样去设置STM32堆栈空间的大小呢?STM32有哪几种调节堆栈空间大小的方式?
    发表于 10-21 07:33

    STM32堆栈的地址是怎么得出来的?

    STM32堆栈的地址是怎么得出来的?
    发表于 11-26 07:14

    什么是?什么是

    ,程序执行过程中溢出,极大可能的影响程序、系统的稳定,严重时会造成程序、系统的崩溃,所以堆栈溢出检测十分重要且必要。什么是,什么是
    发表于 12-22 06:09

    STM32堆栈区划分

    STM32堆栈区(一)一个由C/C++编译的程序占用的内存分为以下几个部分:区(stack):编译器自动分配释放,存放函数的参数值,局部变量的值等。操作方式类似于数据结构中的
    发表于 01-20 08:32

    atmega128堆栈的特点是什么?

    atmega128堆栈的特点是什么?
    发表于 01-24 07:16

    stm32的相关资料推荐

    关于已经是程序员的一个月经话题,大部分有是基于os层来聊的。那么,在赤裸裸的单片机下的是什么样的分布呢?以下是网摘:刚接手STM32
    发表于 01-25 06:54

    STM32堆栈溢出检测相关资料下载

    函数调用,局部变量等数据。heap用于动态内存分配。堆栈可以在启动文件或者链接脚本中指定大小,但在实际开发中,尤其工程量较大的项目中难以确定堆栈使用量,容易造成堆栈溢出,造成程序崩溃
    发表于 02-21 07:05

    怎样去解决STM32堆栈空间不足的问题呢

    怎样去设置STM32启动文件堆栈空间的大小呢?怎样去解决STM32堆栈空间不足的问题呢?
    发表于 02-21 06:39

    软件中的堆栈是不同的东西吗?

    区和区有什么不同的地方
    发表于 10-10 07:12