官方资料:
依次打开 -> keil -> help -> uVision help,打开帮助文件,然后定位到分散加载文件章节:
分散加载文件有什么用?
我们知道,在嵌入式程序中,main函数并不是首先被执行的代码,还有一个隐藏的函数,名字叫__main,他会在main之前被执行,还有一些汇编代码也会在main之前被执行。他们主要干了这些事情:1、设置栈顶地址;2、设置PC指针;3、把0初始化变量所在内存区清0;4、给非0初始化的变量赋值;5、设置栈顶地址。
load view中就是编译完的整个固件的内容(其内容的排布方式就是按照图7-6中load region所定义的方式,称为加载域),非0初始化的变量的初值,就存在于上图所示的Load View的RW section区域,__main中会有一段代码,把这些值一一复制到内存的RW section区域,这样非0初始化变量的初始化就完成了,进入main函数时,这些变量就已经被正确赋好值了。
而Execution View就是执行域,其内容的排布方式就是按照图7-6中exec region所定义的方式。
所谓load region,译为加载域、装载域,它描述了程序在存储时排布样式,对于STM32单片机来说,他描述的就是固件在flash中的样子。假如你的单片机有2个flash,如果你想让a.c里的函数下载到flash1里面,让b.c里面的函数下载到flash2里面,就可以通过加载域功能来实现。
execute region,译为运行域,它描述了运行时的排布样式。他描述的是程序运行起来以后,各个变量和程序在RAM和ROM中的样子。
为什么要区分这两种状态?试想,我们下载到单片机的程序,下次上电重启后,要能运行,那么这段程序必须要放到ROM中,而有时候为了程序的运行速度,我们会故意设置(通过分散加载文件)把某些函数放到RAM执行,而RAM是会掉电遗失的,如何才能实现让每次重上电后让某些函数运行在RAM中?当然是在main函数运行之前,就把这些函数复制到RAM中。
由图7-7看起来,其实对于一个简单的固件,装载域和运行域的样子基本是一样的,尤其是RO代码段,直接保持不变,也不需要复制到别处,就地运行就行了。唯一要复制的,就是非0初始化的变量值,需要从加载域复制到内存。
常见语法:
ARM映像文件的组成:
一个映像文件由一个或多个域(region,也有译为“区”)组成
每个域包含一个或多个输出段(section,也有译为“节”)
每个输出段包含一个或多个输入段
各个输入段包含了目标文件中的代码和数据。
以上文字看完之后还是不明所以,主要是这里出现了几个名词:域、输入段、输出段。
输入段中包含了四类内容:代码、已经初始化的数据、未经过初始化的存储区域、内容初始化为零的存储区域。每个输入段有相应的属性:只读的(RO)、可读写的(RW)以及初始化成零的(ZI)。
一个输出段中包含了一些列具有相同的RO、RW和ZI属性的输入段。输出段属性与其中包含的输入段属性相同。
一个域包含一到三个(显然是RO RW ZI三个中的部分或全部)输出段,各个输出段的属性各不相同:RO属性、RW属性和ZI属性
到这里我们就可以知道,一般情况下,代码会被放到RO属性的输入段,已经初始化的变量会被分配到RW属性输入段,而“ZI”属性输入节可以理解为是初始化成零变量的集合。
输入段、输出段的官方介绍如下:
简单翻译一下:
输入段:目标文件中
更多【输入段】有关的知识,可直接参阅帮助文件,如下:
上图是keil为STM32自动生成的一个sct文件,在keil中我们勾选了使用2块RAM区域(详情自行学习F4 CCM内存),所以这个分散加载文件里面就有2个RAM相关的运行域。看了这个文件以后,更容易理解为什么执行域要被加载域给包住了,ER_IROM1中的内容显然是要全部进入加载域的,RW_IRAMx的内容中的RW部分,在flash和RAM中各有一份,这样LR_IROM的内容就确定下来了:代码、RO数据、RW的初始化数据。
1、这个分散加载文件共有1个加载域LR_IROM1,3个运行域:ER_IROM1、RW_IRAM1、RW_IRAM2。第一个运行时域,起始地址0x08008000,大小0x00080000;第一个执行域必须和加载域地址重合,因为ARM的复位地址就是加载域的起始地。
2、 *.o (RESET, +First)
将编译后生成的文件.o中找到含有“RESET”段的内容放到“ER_IROM1"这块存储区域内;用First指定该输入段处于该执行域的开头。
3、.ANY (+RO)代表把任意目标文件(也即.o文件)中的代码段(RO)编译进本加载域。
.ANY (+RW +ZI)代表可以把任意文件中的数据段(RW和ZI)编译进本执行域。
usart.o (+ZI)代表把usart.o文件中ZI数据段变量编译进本执行域。
Region$$Table$$Base
Region$$Table$$Limit
KEIL的分散加载文件_aron566的博客-CSDN博客_分散加载文件
对于.ANY的确切用法,可自行搜索:使用.ANY模块选择器放置未分配的段