- 由于本人是先学的C/C++内存管理,所以也是基于这个理解的嵌入式内存管理
文章目录
1. 基础认知
- STM32F7 Cortex-M7内核使用32位地址总线,虚拟映射了4G的可访问内存 (0xFFFF FFFF = 2^32 ≈ 4GB)
- 单片机与电脑/linux嵌入式 在代码运行的空间上不同。大多数单片机,代码都是在Flash中运行的。而电脑/linux嵌入式,是将代码从存储介质(可能是硬盘/SD卡/EMMC/NAND)中读出,拷贝到RAM,再在RAM中去执行代码。需要一定的Flash与RAM的基础认识
- 嵌入式系统中,比较常见的Contex-M的虚拟内存划分如下:
- 可以看到FLASH对应的区域为 0x0800 0000 开始的
- RAM对应的区域是从 0x2000 0000 开始
2. Keil MDK中的内存划分
2.1 内存使用的查看
- 工程编译后,一般在Debug目录下会生成%Project_name%.map文件,打开 *.map文件,包含了各个函数和文件占用的空间大小和地址。
- *.map 末尾出现以下内容
- 简单的说就是在烧写的时候是FLASH中的被占用的空间为:Code + RO Data + RW Data
上图示例工程中FLASH的占用大小为 54.66 KB - 程序运行的时候,芯片内部RAM使用的空间为: RW Data + ZI Data
上图示例工程中ARM的占用大小为 6.11 KB
2.2 内存划分
-
内存的划分如下表
缩写 作用 Code 储存程序代码 RO Data 存储Const常量和指令 RW Data 储存初始化值不为0的全局变量 ZI Data 储存未初始化的全局变量和初始化值为0的全局变量 -
Flash存储:Code + RO Data + RW Data ;
-
RAM存储:RW Data + ZI Data ; RAM还有堆栈区域,储存动态分配内存和局部变量,初始化值为0的全局变量
问答
为什么 FLASH 和 RAM 都存在RW-Data?
- 可以看到 2.2章节 内存划分,RW-Data 对应到ARM中的date段,初始化值非0的全局变量,由于ARM掉电丢数据,所以有值的数据需要拷贝到FLASH中,FLASH中的Copy of Data Section便是拷贝的data段,在上电后会从FLASH中将初始化值不为0的全局变量再拷贝到ARM中,所以RW-Data既存在于FLASH又存在于RAM中
- 那为什么不直接将全局变量放在FLASH中呢?
- 这是由于FLASH的性能决定的,片内的可执行程序的FLASH为NOR FLASH,NOR FLASH的写性能很差,需要先擦除再写,作为一个全局变量,读写是频繁的,显然这是不允许的
- 总结:
- RW-Data掉电需要保存,所以必须要存储在FLASH 中
- RW-Data需要频繁读写,所以读写速度要快,所以必须在RAM中使用
为什么有的程序可以在FLASH中运行,有的却必须要在RAM中运行呢?
- 这是由于选择不同FLASH决定的
- NOR FLASH,可以直接寻址一个字节,可以找到一个指令的具体地址,因此可以直接运行。
- NAND FLASH 的存储单元是块,不能对指令直接寻址,因此不能直接运行其中的代码。只能将NAND FLASH中的代码拷贝到ARM中才能运行。
- 对于NAND FLASH中的代码大小大于 RAM的大小的情况,可以分时分段使用,运行起来也是没有问题的。
为什么烧录程序地址有时是0X0800 0000 有时是 0x2000 0000
- 程序文件一般都需要烧录到芯片的Flash存储器中。Flash存储器通常分为两个区域,分别是主Flash区和备份Flash区。其中,0x08000000是主Flash区的起始地址,0x20000000是备份Flash区的起始地址。
- 0x0800 0000是内置FLASH的起始地址,0x2000 0000 是内置SRAM的起始地址,他们都可以作为程序的启动地址
为什么STM32的Flash地址是0x08000000,而不是0x00000000?
参考链接
STM32 内存分配解析及变量的存储位置
KEIL MDK 查看代码量、RAM使用情况–RO-data、RW-data、ZI-data的解释
嵌入式系统中,FLASH中的程序代码必须搬到RAM中运行吗?
RAM、ROM、Flash的分类、NOR FLASH和NAND FLASH性能比较