最近在一个问答社区回答了一个问题,关于单片机存储器的,于是有了想专门写一篇关于单片机存储器的想法。作为单片机内部一个重要组成部分,存储器占有很重要的地位,今天就来聊聊我对于单片机的内部存储器RAM和FLASH的一些认识和理解。

1、先聊聊存储器

存储器是单片机结构的重要组成部分,存储器是用来存储编译好的程序代码和数据的,有了存储器单片机系统才具有记忆功能。按照存储介质的特性,可以分“易失性存储器”和“非易失性存储器”两类。易失性存储器断电后,里面存储的内容会丢失;非易失性存储器断电后,数据可以依然保持。
9123bfb73390453299e66ac0fd815a1b~noop.image?_iz=58558&from=article.jpg
存储器分类

2、单片机的存储器

如下图所示是STM32F103RB系列单片机所使用的存储器大小,Flash为128KB,RAM为20KB,这里的RAM是指SRAM。
95764bba01bf4336b85ebb2235f8033a~noop.image?_iz=58558&from=article.jpg
STM32F103RB内存大小

这两个存储器的寄存器输入输出端口被组织在同一个4GB的虚拟线性地址空间内。可访问的存储器空间被分成8个主要块,每个块为512MB。Flash用来存储编译好的程序文件,SRAM用来存储运行程序时所创建的临时数据。所以如果不加入外置存储器,那么程序里的东西就会出现在这两个存储器中。
下图为STM32F103RB单片机的内存映射图(部分),可以看到画红圈的两个就是SRAM和Flash存储器。不知道大家有没有注意,当使用J-Flash软件给stm32下载bin文件的时候需要填写起始地址,那个0x08000000其实就是Flash存储器的起始地址。
a6b6738662734a4290a25a011420f10c~noop.image?_iz=58558&from=article.jpg
STM32F103内存映射图

3、关于编译器生成的文件

如果你玩过单片机,那你应该对Keil这款软件不会感到陌生,下图是我的那款OLED时钟的软件用Keil编译后的编译信息。
a9d2030a88ec4cc7ae0e573800c857eb~noop.image?_iz=58558&from=article.jpg
KEIL编译信息

很多人并不一定知道Program Size的含义,我来给大家解释一下。
Code:是程序中代码所占字节大小;
RO-data:程序只读的变量,也就是带const的,和已初始化的字符串等;
RW-data:已初始化的可读写全局/静态变量;
ZI-data:未初始化的可读写全局/静态变量;
那么这个程序占用的Flash存储器的空间大小是多少呢?程序所占Flash空间大小=Code+RO data+RW data=生成的bin文件大小
那么这个程序占用的SRAM存储器的空间大小是多少呢?程序固定占用RAM大小=RW data+ZI data
这些信息除了在编译器下方的信息栏里面看到,也可以在项目文件里的.map文件的最下面找到,如下图:
e36adc91f2dd4b498babd36788d27ffc~noop.image?_iz=58558&from=article.jpg
.map文件信息

4、数据在存储器上的存储结构

程序在Flash上的存储结构如下图所示,通过阅读hex文件和MDK下调试综合提炼出来的。其中,ZI-data对应未初始化数据段,RW-data对应已初始化数据段,Code对应代码段。
89fd27e725aa43bfa41f05d3d9c37fc7~noop.image?_iz=58558&from=article.jpg
STM32的Flash存储结构

数据在SRAM上的结构,如下图所示。这部分大家可以参考上面的内存映射图来理解。
943c29319f004b80ae8ad1bedff7743d~noop.image?_iz=58558&from=article.jpg
STM32的SRAM存储结构

5、总结

至此我相信大家应该对stm32单片机的内部存储有了更进一步的认识。其实如果想更深入的了解单片机的运行轨迹,我建议大家来详细研究一下stm32单片机的上电内存读取过程,如果搞明白了这块收获会是非常大的。

来源:HACK实验室