41.3. 查看工程的空间分布¶
由于内部FLASH本身存储有程序数据,若不是有意删除某段程序代码,一般不应修改程序空间的内容,所以在使用
内部FLASH存储其它数据前需要了解哪一些空间已经写入了程序代码,存储了程序代码的扇区都不应作任何修改。
通过查询应用程序编译时产生的“*.map”后缀文件,可以了解程序存储到了哪些区域,它在工程中的打开方式见
图44_2,也可以到工程目录中的“Listing”文件夹中找到,关于map文件的详细说明可参考前面的《MDK的编译过程及文件详解》章节。
图 44‑2 打开工程的.map文件
打开map文件后,查看文件最后部分的区域,可以看到一段以“Memory Map of the
image”开头的记录(若找不到可用查找功能定位),见 代码清单44_1。
代码清单 44‑1 map文件中的存储映像分布说明¶
=========================================================
Memory Map of the image //存储分布映像
Image Entry point : 0x08000131
/*程序ROM加载空间*/
Load Region LR_IROM1 (Base: 0x08000000, Size: 0x000017a8, Max: 0x00080000, ABSOLUTE)
/*程序ROM执行空间*/
Execution Region ER_IROM1 (Base: 0x08000000, Size: 0x0000177c, Max: 0x00080000, ABSOLUTE)
/*地址分布列表*/
Base Addr Size Type Attr Idx E Section Name Object
0x08000000 0x00000130 Data RO 3 RESET startup_stm32f10x_hd.o
0x08000130 0x00000000 Code RO 479 * .ARM.Collect$$$$00000000 mc_w.l(entry.o)
0x08000130 0x00000004 Code RO 742 .ARM.Collect$$$$00000001 mc_w.l(entry2.o)
0x08000134 0x00000004 Code RO 745 .ARM.Collect$$$$00000004 mc_w.l(entry5.o)
/*...此处省略大部分内容*/
0x080016e8 0x00000024 Code RO 772 .text mc_w.l(init.o)
0x0800170c 0x00000010 Code RO 483 i.__0printf$bare mc_w.l(printfb.o)
0x0800171c 0x0000000e Code RO 784 i.__scatterload_copy mc_w.l(handlers.o)
0x0800172a 0x00000002 Code RO 785 i.__scatterload_null mc_w.l(handlers.o)
0x0800172c 0x0000000e Code RO 786 i.__scatterload_zeroinit mc_w.l(handlers.o)
0x0800173a 0x00000022 Code RO 490 i._printf_core mc_w.l(printfb.o)
0x0800175c 0x00000020 Data RO 782 Region$$Table anon$$obj.o
这一段是某工程的ROM存储器分布映像,在STM32芯片中,ROM区域的内容就是指存储到内部FLASH的代码。
41.3.1. 程序ROM的加载与执行空间¶
上述说明中有两段分别以“Load Region LR_ROM1”及“Execution Region
ER_IROM1”开头的内容,它们分别描述程序的加载及执行空间。在芯片刚上电运行时,会加载程序及数据,例如它会从程序的存储区域加载到程序的执行区域,还把一些已初始化的全局变量从ROM复制到RAM空间,以便程序运行时可以修改变量的内容。加载完成后,程序开始从执行区域开始执行。
在上面map文件的描述中,我们了解到加载及执行空间的基地址(Base)都是0x08000000,它正好是STM32内部FLASH的首地址,即STM32的程序存储空间就直接是执行空间;它们的大小(Size)分别为0x000017a8及0x0000177c,执行空间的ROM比较小的原因就是因为部分RW-data类型的变量被拷贝到RAM空间了;它们的最大空间(Max)均为0x00080000,即512K字节,它指的是内部FLASH的最大空间。
计算程序占用的空间时,需要使用加载区域的大小进行计算,本例子中应用程序使用的内部FLASH是从0x08000000至(0x08000000+0x000017a8)地址的空间区域。
41.3.2. ROM空间分布表¶
在加载及执行空间总体描述之后,紧接着一个ROM详细地址分布表,它列出了工程中的各个段(如函数、常量数据)所在的地址Base
Addr及占用的空间Size,列表中的Type说明了该段的类型,CODE表示代码,DATA表示数据,而PAD表示段之间的填充区域,它是无效的内容,PAD区域往往是为了解决地址对齐的问题。
观察表中的最后一项,它的基地址是0x0800175c,大小为0x00000020,可知它占用的最高的地址空间为0x0800177c,跟执行区域的最高地址0x0000177c一样,但它们比加载区域说明中的最高地址0x80017a8要小,所以我们以加载区域的大小为准。对比表
44‑1的内部FLASH页地址分布表,可知仅使用页0至页2就可以完全存储本应用程序,所以从页3(地址0x08001800)后的存储空间都可以作其它用途,使用这些存储空间时不会篡改应用程序空间的数据。