一.引导过程
1.bootstrap/bootloader/bootrom bootstrap是固化在CPU的ROM中的一小段指令系列,它是最初级的引导,旨在初始化CPU、时钟、堆栈,目标是让CPU正常运作起来。 引导加载程序(bootloader)是系统上电后运行的第一段软件代码。广义的bootloader可以认为是BootstrapProgram+Boot Image,不过一般就是指Boot Image。Boot Image的地位和作用可类比PC中位于BIOS固件程序(firmware)+硬盘MBR中的OS BootLoader(比如LILO和GRUB 等),它完成系统从上电后的硬件检测和资源分配,并将内核映象加载到RAM中,然后跳转到内核的入口点去运行启动操作系统。 bootrom通常是用来存储BootLoader的ROM/FLASH芯片,在VxWorks文档中的bootrom区是指Boot Image存放的位置。bootrom 完成VxWorks启动前的基本引导工作,如最简初始化硬件,下载映象文件并解压到RAM中等操作。 2.引导流程 CPU从没有电到上电状态,经过自复位的过程后,指令指针指向一个固定的地址。基于 CPU 构建的嵌入式系统通常都有某种类型的固态存储设备(比如:ROM、EEPROM或FLASH等)被映射到这个预先安排的地址上。因此,在系统上电 后,CPU将首先执行这个地址所包含的指令,即Boot Loader程序。 无论如何,CPU开始执行一段指令了,这段指令的作用首先是将可执行程序所需的最小环境搭建起来。这个初始化过程包括初 始化CPU、内存控制器及各种必需输入/输出设备、磁盘控制器等等。以X86体系结构来说,需要初始化CPU、北桥、南桥,常说的BIOS就是这样一段初 始化程序。在那些没有BIOS的架构中,这一工作由系统的bootrom完成。 建立了最小可运行系统,操作系统的内核就可以运行了。于是,BIOS或bootrom程序将操作系统从能够永久保存内容的存储介质中读取出来加载到内存中。这些可永久保存内容的存储介质可能是NVROM、磁盘、光盘等,例如我们常说的操作系统光盘。 通常,操作系统在加载过程中还会对硬件环境做一次重新初始化,这一次初始化就不仅仅是最小运行环境了。包括CPU在内的 全部计算机所包含的硬件都会被操作系统依次初始化,同时初始化的还包括操作系统内核本身。这样,整个系统就处于一种可控状态,可以开始执行用户应用程序 了。 从引导到系统启动是一个bottom-up的过程;启动后,用户交互到系统响应则是一个top-down的过程。 二.VxWorks映象 1.VxWorks映象的组成 VxWorks映象由文本段(.text/.code),数据段(.data)和BSS段(.bss)组成。文本段相当于代码段,是由一些指令组成的;数据段就是由一些初始化过的全局和静态变量组成;BSS段也是由全局变量和静态变量组成,只不过他们都没有经过初始化。 2.VxWorks映象的类型 VxWorks Image的文件类型有两类三种: A.加载型映象(VxWorks类型) (1)Loadable Image是包含用户程序的VxWorks操作系统映象,其不具备引导功能,需要借助bootrom引导程序通过网口或串口下载到RAM中。bootrom在此扮演了“搬运工”的角色。 B.可引导型映象(BootRom类型) 可引导型(Bootable)映象包含含有用户程序的VxWorks操作系统映象,并包括完整的引导代码,可以在系统上电后自动完成自身的引导。 (2)ROM-basedImage(压缩/没有压缩):即将Image直接烧入ROM/flash,运行时将Image拷入RAM中运行。 (3)ROM-residentImage:Image的指令部分驻留在ROM中运行,仅将数据段部分拷入RAM。 注意这里说的三种映象都是包含真正操作系统VxWorks的映象,其中后两种可以直接启动并运行起来,但是第一种不行, 它必须借助另一个叫做Boot Image的映象(可以在Tornado中的build->buildboot rom中生成)才能运行起来,也就是利用Boot Image引导起来然后通过网口或串口下载真正包含VxWorks的LoadableImage,然后才能运行起来。也就是说Boot Image是和LoadableImage结合使用的。 现在看来一共有四种映象文件,让我们看看它们的组成: (1)Boot Image:包含一段起始引导程序(BootStrapProgram)和一段ROM引导程序(ROM Boot Program)。 (2)LoadableImage:由操作系统VxWorks和应用组成的映象。 (3)ROM-basedImage(压缩/没有压缩):包含一段叫做BootStrapProgram的程序+LoadableImage(即有操作系统VxWorks和应用组成的映象)。 (4)ROM-ResidentImage:同上。 通过上面我们可以看出,ROM-based Image,ROM-ResidentImage,Boot Image三种映象都包含一段叫做BootStrapProgram的程序,可以把ROM引导程序的代码段和数据段拷贝到RAM中。同时,它具有启动功能。 三.VxWorks映象启动流程 下面让我们看看三种VxWorks的启动过程: 1.BootImage+Loadable Image 前面提到Loadable Image是依靠Boot Image加载启动的,首先由Boot Image中的BootStrapProgram程序把ROM引导程序(ROM Boot Program)加载到RAM中的RAM_HIGH_ADRS处,然后跳转到此处执行ROM引导程序,由ROM引导程序负责一系列简单的硬件初始化(网 口,串口等),开始下载LoadableImage(即包含应用的VxWorks操作系统)到RAM_LOW_ADRS,然后跳转到此处启动 VxWorks操作系统。 下面的图一是一个简单的流程图,后面的图二是更为详细的流程图。
图一
图二(1)
图二(2) 引导过程成功以后,RAM中ROM引导程序占用的空间(从RAM_HIGH_ADRS开始)可以重新被系统利用。 2.ROM-basedImage(压缩/没有压缩) 这种映象由起始引导程序(BootStrap Program)和基于ROM的VxWorks映象组成。因此,这种bootrom的体积较大。BootStrapProgram把基于ROM的 VxWorks映象加载到内存的RAM_LOW_ADRS处,然后直接启动VxWorks操作系统(如果是压缩的,需要先解压缩)。图三是一个简图,图四 是更为详尽的流程图。
图三
图四 3.ROM-residentImage 这种映象由起始引导程序(BootStrap Programs)和驻留ROM的VxWorks映象组成。VxWorks系统文本段(代码段)驻留在ROM,搬移程序负责将data段和bss段搬移到 内存的RAM_LOW_ADRS处,直接启动VxWorks映像(含符号表)。此时,RAM_LOW_ADRS是VxWorks映象的加载点,也是 VxWorks数据段的起始点。 三.VxWorks映象函数级启动过程 上一节主要是从映象的分类和各种映象的大致加载流程上看VxWorks的启动过程,这一节让我们从函数级看一下VxWorks的启动过程。 1.BootImage+Loadable Image VxWorks借鉴了传统PC操作系统的引导原理,其将整个引导过程分为两个阶段: (1).BOOTROM启动; 起始引导程序(BootStrap Program)驻留在ROM中,主要包含: 汇编级的硬件初始化程序romInit.s,用于系统的基本初始化,设置一些重要寄存器的初始值,进行存储器的映射 搬移程序bootInit.c,将ROM引导程序拷贝至RAM的高端地址RAM_HIGH_ADRS,然后跳转到此处执行ROM引导程序。 ROM引导程序运行,将可加载的VxWorks映象下载到内存的指定地址RAM_LOW_ADRS处。 (2).启动VxWorks内核。 下面是具体的流程图:
其中第一阶段的执行流程使用的是上图的左边的源文件中的那些函数 (romInit->romStart->usrInit->sysHwinit->usrKernelinit->usrRoot); 第二阶段执行流程使用的是上图中右边源文件中的那些函数 (sysInit->usrInit->sysHwinit->usrKernelinit->usrRoot->usrAppInit)。 下面具体解释: 第一阶段: (1)romInit.s : romInit() /*entry point for VxWorks in ROM*/ 系统上电之后,首先调用的函数就是romInit(),其主要完成两个操作:将CPU设置为正确的工作状态,包括各个寄 存器的值以及CPU的工作模式;初始化系统内存并建立堆栈。由于需要设置CPU模式,所以这里的代码必须由汇编代码完成,并且汇编也是建立堆栈的唯一选 择。 禁止中断,避免陷入不确定混乱状态。 清除cache。 初始化CPU基本寄存器,调用SDRAM初始化函数初始化UPM。 初始化系统堆栈,在内存中建立起堆栈后,系统就具备了高级语言的执行条件。后面的代码可以用C实现。 把启动类型(冷启动/热启动)放在堆栈上。 直接跳转到bootInit.c : romStart() (2)bootInit.c : romStart() /*generic ROM initialization*/ 这是VxWorks中所执行的第一段C语言代码,但仍在ROM中执行。 把ROM Boot Program的代码段和数据段从ROM复制到RAM中。 完成程序映象的解压缩(如果映象是压缩版本的)。 跳转到bootConfig.c : usrInit()开始执行ROM引导程序。 从这里开始,可引导型映象和加载型映象走上了相同的初始化道路。 (3)bootConfig.c : usrInit() VxWorks中第一个在RAM中执行的函数。执行操作系统内核所必须的初始化程序。 Cache程序库的初始化。 清零系统的BSS段。 初始化中断向量表。 使硬件工作在一个“安静”的状态,尽量不产生各种中断或者异常。 调用sysHwInit()初始化硬件。 调用usrKernelInit()初始化内核的必要组件。 调用KernelInit(),初始化VxWorks内核并产生usrRoot根任务。 在usrRoot根任务中解析Bootline,产生bootCmdLoop任务,用于启动、加载VxWorks映象。 此时,调试超级终端会有如下打印信息(printBootLogo()): VxWorks System Boot Copyright 1984-1998 Wind River Systems, Inc. CPU: MPC860 Version: 5.4 BSP version: 1.2/0 Creation date: Aug 22002, 09:19:47 Press any key to stopauto-boot... 3 接着,将调用自动引导程序autoboot(timeout),在指定时间timeout内,按任意键可停止自动启动, 修改启动行参数(read andexecute the ROM commands)。下一步将调用bootload()将指定主机目录下的VxWorks映象下载到目标板的RAM地址RAM_LOW_ADRS处,并跳 转(go)到此处执行指令代码,启动VxWorks操作系统。 [VxWorks Boot]: p boot device : cpm unit number : 0 processor number : 0 host name : Michel file name : c:/ftpRoot/vxWorks inet on ethernet (e) :168.2.7.27:ffffff00 host inet (h) : 168.2.7.10 user (u) : target Passwd(pw) : target flags (f) : 0x0 ――――――――――――――――――――――――――― [VxWorks Boot]: @ boot device : cpm unit number : 0 processor number : 0 host name : Michel file name : c:/ftpRoot/vxWorks inet on ethernet (e) :168.2.7.27:ffffff00 host inet (h) : 168.2.7.10 user (u) : target Passwd(pw) : target flags (f) : 0x0
Attached TCP/IPinterface to cpm0. Attaching networkinterface lo0... done. 第二阶段: (1)bootConfig.c : bootLoad() 加载VxWorks映象,并跳转到它的加载地址,具体流程如下。 usrBootLineInit()中strcpy (BOOT_LINE_ADRS,DEFAULT_BOOT_LINE); 从FLASH中读出DEFAULT_BOOT_LINE配置的引导方式及映象文件。 bootload()->usrBootLineCrack(BOOT_LINE_ADRS, ¶ms)获取BOOT_PARAMS,通过params.bootDev类型来决定从硬盘、软盘、闪存加载或通过网口、串口下载VxWorks映象。 bootLoad (BOOT_LINE_ADRS, &entry); { scsiLoad(); /* loada vxWorks image from a local SCSI disk */ fdLoad(); /* loada vxWorks image from a local floppy disk */ ideLoad(); /* loada vxWorks image from a local IDE disk */ ataLoad(); /* loada vxWorks image from a local ATA disk */ pcmciaLoad(); /* loada vxWorks image from a PCMCIA disk device */ tffsLoad(); /* loada vxWorks image from a TFFS Flash disk */ tsfsLoad(); /* loada vxWorks image from a Target Server File System (TSFS) */ netLoad(); /*downLoad a file from a remote machine via the network */ bootLoadModule(); /*bootstrap load an object module into memory */ } 下载完成后,直接跳转到VxWorks系统映象起始地址(RAM_LOW_ADRS)处,从系统入口点(VxWorksimage entry point)开始执行,入口函数为sysInit(): go (entry); /*... and never return */ (2)sysALib.s : sysInit() 与romInit.s : romInit()的初始化过程类似,但不再初始化SDRAM。 (3)usrConfig.c : usrInit() 设置cache的工作模式,板级硬件初始化,初始化Wind内核,启动usrRoot()根任务。 (4)usrConfig.c : usrRoot() 初始化内存,系统时钟,I/O系统,标准输入输出错,异常处理,最后会调用usrAppInit.c中的usrAppInit()进行用户级应用模块的初始化。 此时调试超级终端打印如下信息,Boot引导完成。 /*VXWORKS Image GettingLoaded*/ Loading... 881680 Starting at 0x10000…
Attached TCP/IPinterface to cpm unit 0 Attaching networkinterface lo0... done.
VxWorks Copyright 1984-1998 WindRiver Systems, Inc. CPU : MPC860 vxWorks : 5.4 BSP version: 1.2/0 Creation date: Aug 22000 WDB : Ready 2.ROM-basedImage(压缩/没有压缩) 和上面那种启动方式相比,这种启动方式省去了一些步骤,执行完romStart()之后就已经将VxWorks加载到RAM中了,因此,下一步就是把控制权交给VxWorks,由VxWorks从sysInit()开始执行即可。下面是具体的流程: (1)romInit.s : romInit() 同上。 (2)bootInit.c : romStart() 把基于ROM的VxWorks映象的代码段(如果是VxWorks_romResident映象,则不拷贝代码段)和数据段从bootrom复制到RAM当中。 完成程序映象的解压缩(如果映象是压缩版本的) 跳转到sysALib.s : sysInit() (3)sysALib.s : sysInit() 重新进行CPU内核(主要是cache)的初始化。这些工作在romInit()里面曾经进行过,由于系统刚刚进入RAM中执行,需要再次初始化。 无论使用何种系统(包括仿真器)引导,RAM版本的VxWorks都是从这里开始执行的。 控制权移交给 usrInit() (4)usrConfig.c : usrInit() 执行操作系统内核所必须的初始化程序。 Cache程序库的初始化。 清零系统的BSS段。 初始化中断向量表。 使硬件工作在一个“安静”的状态,尽量不产生各种中断或者异常。 控制权移交给KernelInit(),产生usrRoot根任务,最后会调用usrAppInit.c中的usrAppInit()进行用户级应用模块的初始化。 此时,调试超级终端会有如下打印信息: /*VXWORKS Image GettingLoaded*/ Loading... 881680 Starting at 0x10000…
Attached TCP/IPinterface to cpm unit 0 Attaching networkinterface lo0... done.
VxWorks Copyright 1984-1998 WindRiver Systems, Inc. CPU : MPC860 vxWorks : 5.4 BSP version: 1.2/0 Creation date: Aug 22000 WDB : Ready 3.ROM-residentImage 这种启动方式的流程和上面那种基本相同,只是不需要加载text段到RAM中而已,故在此不作介绍了。 四.使用Tornado编译VxWorks映象 Tornado2.2\target\config\all下的bootConfig.c/bootInit.c /usrConfig.c为通用的bootrom/vxworks代码模版。其中,bootConfig.c/bootInit.c是用来生成 bootrom的,是通过工具栏里的Build->Build Boot Rom生成的,相当于命令行;usrConfig.c是用于生成vxworks的。 需要注意的是如果使用手动编译,则编译的是usrConfig.c文件;如果在Tornado开发环境下编译,则编译的是Tornado根据用户配置自动生成的prjConfig.c文件。 /* prjConfig.c - dynamicaly generated configuration file */ 工程下编译就要按照prjConfig.c里各个程序的封装顺序执行。
说明: 本文涉及的代码片段均源自互联网,仅供学习使用,无任何商业用途。
|
|