文章目录
- 一、存储器分类
- 二、C语言内存分区内存区
- 三、STM32启动文件分析
- 四、应用分析
一、存储器分类
RAM(Random Access Memory) :掉电之后就丢失数据,读写速度块
ROM (Read Only Memory) :掉电之后仍然可以保持数据
单片机的RAM和ROM
单片机的ROM,叫只读程序存储器,是FLASH存储器构成的,如U盘就是FLASH存储器。所以,FLASH和ROM是同义的。单片机的程序,就是写到FLASH中了。而RAM是随机读/写存储器,用作数据存储器,是在运行程序时,存放数据的。
二、C语言内存分区内存区
C语言:内存分配—栈区、堆区、全局区、常量区和代码区
一篇带你了解C语言内存五大区——栈区,堆区,全局区,常量区,代码区
干货——聊聊内存那些事(基于单片机系统)
内存主要分为:代码区、常量区、静态区(全局区)、堆区、栈区这几个区域。
代码区:存放程序的代码,即CPU执行的机器指令,并且是只读的。
常量区:存放常量(程序在运行的期间不能够被改变的量,例如: 25,字符串常量”dongxiaodong”, 数组的名字等)
静态区(全局区):静态变量和全局变量的存储区域是一起的,一旦静态区的内存被分配, 静态区的内存直到程序全部结束之后才会被释放
堆区:由程序员调用malloc()函数来主动申请的,需使用free()函数来释放内存,若申请了堆区内存,之后忘记释放内存,很容易造成内存泄漏
栈区:存放函数内的局部变量,形参和函数返回值。栈区之中的数据的作用范围过了之后,系统就会回收自动管理栈区的内存(分配内存 , 回收内存),不需要开发人员来手动管理。栈区就像是一家客栈,里面有很多房间,客人来了之后自动分配房间,房间里的客人可以变动,是一种动态的数据变动。
- 详细代码如下
#include "main.h"
#include <string.h> //用于字符串处理
#include <stdio.h> //用于printf打印
#include <stdlib.h> //用于分配堆区---调用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(); //设置系统时钟为72MLED_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); //已初始化局部指针变量p1int *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、编译器编译文件分析
那么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字节