打印
[其他ST产品]

STM32 内存分配、堆栈以及变量存储位置理解与分析

[复制链接]
3203|37
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
1、STM32内存(FLASH和RAM)
  一般来说单片机的内存指的是FLASH和RAM,当在程序中定义了全局变量、局部变量、只读变量等参数时都是会存放到对应的FLASH或者是RAM中。具体对单片机FLASH和RAM的介绍之后再写,这里只对单片机内存分配,对堆和栈以及变量的存储做一个梳理和记录。

2、FLASH
  FLASH主要是存放代码和数据的。下面是将 flash 内部进行细分之后的一张图。


使用特权

评论回复
沙发
一点点0321|  楼主 | 2023-7-31 17:04 | 只看该作者
STM32的flash是从地址0x0800 0000开始的,是向上增长的。Flash又可以细分为这么几个部分,分别是文本段 (Text),其中文本段中又包含可执行代码 (Executable Code)和常量 (Literal Value),在文本段之后就是只读数据区域 (Read Only Data),只读数据段后面接着的就是数据复制段 (Copy of Data Section),这个段充当的作用是存放程序中初始化为非 0 值的全局变量的初始值,之所以要将初始值存放到这里,是因为全局变量是存放在 RAM 上的,RAM 上的值掉电便丢失,每次上电后这些变量是要进行重新赋值的,而重新赋的值就存放在这里。
  可以看到STM32的flash中存放了代码、常量、只读数据和数据复制段。

使用特权

评论回复
板凳
一点点0321|  楼主 | 2023-7-31 17:04 | 只看该作者
如何理解这些我们来做个实验。简单写一个点亮LED的测试工程,定义由const修饰的一个常量TEST_DATA1,和一个有初始值的全局变量TEST_DATA2。
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "usart.h"       

const int TEST_DATA1= 4660; //一个常量

int TEST_DATA2=0x1112;//一个有初始值的全局变量

int main(void)
{
        delay_init(168);                  //初始化延时函数
        LED_Init();                        //初始化LED端口
        uart_init(115200);

        printf("%p\r\n",&TEST_DATA1);
        printf("%p\r\n",&TEST_DATA2);
        while(1)
        {
          GPIO_ResetBits(GPIOF,GPIO_Pin_9);  //LED0对应引脚GPIOF.9拉低,亮  等同LED0=0;
          GPIO_SetBits(GPIOF,GPIO_Pin_10);   //LED1对应引脚GPIOF.10拉高,灭 等同LED1=1;
          delay_ms(500);                     //延时300ms
          GPIO_SetBits(GPIOF,GPIO_Pin_9);           //LED0对应引脚GPIOF.0拉高,灭  等同LED0=1;
          GPIO_ResetBits(GPIOF,GPIO_Pin_10); //LED1对应引脚GPIOF.10拉低,亮 等同LED1=0;
          delay_ms(500);                     //延时300ms
        }
}

使用特权

评论回复
地板
一点点0321|  楼主 | 2023-7-31 17:04 | 只看该作者
验证过程:
  1、通过代码里printf把TEST_DATA1和TEST_DATA2的地址打印出来,通过串口助手可以看到:

  TEST_DATA1存放在flash的0x0800 0d4c中,而TEST_DATA2存在ram中。这里解释一下,TEST_DATA1是一个常量存放在flash中是没错的,而TEST_DATA2是一个有初始值的全局变量,应该和上面说的一样存放在flash中然后在上电时把值搬到ram中,但是为什么打印出来是在ram呢?原因应该是它已经搬完了。接下来进一步去flash中找这两个值。

使用特权

评论回复
5
一点点0321|  楼主 | 2023-7-31 17:04 | 只看该作者
2、在MAP文件中查找,通过双击“LED”,会跳转到MAP文件,我们使用快捷键“ctrl+f”在MAP中查找TEST_DATA变量,如下图

使用特权

评论回复
6
一点点0321|  楼主 | 2023-7-31 17:05 | 只看该作者

在这里依然是串口里打印出来的地址,那再换一种方式。

使用特权

评论回复
7
一点点0321|  楼主 | 2023-7-31 17:05 | 只看该作者
3、通过ST-LINK Utility软件直接查看芯片的flash。先定位到TEST_DATA1所在的0x0800 0d4c:

使用特权

评论回复
8
一点点0321|  楼主 | 2023-7-31 17:05 | 只看该作者
在flash的0x0800 0d4c处找到了定义的常量TEST_DATA1:4660(0x1234),通过全局搜索定义的TEST_DATA2:0x1112,在flash的最后找到了这个全局变量的初始值0x1112。

使用特权

评论回复
9
一点点0321|  楼主 | 2023-7-31 17:06 | 只看该作者
这里已经验证过这两个值就是定义的TEST_DATA1和TEST_DATA2,还想测试的话可以多定义几个,结果是一样的。
  这就是flash中变量的存储,除了代码外,还存在一些常量、只读变量以及有初始值的全局变量。

使用特权

评论回复
10
一点点0321|  楼主 | 2023-7-31 17:06 | 只看该作者
3、RAM
  相对对flash来说,ram主要就是用来存储数据了,如下是STM32中ram的分区

 ram中包含了如下几个部分:
    1、data : 存放初始化为非 0 值的全局变量
    2、bss : 存放未初始化或者是初始化为 0 的全局变量
    3、堆 (heap) : 由 malloc 申请,由 free 释放
    4、栈 (Stack) : 存放局部变量和函数调用时的返回地址

使用特权

评论回复
11
一点点0321|  楼主 | 2023-7-31 17:07 | 只看该作者
其中data和bss比较好理解就是一些全局变量。堆和栈的空间可以由我们来自由设定如下图所示,只要这些部分加起来不超过STM32的RAM空间。

使用特权

评论回复
12
一点点0321|  楼主 | 2023-7-31 17:07 | 只看该作者
  在STM32的启动文件(.s)中,刚开头就有对堆和栈空间的定义描述。如图定义了栈的大小是(0x400),堆的大小是(0x200)。栈里面存放的是一些函数执行时的局部变量、中断入口等,函数执行结束时这些存储单元自动被释放。堆是程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在适当的时候用free或delete释放内存。

使用特权

评论回复
13
一点点0321|  楼主 | 2023-7-31 17:07 | 只看该作者
再来看一下MAP文件,如下图

使用特权

评论回复
14
一点点0321|  楼主 | 2023-7-31 17:07 | 只看该作者
 可以看到在整个ram空间(0x2000 0000起)依次存放了data、bss、HEAP、STACK,其中堆和栈的大小和我们定义的是一致的。
  在ram中值得关注的是堆和栈的空间,堆是向上增长的而栈是向下生长的,如果一个函数运行的时候有大量的局部变量(栈向下增长),同时程序在整个过程中malloc申请了大量的堆空间而没有释放(堆向上增长),造成堆和栈空间的冲突,一旦堆栈冲突,系统就崩溃了。

使用特权

评论回复
15
一点点0321|  楼主 | 2023-7-31 17:07 | 只看该作者
特别说明一下,我使用了很多正点原子的工程,他们里面使用的自定义的mymalloc函数(区别于C的malloc)存放在bss字段里而不是HEAP字段里,使用的时候别搞混了。
  综上就是STM32内存分配、堆栈以及变量存储位置的理解。

使用特权

评论回复
16
jackcat| | 2023-8-4 13:49 | 只看该作者
堆栈是一种数据结构              

使用特权

评论回复
17
yorkbarney| | 2023-8-4 14:15 | 只看该作者
堆栈用于存储函数调用期间的局部变量、函数参数和返回地址等。在STM32上,堆栈通常使用由MSP(Main Stack Pointer)和PSP(Process Stack Pointer)指向的SRAM区域。

MSP用于主线程和中断服务例程的堆栈,而PSP用于任务(多线程)的堆栈。当发生中断时,内核会自动切换到MSP;当发生任务切换时,内核会自动切换到PSP。

堆栈的大小应根据应用程序和中断处理的需求进行合理配置。可以通过修改链接脚本或在启动文件中设置堆栈大小。

使用特权

评论回复
18
olivem55arlowe| | 2023-8-4 15:08 | 只看该作者
stm32静态局部变量存储在什么

使用特权

评论回复
19
nomomy| | 2023-8-4 15:33 | 只看该作者
堆栈的工作方式类似于数据结构中的栈。

使用特权

评论回复
20
qiufengsd| | 2023-8-4 16:34 | 只看该作者
内存分配、堆栈和变量存储位置是非常重要的概念。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

55

主题

396

帖子

0

粉丝