之前一直没认真关注过这个,随心所欲地瞎比写,然后终于flash被写满了,于是才来研究下。
keil在每次编译后都会打印各个区域的大小情况,例如下图。
image.png
并且会在那堆编译文件中生产一个.map的文件,里面详细列举了各个地址使用情况,翻到最后便能看到你实际flash的需求情况了。例如下图程序,实际使用的flash是123.96KB
image.png
然后简单说明一下各个区域代表的意思
- Code表示的就是你的代码,其中不包含变量定义相关,而是逻辑部分。
- RO-data是只读数据段,存放常量。那什么是常量呢,例如定义了int a=123,这123就是常量,需要被保存起来。宏定义不是常量,它是在编译前进行替换的。
- RW-data读写数据段,用于存放已被初始化且初始化不为0的全局变量。还是上面的例程int a=123,他存放的便是int a。
- ZI-data 0数据段,用于存放为被初始化或者初始化为0的全局变量。例如int a,那么a会被保存到ZI-data而不是RW-data。
实际上我们存入flash中的数据包含的是 Code + RO-data + RW-data,是不包含ZI-data的。
当程序运行时RW-data将从flash被搬运到内存中,然后再划分出ZI-data段并将其全部置零。
这里借用一种RT-THREAD文档的图片
image.png
以上为理论,我们再实际用代码测试一下
首先顺便打开一个工程,进行编译,得出区域使用情况
Program Size: Code=112806 RO-data=13838 RW-data=1324 ZI-data=10396
然后我们定义一个全局变量,并且为了防止被优化,调用打印来使用它
char *data = "123456789";
void pt_data()
{
rt_kprintf("%s",data);
}
//主函数中调用pt_data()
再次编译得到新的区域使用情况
Program Size: Code=112834 RO-data=13850 RW-data=1328 ZI-data=10392
接下里我们就对比一下,其中RO-data多了12个字节,来源于定义的字符串常亮"123456789",每个字符占8个字节,算上\0一共是10个字节,但是由于我们是32位单片机,只能是4字节的整数倍,所以这里使用了12个字节。
再来是RW-data多了4个字节,原因是我们定义的char *data指针,同样因为是32位单片机,所以使用了4个字节。
至于ZI-data少了4个字节,emmm这个我一脸懵逼,望大佬指教。
接下来我们尝试定义一个未初始化的全局变量
uint32_t a[100];
void pt_data()
{
rt_kprintf("%d",a[0]);
}
//在主函数中调用pt_data
然后得到新的区域使用情况
Program Size: Code=112834 RO-data=13838 RW-data=1324 ZI-data=10796
我们能够发现,RO-data和RW-data均未改变,而ZI-data增加了400,正好就是数组a。
网友评论