一、前言
在之前的学习过程中,对stm32内存分布经常会产生一个疑问,在keil编译出来的程序,最后面会统计出各个部分所占用大小,比如下面这个
可以知道程序中的Code(代码段)、RO-data(只读数据段)、RW-data(可读可写数据段)和ZI-data(未初始化或初始化为0的全局变量和静态变量)分别占用的字节数,把RW段和ZI段的字节大小相加为67488byte(转为十六进制为:0x107a0)。
![](https://i-blog.csdnimg.cn/direct/5a9616353656405d9a3425fa7485d63e.png)
![](https://i-blog.csdnimg.cn/direct/0f0b643260074c85ac01f55125d80c33.png)
从图中可以发现程序中用到的SRAM大小等于RW段加ZI段的大小,也与__initial_sp栈顶的地址偏移量相等。那么这时就会有个问题,RW加ZI的区域和栈的区域不是重叠了吗?要回答这个问题,我们要先理解两个概念——程序文件、运行中的程序。
二、程序文件
程序文件:程序编译后生成的可执行文件,如:bin文件和hex文件等。
在程序文件中,分区情况有下面这些:
1. Code段
也是RO-Code段,包含程序运行的代码(机器码),一直存储在FLASH上。
2. RO-data (read only)
只读数据段,一般为const关键字修饰的全局变量,开始存储在flash,程序运行时会移到RAM。
3. RW-data (read write)
可读可写数据段,包括初始化不为0的全局变量、static关键字修饰的全局变量和局部变量,在FLASH和RAM中都占用了空间。
4. ZI-data (zero init)
初始化为0的数据段,包括初始化为0或未初始化的全局变量和static修饰的全局变量和局部变量,一直存储在RAM,编译器给出的ZI-data空间实际还包含了堆栈空间(可从前言中的分析看出)。
5. RO
只读段,包括只读代码段(Code段)和只读数据段(RO-data)。
从map文件的最后可以看出前面几个区域的大小关系以及在存储器的分布,RAM的大小等于RW-data段加ZI-data段大小,FLASH的大小等于Code段加RO-data段加RW-data段大小,这时程序中并没有分配堆栈的空间。
程序文件中的内存分布图如下(图中所示每个区域大小因程序而异)
三、运行中的程序
运行中的程序:MCU上电后开始运行的过程。
MCU上电后开始运行,会初始化堆栈,将RW-data段数据从FLASH移到RAM(类似于memcpy(ram_rw,flash_rw,size)),将RAM中ZI-data段数据清零(类似于memset(zi,0,sizeof(zi))),这些过程是在__main函数中实现的,具体可以参考stm32的启动文件。
程序开始运行后的分区情况主要有:
1. 代码段(code/txt)
存放程序执行代码的内存区域,这块区域在程序运行前就确定了,绝大多数情况在FLASH中,但也可以把code放在RAM中运行。
2. 静态存储区(.bss段+.data段)
静态存储区是.bss段和.data段的统称,其中ZI-data段数据会被加载到.bss段,而RW-data会被加载到.data段。
3. 栈区(stack)
4. 堆区(heap)
![](https://i-blog.csdnimg.cn/direct/9da5c801f0a34a47ab80fd8f8285cf21.png)
四、结语
如有错误,欢迎大家指正!