介绍

使用编程到设备中的引导程序,您可以轻松下载和执行应用程序,而无需将产品带回车间。但是,由于引导加载程序和应用程序都驻留在一个设备中,因此必须特别注意确保它们共享可用内存。

本次网络研讨会着眼于您可以选择的一种策略,即链接引导程序和它们下载的应用程序,实现这一点的编译器选项,以及如何检查所有内容是否按要求定位。你到底在引导程序中放了什么,以及如何编写,都由你自己决定;然而,我们将查看PIC18引导加载程序的典型流程图,并显示引导加载程序可以用来调用应用程序和处理中断的特定代码序列。

尽管本演示文稿中详细介绍的编译器选项可以应用于其他8位设备,但由于备用指令集的原因,中端PIC引导程序的结构需要有所不同,尤其是在使用中断时。

链接PIC18引导程序和应用程序-LMLPHP

讨论

让我们先来看看您可能想要构建引导程序的方式。本次网络研讨会剩余部分所示的内存排列假设引导加载程序是以这种方式设计的。

您的引导加载程序是唯一一个始终被编程到设备中的代码,因此它必须定义★ 重置时执行。此代码将转到★ 等待在您选择的外围设备上发送应用程序数据,例如USART。

一旦数据开始到达,★ 引导加载程序从应用程序启动地址开始读取并将其编程到闪存中,我们将称之为,该地址必须是预定义的并保持固定。应用程序数据最容易使用的格式是Intel HEX文件,该文件在使用MPLAB XC8 C编译器生成时默认生成。

如果没有数据发送到外围设备上的引导加载程序,那么引导加载程序应该超时,如果您愿意,您可以简单地假设之前已经下载了代码。

一旦应用程序被完全下载和编程,或者等待下载的代码超时,引导加载程序就可以★ 跳转到预定义的应用程序起始地址处的应用程序。由于此跳转永远不会返回,因此引导加载程序★ 现在基本上完成了,应用程序控制了设备。★

如果您的应用程序需要使用中断,那么也需要在引导加载程序中进行处理。让引导加载程序定义将驻留在中断向量位置的代码是最简单的,并且★ 当中断发生时,只需使用以下代码★ 跳转到应用程序中预定义的中断地址。应用程序将定义并执行中断序列的返回,因此在该跳跃之后,★ 引导加载程序代码再次完成。

我们稍后将在本演示中详细讨论跳转到应用程序的代码,但现在,让我们看看如何在PIC18设备的内存中安排引导加载程序和应用程序代码。

程序内存布局

链接PIC18引导程序和应用程序-LMLPHP

说明

这里我们看到了PIC18设备的程序存储器。与中端设备不同,此内存似乎不会被分页,因此此过程中不考虑此问题。

我们通常不需要考虑设备的数据存储器。一旦引导加载程序完成执行,它使用的任何RAM现在都是免费的,可以由应用程序使用,因此不会共享这些内存。

我们将使用的基本方法是从概念上★ 拆分程序内存,将一部分分配给引导加载程序,将另一部分分配到应用程序。如果两者都不使用分配给另一个的内存,那么一旦两个程序映像在设备中合并,代码就会正常工作。通常,会为引导加载程序分配尽可能少的内存。

您必须考虑几个重要的内存位置。首先,设备重置★ 被硬编码为地址0。重置后,代码将始终指向此地址。其次是中断★ 位于地址8和18h附近的矢量。高优先级和低优先级中断分别指向这些位置,并且这些地址由设备固定。

现在让我们看看如何将★ 引导加载程序应用程序本身。我们将在后面看到可以用来处理中断的代码,但假设我们只是用C编写引导加载程序。如果将其留在自己的设备上,编译器将★ 生成处理设备重置的代码,并将其分配给重置向量;我们的★ 中断代码将被链接到中断向量位置;但是★ 代码的其余部分将被链接

程序内存中任何可用的位置。通常情况下,链接器从空闲内存开始向上整理一些部分,而从内存顶部开始向下整理其他部分。这个代码的确切链接位置无关紧要,但我们需要确保它都包含在任意的内存范围内。

我们可以这样做★ 使用编译器选项保留内存。我们可以将内存从默认的片上范围中移除★ 强制链接器将我们的代码定位到程序内存空间的一个小区域中。我们将很快看到相关的选项以及您如何在IDE中访问它,但这就是链接引导加载程序的全部内容。

现在来看我们的可下载应用程序。★ 同样,如果我们不使用选项来指示其他情况,编译器将在★ 重置矢量,我们的★ 中断函数将链接到中断向量,并且★ 代码的剩余部分将被分配一些其他空闲位置。这不是我们所需要的,所以我们可以尝试使用相同的选项来保留较低的内存。然而,这只会★ 移动那些在自由空间中链接的代码部分。我们的重置和中断代码仍将在矢量位置链接,因为链接器对它们有明确的说明,必须遵守这些说明。

然而,我们可以使用一种不同的编译器选项,它是专门考虑到引导加载程序而设计的。这样做不仅可以在您指定的地址下保留内存,还可以★ 将重置代码和中断代码都上移。这就好像整个程序内存图像向上偏移了一个偏移量。

使用这两个选项可以确保当引导加载程序和应用程序★ 加载到设备中时,没有覆盖或干扰。

应用程序

现在让我们来看看我们是如何使编译器根据需要链接我们的应用程序代码的。我已经决定引导加载程序将占用0到2FF十六进制的地址范围,并且我们的应用程序将从地址300开始。因此,我们需要将整个应用程序映像向上移动300个十六进制,并使用–codeoffset选项来完成此操作。然后,我们将使用地图文件确认一切正常。让我们切换到IDE中,看看这是如何实现的。

我已经在MPLAB X IDE中打开了我的应用程序项目。我只输入了空函数,但你可以看到我有一个主函数和两个以通常方式定义的中断函数,尽管是空的。当然,这些函数将由您的应用程序代码填充。

在我们调整编译器选项之前,让我们看看映射文件,它指示了事物链接的位置。它将向我们展示在应用代码偏移选项之前是如何安排的。首先,让我们构建这段代码,使映射文件是最新的。现在,对于常规构建,映射文件将位于项目目录中的dist>default>production目录下。它将有一个.map扩展名。

文件顶部是用于构建项目的链接器选项的副本。这看起来可能很神秘,但实际上只有两种类型的选项通常用于链接部分——或者我们称之为psect。这些选项中的第一个是-p选项。还记得我是如何指示与重置和中断向量相关的代码明确链接到这些位置的吗?好吧,这就是可以做到这一点的选项。在这里,您可以看到-p选项,它链接地址0处的重置向量部分(-preset_vec=0h)。这个相同的选项还链接地址8处的中断代码和地址18十六进制处的低优先级中断代码。

另一种选项是-A选项,它只定义一个地址范围,称为链接器类。还请记住,我是如何指出大多数部分都链接到内存范围内的任何位置的。这些-A选项就是如何定义这些范围的。在这里,您可以看到将CODE类定义为从0到17FFF十六进制(-ACODE=0h-17fffh)的地址范围的选项,这是我选择的设备的程序内存。请记住,不同的设备具有不同的内存大小。几乎所有的可执行代码都放在一个名为code的类中,所以在映射文件中查找它是一个很好的类。

如果您在地图文件中向下滚动,您可以看到这些部分的实际位置。您可以看到CODE类中分配的所有部分的链接地址遍布各处。重置和中断向量是我们所期望的,但其他代码的位置更高。还有常量数据链接到程序内存中。我们不需要担心后面的类,因为它们在RAM中。

因此,目前我们的应用程序位于引导加载程序的顶部,这是我们不希望看到的,所以让我们打开项目财产,选择Linker选项类别,然后选择Additional options选项卡。我们想要的选项称为Codeoffset,单击它以获取帮助。我们只需给它一个十六进制偏移地址,该地址将应用于我们的整个程序。因此,在这个例子中,我们需要偏移300个十六进制,然后应用更改。

我们需要重新编译,这就是我们所需要做的。但是,让我们确认更改已经发生——回到映射文件。

您现在可以看到重置矢量代码已链接到地址300 hex;308处的中断代码和318处的低优先级中断代码。如果检查链接器类,例如CODE类,您可以看到它现在是一个从300开始的内存范围,而不是0。您也可以检查分配给下面部分的实际地址。您可以看到,没有一个代码低于地址300。常量数据也链接在正确的范围内。

所以我们的应用程序完成了。

bootloader程序

现在,让我们转向引导加载程序,看看我们如何在IDE中链接它。在这个项目中,我们只需要确保所有内容都链接到某个地址以下,我们将使用–ROM选项来完成这项工作。


所以,这是我在MPLAB X IDE中打开的引导程序项目。同样,您在引导程序中到底放了什么取决于您,但我们将在本演示稍后的文件中介绍您可以在我的文件中看到的汇编代码片段。

回想一下,我们的引导加载程序不会像我们的应用程序那样在内存中向上移动。重置和中断代码将链接到通常的矢量位置。然而,我们必须确保引导加载程序中的任何内容都不能超过地址300h。

让我们先编译这个项目,然后打开映射文件。这个项目显然是针对同一个设备的,所以链接器选项最初将与以前相同。因此,重置和中断部分按照我们希望的方式进行连接。但您可以看到,例如,CODE类仍然覆盖了片上程序内存的整个范围。如果我们向下滚动,您可以看到在这种特殊情况下,所有代码都低于300十六进制,但我们不应该总是这样。

让我们打开项目财产,确保只有较低的内存可用。转到XC8全局选项,我们想调整ROM范围选项。点击它获取更多信息。默认情况下,所有片上存储器都可用。有了这个选项,我们可以要求所有默认内存,并减去我们不想要的部分,但更容易的是指定我们想要的内存,在本例中为0-2ff。

我们需要重新编译,然后再次检查映射文件,以确保该选项被接受。例如,您现在可以看到CODE类选项反映了新的内存范围,这确保了分配给这个类的任何内容都不会链接到我们的应用程序的顶部。正如我们所期望的那样,所有的部分都被链接起来了,如地图文件中下面所示。

参考

04-11 09:44