打印
[其他ST产品]

stm32内存分配解析及变量的存储

[复制链接]
220|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
内存映射
    在一些桌面程序中,整个内存映射是通过虚拟内存来进行管理的,使用一种称为内存管理单元(MMU)的硬件结构来将程序的内存映射到物理RAM中。在对于RAM紧缺的嵌入式系统中,是缺少MMU内存管理单元的。因此在一些嵌入式系统中,比如常用的STM32来讲,内存映射被划分为闪存段(也被称为Flash,用于存储代码和只读数据)和RAM段(用于存储写数据)。
    **STM32的Flash和RAM地址范围**
    !

使用特权

评论回复
沙发
等你下课|  楼主 | 2023-7-31 16:55 | 只看该作者

使用特权

评论回复
板凳
等你下课|  楼主 | 2023-7-31 16:55 | 只看该作者
从中我们可以看到RAM地址是从0x2000 0000开始的,Flas地址是从0x0800 0000开始的。

使用特权

评论回复
地板
等你下课|  楼主 | 2023-7-31 16:56 | 只看该作者
代码和数据是存放在Flash中的,下面是将flash内部进行细分后的一张图片,图中标明了代码段,数据段以及常量在flash中的位置。Flash又可以分为这么几个部分,分别是文本段(Text),其中文本段中又包括可执行代码
(Executable Code)和常量 (Literal Value),在文本段之后就是只读数据区域 (Read Only Data),当然并不是所有架构的单片机都满足这样一个排布规律,这里只针对ARM Cortex M3 系列,只读数据段后面接着的就是数据复制段 (Copy of Data Section),第一次遇到这个概念的朋友看到数据复制可能会有所疑惑,其实这个段充当的作用是存放程序中初始化为非 0 值的全局变量的初始值,之所以要将初始值存放到这里,是因为全局变量是存放在 RAM 上的,RAM 上的值掉电便丢失,每次上电后这些变量是要进行重新赋值的,而重新赋的值就存放在这里。那为什么不存放初始化为 0 的全局变量初始值呢,原因也很简单,既然是初始化为 0,那么在上电后统一对存放初始化为 0 的全局变量的那块区域清0就好了。下面举一个例子分析各个变量在上述中的存储位置:#include <stdio.h>

const int read_only_variable = 2000;

int data = 500;

void my_function(void)

{

int x = 200;

char *str = 'string';

}

使用特权

评论回复
5
等你下课|  楼主 | 2023-7-31 16:56 | 只看该作者
在上述代码中,read_only_variable 是一个用 const 修饰的全局变量,它是只读的,存放在 flash 中的只读数据区域,编译器会给 read_only_variable 分配一个地址,并将 2000 这个数据存放到这个位置。data 这个变量将存放到 RAM 中的RW区域中 (后面将会进行详细讲解),但是 data 后面的初始值 500 将会被存放到数据复制区域中, 也就是上图中从下往上的第三个区域。在 my_function 中的变量 x 将会被存放到 RAM 中的堆栈中,将 x 赋值为 200 ,200 将被存储到 flash 里的 Text 中的常量区 (Literal Valu) 中。str 是一个 char 型的指针变量,它指向的是字符串第一个字符存放的位置,然而对于字符串 string 来讲,它是存放在Text常量区的,所以指针变量指向这个区域的一个地址,但是因为它终归中局部变量,它指向 Flash 的一个地址,但是其本身还是存放于 RAM 中的堆栈上的。
RAM

使用特权

评论回复
6
等你下课|  楼主 | 2023-7-31 16:56 | 只看该作者
STM32单片机的片内RAM会被链接文件“分区”为如下几个段:

如上图所示,RAM中包含了如下几个部分:
栈 (Stack) : 存放局部变量和函数调用时的返回地址

堆 (heap) : 由 malloc 申请,由 free 释放

bss : 存放未初始化或者是初始化为 0 的全局变量

data : 存放初始化为非 0 值的全局变量

使用特权

评论回复
7
等你下课|  楼主 | 2023-7-31 16:57 | 只看该作者
下面举一个简单的例子来说明变量在各个段中的存储位置:
#include <stdio.h>

#include <stdlib.h>

int data_var = 500;

int bss_var0;

int bss_var1 = 0;

static int static_var;

void my_function(void)

{

    static int static_var1 = 0;

    int stack = 0;

    char *buffer;

    const int value = 1;

    buffer = malloc(10);

}


上述变量的命名已经很清楚地表明了变量处于 RAM 中的哪一个段,datavar 是已经初始化的全局变量,存放在 RAM 的 data 区,bssvar0 和 bssvar1是未初始化和初始化为0的全局变量,他们都存放于 RAM 中的 bss段,由 static 修饰的staticvar 和 static_var1 都存放于 bss段,区别只在于两个变量的作用域不同。stack 是在函数内部定义的局部变量,其存放于 RAM 的栈区域,用 const 修饰的局部变量 value ,虽然他是只读的,但是它是存储于 RAM 中的栈中的,这里也说明一点,并不是所有用 const 修饰的变量都是存放于只读变量区的。buffer指针变量用 malloc 函数申请了 10 字节的内存空间,那这10字节的内存空间位于堆中。

使用特权

评论回复
8
等你下课|  楼主 | 2023-7-31 16:58 | 只看该作者
堆栈溢出

在STM32的启动文件(startup_stm32fxxx.s)中,刚开头就有对堆和栈空间的定义描述。如图定义了栈的大小是(0x400),堆的大小是(0x200)。栈里面存放的是一些函数执行时的局部变量、中断入口等,函数执行结束时这些存储单元自动被释放。堆是程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在适当的时候用free或delete释放内存。

使用特权

评论回复
9
等你下课|  楼主 | 2023-7-31 16:59 | 只看该作者
再来看一下MAP文件,如下图:

使用特权

评论回复
10
等你下课|  楼主 | 2023-7-31 16:59 | 只看该作者
可以看到在整个ram空间(0x2000 0000起)依次存放了data、bss、HEAP、STACK,其中堆和栈的大小和我们定义的是一致的。
  在ram中值得关注的是堆和栈的空间,堆是向上增长的而栈是向下生长的,如果一个函数运行的时候有大量的局部变量(栈向下增长),同时程序在整个过程中malloc申请了大量的堆空间而没有释放(堆向上增长),造成堆和栈空间的冲突,一旦堆栈冲突,系统就崩溃了。
   如果在程序运行的过程中,堆的空间也一直在消耗,同时栈的空间也在增加,那么这时堆和栈如果碰到一起,那么就会造成堆栈溢出,从而导致我们的程序跑飞。

使用特权

评论回复
11
等你下课|  楼主 | 2023-7-31 16:59 | 只看该作者
问题:
1、stm32程序定义的各种参数都存在哪,比如我定义一个存放1000个数的数组,这些数都存在哪啊???
看你是怎么定义的了,如果加了const,那就保存在ROM中。如果申明了数组但没初始化,那就是放在RAM中的;如果初始化了,数组放在RAM中,但数组初始化的数据放在ROM中,有程序从ROM复制到RAM。

使用特权

评论回复
12
等你下课|  楼主 | 2023-7-31 16:59 | 只看该作者
2、stm32const数组占用什么空间?
stm32const数组占用结构体空间。根据查询相关资料显示stm32const数组文件默认定义的堆、栈大小为0乘200、0乘400时,占用结构体空间,当超出定义大小时会溢出到全局、静态变量空间。数组就是有序的元素序列,若将有限个类型相同的变量的集合命名,那么这个名称为数组名。

使用特权

评论回复
13
Clyde011| | 2023-12-29 07:32 | 只看该作者

首先是进行按比例和具体的施胶量进行混合操作

使用特权

评论回复
14
公羊子丹| | 2023-12-29 08:25 | 只看该作者

将在原边形成电压尖峰,

使用特权

评论回复
15
万图| | 2023-12-29 09:28 | 只看该作者

使该元器件不超过正常值范围

使用特权

评论回复
16
Uriah| | 2023-12-29 10:31 | 只看该作者

该电容可以存储高达8KV的电位

使用特权

评论回复
17
帛灿灿| | 2023-12-29 12:27 | 只看该作者

ESD静电保护器工作特性与TVS管一致。

使用特权

评论回复
18
Bblythe| | 2023-12-29 13:30 | 只看该作者

环氧树脂、聚胺脂、有机硅灌封胶

使用特权

评论回复
19
周半梅| | 2023-12-29 15:26 | 只看该作者

保护被保护IC或线路

使用特权

评论回复
20
Pulitzer| | 2023-12-29 16:29 | 只看该作者

电源模块的灌封用的胶是可以根据需求而调制的

使用特权

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

本版积分规则

26

主题

306

帖子

0

粉丝