MCU内存基础知识

文章目录

  • 一、存储器分类
  • 二、C语言内存分区内存区
  • 三、STM32启动文件分析
  • 四、应用分析

一、存储器分类

MCU内存基础知识_第1张图片
RAM(Random Access Memory) :掉电之后就丢失数据,读写速度块
ROM (Read Only Memory) :掉电之后仍然可以保持数据

单片机的RAM和ROM

单片机的ROM,叫只读程序存储器,是FLASH存储器构成的,如U盘就是FLASH存储器。所以,FLASH和ROM是同义的。单片机的程序,就是写到FLASH中了。而RAM是随机读/写存储器,用作数据存储器,是在运行程序时,存放数据的。

二、C语言内存分区内存区

C语言:内存分配—栈区、堆区、全局区、常量区和代码区

一篇带你了解C语言内存五大区——栈区,堆区,全局区,常量区,代码区

干货——聊聊内存那些事(基于单片机系统)
内存主要分为:代码区、常量区、静态区(全局区)、堆区、栈区这几个区域。
MCU内存基础知识_第2张图片

代码区:存放程序的代码,即CPU执行的机器指令,并且是只读的。

常量区:存放常量(程序在运行的期间不能够被改变的量,例如: 25,字符串常量”dongxiaodong”, 数组的名字等)

静态区(全局区):静态变量和全局变量的存储区域是一起的,一旦静态区的内存被分配, 静态区的内存直到程序全部结束之后才会被释放

堆区:由程序员调用malloc()函数来主动申请的,需使用free()函数来释放内存,若申请了堆区内存,之后忘记释放内存,很容易造成内存泄漏

栈区:存放函数内的局部变量,形参和函数返回值。栈区之中的数据的作用范围过了之后,系统就会回收自动管理栈区的内存(分配内存 , 回收内存),不需要开发人员来手动管理。栈区就像是一家客栈,里面有很多房间,客人来了之后自动分配房间,房间里的客人可以变动,是一种动态的数据变动。MCU内存基础知识_第3张图片

  1. 详细代码如下
#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);        
	}
}

三、STM32启动文件分析

  • STM32启动流程分析

32位的M3有4GB的寻址空间,2^32(字节) = 4G(字节),STM32的存储器地址映射,地址范围为:0x0000_0000-0xFFFF_FFFF;其中代码区的地址是从0x0800_0000开始的,结束于0x0800_0000+芯片的Flash的大小;
STM32寄存器版的基础知识—内存映射

STM32单片机启动流程分析

四、应用分析

  • STM32flash就是ROM

1、编译器编译文件分析
MCU内存基础知识_第4张图片
MCU内存基础知识_第5张图片
那么RAM是什么呢,RAM就是运行内存,掉电数据就丢失;(通常保存着堆、栈、bss段、data段、ZI-data、RW-data)

在map文件可以查看到RAM大小
MCU内存基础知识_第6张图片

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字节

你可能感兴趣的:(MCU,单片机)