RAM(Random Access Memory) :掉电之后就丢失数据,读写速度块
ROM (Read Only Memory) :掉电之后仍然可以保持数据
单片机的RAM和ROM
单片机的ROM,叫只读程序存储器,是FLASH存储器构成的,如U盘就是FLASH存储器。所以,FLASH和ROM是同义的。单片机的程序,就是写到FLASH中了。而RAM是随机读/写存储器,用作数据存储器,是在运行程序时,存放数据的。
一篇带你了解C语言内存五大区——栈区,堆区,全局区,常量区,代码区
干货——聊聊内存那些事(基于单片机系统)
内存主要分为:代码区、常量区、静态区(全局区)、堆区、栈区这几个区域。
代码区:存放程序的代码,即CPU执行的机器指令,并且是只读的。
常量区:存放常量(程序在运行的期间不能够被改变的量,例如: 25,字符串常量”dongxiaodong”, 数组的名字等)
静态区(全局区):静态变量和全局变量的存储区域是一起的,一旦静态区的内存被分配, 静态区的内存直到程序全部结束之后才会被释放
堆区:由程序员调用malloc()函数来主动申请的,需使用free()函数来释放内存,若申请了堆区内存,之后忘记释放内存,很容易造成内存泄漏
栈区:存放函数内的局部变量,形参和函数返回值。栈区之中的数据的作用范围过了之后,系统就会回收自动管理栈区的内存(分配内存 , 回收内存),不需要开发人员来手动管理。栈区就像是一家客栈,里面有很多房间,客人来了之后自动分配房间,房间里的客人可以变动,是一种动态的数据变动。
#include "main.h"
#include //用于字符串处理
#include //用于printf打印
#include //用于分配堆区---调用malloc和free
#include "delay.h"
#include "uart3.h"
#include "led.h"
//全局区
int q1; //未初始化全局变量
static int q2; //未初始化静态变量
const int q3; //未初始化只读变量
int m1=1; //已初始化全局变量
static int m2=2; //已初始化静态变量
//常量区
const int m3=3; //已初始化只读变量
int main(void)
{
SystemCoreClockUpdate(); //设置系统时钟为72M
LED_GPIO_Config();
Uart3_init();
while(1)
{
//栈区
int mq1; //未初始化局部变量
int *mq2; //未初始化局部指针变量
int mq3=3; //已初始化局部变量
char qq[10] = "hello"; //已初始化局部数组
const int mq4; //未初始化局部只读变量
const int mq5=3; //已初始化局部只读变量
//堆区
int *p1 = malloc(4); //已初始化局部指针变量p1
int *p2 = malloc(4); //已初始化局部指针变量p2
//全局区
static int mp1; //未初始化局部静态变量
static int mp2=2; //已初始化局部静态变量
//常量区
char *vv = "I LOVE YOU";//已初始化局部指针变量
char *mq = "5201314";
printf("\n栈区-变量地址\n");
printf("未初始化局部变量 :0x%p\r\n",&mq1);
printf("未初始化局部指针变量 :0x%p\r\n",&mq2);
printf("已初始化局部变量 :0x%p\r\n",&mq3);
printf("已初始化局部数组 :0x%p\r\n", qq );
printf("未初始化局部只读变量 :0x%p\r\n",&mq4);
printf("已初始化局部只读变量 :0x%p\r\n",&mq5);
printf("\n堆区-动态申请地址\r\n");
printf("已初始化局部int型指针变量p1 :0x%p\r\n", p1);
printf("已初始化局部int型指针变量p2 :0x%p\r\n", p2);
printf("\n全局区-变量地址\n");
printf("未初始化全局变量 :0x%p\r\n",&q1);
printf("未初始化静态变量 :0x%p\r\n",&q2);
printf("未初始化只读变量 :0x%p\r\n",&q3);
printf("已初始化全局变量 :0x%p\r\n",&m1);
printf("已初始化静态变量 :0x%p\r\n",&m2);
printf("未初始化局部静态变量 :0x%p\r\n",&mp1);
printf("已初始化局部静态变量 :0x%p\r\n",&mp2);
printf("\n常量区地址\n");
printf("已初始化只读变量 :0x%p\r\n",&m3);
printf("已初始化局部指针变量 :0x%p\r\n",vv );
printf("已初始化局部指针变量 :0x%p\r\n",mq );
printf("\n代码区地址\n");
printf("程序代码区main函数入口地址 :0x%p\n", main);
led485_flicker();
delay_ms(1000);
free(p1);
free(p2);
}
}
32位的M3有4GB的寻址空间,2^32(字节) = 4G(字节),STM32的存储器地址映射,地址范围为:0x0000_0000-0xFFFF_FFFF;其中代码区的地址是从0x0800_0000开始的,结束于0x0800_0000+芯片的Flash的大小;
STM32寄存器版的基础知识—内存映射
1、编译器编译文件分析
那么RAM是什么呢,RAM就是运行内存,掉电数据就丢失;(通常保存着堆、栈、bss段、data段、ZI-data、RW-data)
在map文件可以查看到RAM大小
RAM = RW-data + ZI-data
text:代码段,存储在FLASH中
data:初始化数据 数据段
bss:未初始化数据 数据段
可以发现RW-data 出现在了 RAM和FLASH(ROM)中,RW-data为什么会即占用Flash又占用RAM空间?
由前文知道RAM掉电数据会丢失,RW-data是非0初始化的数据,已初始化的数据需要被存储在掉电不会丢失的FLASH中,上电后会从FLASH搬移到RAM中
CPU:STM32F103C8T6,LQFP64,FLASH:64KB,RAM:20KB
flash起始地址为0x8000000,大小为0x10000(16进制)—>65536字节(10进制)—>64KB
RAM起始地址为0x2000000,大小为0x5000(16进制)—>20480字节(10进制)—>20KB
ROM(FLASH)的起始地址是0x8000000 512k的flash大小=512*1024=0x80000字节
RAM的起始地址为0x20000000 大小为 64*1024=0x10000字节