如果你是从一个更早的VxWorks版本转到VxWorks 7的话,你可能想知道:我该如何编译一个bootrom呢?本文将解释VxWorks 7的启动机制是如何变化的,针对基于客制化硬件的工程来说意味着什么?如果你想从更早的VxWorks版本的BSP升级的话,你需要阅读以下内容。

VxWorks 4/5/6的启动过程

在使用VxWorks 7之前,我可以记得的最久远的,VxWorks的启动过程都是一样的:所谓的VxWorks ‘bootrom'是存在于flash存储当中并从复位开始自动运行。bootrom会初始化所有运行VxWorks所需的硬件,然后加载VxWorks系统(通常以ELF文件形式存在)到内存并运行它,bootrom可以从包括可用格式的flash存储文件系统加载VxWorks镜像,或者通过网络连接从另一台机器上加载。

诚然,bootrom是内置了一个应用程序的VxWorks的特殊的编译镜像,此应用程序只是用来加载主要的VxWorks系统镜像。这个特殊的编译镜像包含了能将处理器从复位状态启动的代码,并能将系统启动到一个工作的状态;通常这包含设置时钟,管脚复用,内存控制器等等。bootrom的另一个特殊功能是它是可以驻留并安装在只读存储上的。

尽管这个方法在过去一直工作得很好,但它还是有一些问题:

  • 如果你为一个客制化的硬件来设计一个BSP,你会遇到”鸡和蛋“的问题:在你拥有一个可工作的bootrom前你需要一个可正常工作的BSP,而在你可以测试并调试一个BSP前你(常常)需要一个可以正常工作的bootrom。
  • 因为片上系统(SoCs)集成了更多的功能,初始化硬件的过程变得更加的复杂,在某些时候芯片厂家并没有非常好地用文档记录。
  • 片上系统(SoCs)已经开始包含他们自己的内置启动代码用来支持从不同的存储启动,包括NOR flash,SD卡等等。这使得基于一个VxWorks BSP来编译一个可以和片上系统的启动代码在各种可能的情形下一起工作变得更加困难。

VxWorks 7带来了哪些变化

尽管启动VxWorks 7的整体过程和老版本很相似,但是一些细节还是有非常大的变化,主要的变化如下:

  • VxWorks 7自身不再包含可以从复位开始直接启动到系统的只读存储代码
  • VxWorks 7使用一种Linux风格的设备树来定义硬件,该设备树常常需要在VxWorks内核启动前被以二进制'blob'的形式加载到内存

可能这样就很显然了,VxWorks 7不再支持编译一个旧风格的bootrom(或者任何形式的只读VxWorks镜像),取而代之,硬件必须要安装一个独立的引导加载程序来从复位开始运行并启动系统。

如果你正在使用一个商用的货架硬件产品,使用最多的引导加载程序很可能就是U-Boot,很多厂商,比如NXP,都会提供一个安装了U-Boot的评估板,U-Boot是一个使用广泛而且功能非常强大的引导加载程序。比如,它可以启动诸如Linux的别的操作系统。

但是,如果你是基于客制化设计的硬件来制作系统并且你也不想将U-Boot移植到该硬件上,该怎么办?一个可选项是使用Wind River提供的新的VxWorks 引导加载程序,VxBL。

VxBL是什么?

VxBL是一个精简的,独立的主引导加载程序,可以安装在flash存储上,以便从复位开始运行。在初始化处理器和存储子系统后,它的工作是识别一个随后的程序,并将其加载到主内存,然后运行它。作为这个过程的一部分,VxBL也能够加载一个独立的设备树"blob"来识别系统的硬件配置。

VxBL支持ARM和PowerPC目标机,它能够从各种形式的flash存储或者FAT-32格式的SD卡上加载程序,可以认识被存储成U-Boot镜像或者EFL文件的程序;不像VxWorks 6.9的bootrom,VxBL不是基于VxWorks内核并且不支持网络堆栈。

一个非常好的功能是VxBL能够使用U-Boot镜像头来识别一个压缩的程序,然后解压该程序并将其加载到主内存,这在程序镜像的存储空间非常有限的情况下非常管用,即使这意味着系统需要更长一点的时间来启动。

实现并编译VxBL

如果你打算在你的客制化设计的硬件上使用VxBL,你需要首先花点时间来阅读一下Wind River的VxWorks 7启动引导程序用户指南,包含一个名为“使用VxBL启动”的章节,该章节描述了如何创建和编译一个VxBL项目工程。虽然VxBL的项目工程可以在Wind River的Workbench里创建,但是它其实是一个传统的基于命令行的Makefile工程,可以编译一个独立的,用来编程到flash存储的二进制文件。

很自然地,VxBL的某些部分需要针对你的客制化目标硬件进行裁剪,这包括初始化代码(rootInit.s),通用的具体板卡的程序(bootLib.c)以及一个Makefile,通常,开发这些的最好的方法是从Wind River针对相似硬件的VxBL实现例子中拷贝对应的文件,最好是基于相同的处理器。

VxBL是使用一个Linux风格的配置文件进行配置的,如你期待的那样,配置选项包含诸如内存地址和大小的细节,这必须按照你的硬件的实际情况进行调整和选择。你可以配置VxBL启动引导位于flash存储上固定地址的程序,或者一个SD卡上的固定名字的文件。或者VxBL也可以提供一个有限的交互的命令行解释器,当你测试引导阶段的时候非常有用。

为了在你的目标硬件上安装VxBL,需要一个将二进制代码烧录到flash存储上的方法,这可能需要使用一个JTAG或者类似的调试器,这可以帮助你来测试和调试VxBL,特别是在任何向串行终端可以输出文本前的早期初始化程序。

VxBL的引导策略

其中一个引导策略是使用VxBL来职介引导你的产品将要运行的VxWorks系统镜像,这也包含直接链接到单个镜像的应用程序。

这个策略是VxWorks早期版本支持的只读VxWorks方法的很好的替代,和以前一样,你可以选择压缩镜像来节省空间或者让其保持非压缩的状态来缩短启动时间。

但是如果你更倾向保持和旧的VxWorks bootrom相似可以拥有可以通过一个网络连接来加载VxWorks镜像的灵活性,该怎么办呢?在这种情况下,你可以使用一个VxWorks 7的引导应用程序("boot app")。

VxWorks 7的引导应用程序可以有效地从旧的VxWorks bootrom提取代码并将其链接到VxWorks 7的内核,这可以让你可以像旧的bootrom一样做一些工作,但是至关重要的区别是,你不能够直接从复位开始运行。你可以通过创建一个VxWorks镜像工程并选择PROFILE_BOOTAPP的配置来非常容易地编译一个boot app:

VxWorks 7 PROFILE_BOOTAPP

使用VxBL来加载并运行一个VxWorks 7 boot app,你可以拥有之前旧的bootrom可提供的相同的功能和灵活性。

最后一个事情:热重启

如果你为系统移植VxWorks 7,你还需要了解关于引导策略的另一个事情,在早期的VxWorks版本,你可以调用reboot()来重启VxWorks bootrom,可以通过一个参数来告诉它是进行“冷”或“热”重启,区别是,如果是热重启的话,bootrom将不会重新初始化内存并可以使用设定在RAM中的引导参数进行引导,而不是从非易失的存储中读取。

这个流程在VxWorks 7中是不支持的,但“冷”和”热“重启之间的区别还是有的,但和之前的情况不一样了。一个”冷“重启意味着一个硬件复位(如果这可以被软件识别的话),CPU复位并且整个引导顺序从头重新开始。

“热”重启的情况就非常新了,虽然VxWorks 7将会在不重新加载的情况下重新启动操作系统,但事实是,引导加载程序一点都不会运行(唯一重新加载的是初始化的数据段,这是VxWorks在之前启动过程中已经拷贝好的),当没有必要重新加载一个不同版本的操作软件时,这让重新启动变得非常迅速。你可以通过在你的VxWorks镜像工程中定义INCLUDE_WARM_BOOT来使能这个新的“热”重新机制:

VxWorks 7 Initialize_warm_boot_library

结论

虽然开始的时候听到VxWorks 7没有bootrom了你会感到有些许震惊,但在某种程度上,VxWorks 7的引导策略更好地适应了现代的硬件,并允许重新使用诸如U-Boot的标准引导加载程序,这是很方便的。另一方面,通过使用VxBL你还是能够支持客制化的硬件设计,并可以复制“可只读的VxWorks”和用于VxWorks早期版本的基于bootrom的引导机制。