我们先来做一个最简单的示例,然后逐步深入。
这里我们用STM32F103ZET6作为示例,我们先来看其默认的分散加载(位于Object目录下自动生成的.sct文件):
加载域地址从0x08000000地址开始,大小为0x80000(512KB),运行域(RO)从0x08000000开始,运行域(RW+ZI)从片内SRAM地址开始0x20000000。
有的同学可能会问,《Cortex-M3权威指南》里面不是说上电从0地址开始依次取两个值赋给SP和PC吗,为什么这里会从0x08000000开始呢?这是因为STM32F1有2个boot引脚,接不同的电平的时候会把不同的地址映射到0地址上,如下表:
我们尝试让程序从0x08001000地址上开始运行,先把加载域和执行域的地址改成0x08001000
由上面的STM32上电时地址映射机制可知,由于此时地址空间的0地址是映射到0x08000000的,我们虽然修改了分散加载文件把程序放到了0x08001000,但是上电时还是会从0x08000000处开始取SP和PC,所以应该是不能正常运行的,我们跑一下看看:
可以看到程序停在了0x08000250这个地址,显然这个地址并不属于我们的程序,但是这里为啥会存在正常的指令?因为我们在flash下载设置里面设置了Erase Sectors,如下图,这意味着在下载程序时只擦除需要擦除的区域,也就是说只会从0x08001000处开始擦除,而0x08000000~0x08000FFF区域保持不变,也就是我们上次所烧的程序。
注意:修改完参数之后需要重新编译一下才会生效。

现在我们把下载设置改为全部擦除,如下图
再跑一次看一下,这次停在了0xFFFFFFFE地址处
那么到底怎么才能让程序从0x08001000地址处开始运行?
其实在M0+/M3/M4内核里面有一个叫VTOR的寄存器(M0核里面我记得是没有),地址是0xE000ED08,这个寄存器用于设置异常&中断向量表默认地址,我们需要在程序运行起来之前设置VTOR寄存器,告诉MCU,地址变成0x00001000了,那怎么做呢?在这里,如下图:
这里有一个仿真器初始化文件,可以在程序下载之前写一些寄存器做一些初始化之类的工作,是一个扩展名为.ini的文件,也有其自己的语法,按照下图编写这个ini文件:
这里简单解释下这个ini文件的意思:FUNC的意思是定义一个函数,Setup()是对应的函数,内容大家都看得懂,直接给MSP以及PC赋值,然后写0xE000ED08(VTOR寄存器)地址,告知MCU地址启动地址改变了,最后一行代码的意思是调用Setup()函数。然后把写好的ini文件放到刚才的位置上,如下图:
我们重新编译然后再次运行一次程序,如下,我们的程序完美运行:
上面Debug之后光标默认是在反汇编窗口里面,是因为我们勾选了下面的两个勾,点击它们,变成灰色就可以停在main.c文件里了
这只是一个最简单的分散加载使用示例,我们会尝试把代码加载到RAM中运行,就像电脑和手机一样;我们也会尝试把单独的一个函数或者一个变量加载到固定地址上;我们还会有把一个Flash空间加载多个image的示例等等。
当然上面提到的.ini文件能做的事情也远不止于此,以后我们还会多次涉及这个文件的用法

