“静心理解一下程序存储到了哪些区域,就能知道哪些区域可以进行写入。”
目录
以STM32F103ZET6为例,首先我们先来了解一下内部FLASH
内部 FLASH 的构成
STM32 的内部 FLASH 包含主存储器、系统存储器以及选项字节区域。
主存储
一般我们说 STM32 内部 FLASH 的时候,都是指这个主存储器区域,它是存储用户应用程序的空间,芯片型号说明中的 256K FLASH、512K FLASH 都是指这个区域的大小。
主存储器分为 256 页,每页大小为 2KB,共 512KB。这个分页的概念,实质就是 FLASH 存储器的扇区,与其它 FLASH 一样,在写入数据前,要先按页(扇区)擦除。
系统存储区
系统存储区是用户不能访问的区域,它在芯片出厂时已经固化了启动代码,它负责实现串口、USB以及 CAN 等 ISP 烧录功能。
选项字节
选项字节用于配置 FLASH 的读写保护、待机/停机复位、软件/硬件看门狗等功能,这部分共 16字节。可以通过修改 FLASH 的选项控制寄存器修改。
程序存储到了哪些区域?
由于内部 FLASH 本身存储有程序数据,若不是有意删除某段程序代码,一般不应修改程序空间的内容,所以在使用内部 FLASH 存储其它数据前需要了解哪一些空间已经写入了程序代码,存储了程序代码的扇区都不应作任何修改。通过查询应用程序编译时产生的“*.map”后缀文件,可以了解程序存储到了哪些区域
打开 map 文件后,查看文件最后部分的区域,可以看到一段以“Memory Map of the image”开头的记录 (若找不到可用查找功能定位)
上述说明中有两段分别以“Load Region LR_ROM1”及“Execution Region ER_IROM1”开头的内容,它们分别描述程序的加载及执行空间。在芯片刚上电运行时,会加载程序及数据,例如它会从程序的存储区域加载到程序的执行区域,还把一些已初始化的全局变量从 ROM 复制到 RAM空间,以便程序运行时可以修改变量的内容。加载完成后,程序开始从执行区域开始执行。在上面 map 文件的描述中,我们了解到加载及执行空间的基地址 (Base) 都是 0x08000000,它正好是 STM32 内部 FLASH 的首地址,即 STM32 的程序存储空间就直接是执行空间;它们的大小(Size) 分别为 0x0000190c 及 0x000018c8,执行空间的 ROM 比较小的原因就是因为部分 RW-data类型的变量被拷贝到 RAM 空间了;
在keil中查看内部FLASH中的值进行上述验证,如下图所示
总结:在计算程序占用的空间时,需要使用加载区域的大小进行计算,本例子中应用程序使用的内部FLASH 是从 0x08000000 至 (0x08000000+0x0000190c) 地址的空间区域。所以在此空间区域内是不允许再次写入数据的,在次写入数据就会产生硬件错误中断。
ROM 空间分布表分析
在加载及执行空间总体描述之后,紧接着一个 ROM 详细地址分布表,它列出了工程中的各个段(如函数、常量数据) 所在的地址 BaseAddr 及占用的空间 Size,列表中的 Type 说明了该段的类型,CODE 表示代码,DATA 表示数据,而 PAD 表示段之间的填充区域,它是无效的内容,PAD 区域往往是为了解决地址对齐的问题。
观察表中的最后一项,它的基地址是 0x080018a8,大小为 0x00000020,可知它占用的最高的地址空间为 0x080018c8,跟执行区域的最高地址 0x000018c8 一样,但它们比加载区域说明中的最高地址 0x800190c 要小,所以我们以加载区域的大小为准。对比表 STM32 大容量产品内部 FLASH的构成 的内部 FLASH 页地址分布表,可知(地址 0x800190c ) 后的存储空间都可以作其它用途,使用这些存储空间时不会篡改应用程序空间的数据