VXWORKS——启动过程

VXWORKS是一种灵活的、可裁剪的嵌入式实时操作系统,用户可以根据需要创建自己的VXWORKS映像,由它来引导目标系统,而后下载并运行应用程序。

根据应用场合不同,vxworks映像可以分成三类:可加载的映像、基于ROM的映像和驻留ROM映像。

1.1可加载的映像

运行与RAM,不包含搬移程序,需要借助一些外部程序如BOOTROM才能加载到RAM的低端RAM_LOW_ADRS地址处。这是缺省的开发映像。

目标板上电后,由烧结在BOOT中的起始引导程序Bootstrap将BOOT中的ROM引导程序拷贝到RAM的高端地址RAM_HIGH_ADRS处,并跳转至该地址执行ROM引导程序,配置好所选的加载方式(缺省为网络方式),将指定的主机目录下的可加载的vxworks映像下载到目标板的RAM地址RAM_LOW_ADRS处,并跳转到此处执行。

优点:生成的vxworks映像可以存放在开发主机PC机上,不用烧到BOOT中,节省了BOOT容量,也便于随时修改不同的映像,适用于调试的初期阶段。不足之处是需要在主机上维护一个正确的映像,对于调试硬件无关的上层应用程序不是很方便。

1.2基于ROM的映像

运行于RAM中,但起初存放于ROM中的映像,即该映像需要和搬移程序一起固化在BOOT中。目标板上电后,首先运行BOOT中的引导搬移程序,将整个映像拷贝到RAM地址RAM_LOW_ARDS处,并跳转到此处执行。(bootstrap将boot程序搬移到RAM的高地址,再搬移映像到RAM的低地址并运行)

该映像根据是否被压缩又可分为:

基于ROM的未压缩的vxworks映像,可以直接从ROM拷贝到RAM中;

基于ROM的压缩的映像,主要是为了节约BOOT空间,在从ROOT拷贝到RAM的过程中需要解压缩,因此与上述未压缩的映像相比,它的引导过程相对较慢,但两者在RAM中的运行速度是一样的。

1.3驻留ROM的映像

起初也和搬移程序一起固化在BOOT中,目标板上电后,首先运行BOOT中的引导搬移程序,但仅将映像的数据段和BSS段拷贝到RAM地址RAM_LOW_ADRS处,映像的代码段仍旧留在ROM中(与1.2的区别),从ROM中开始执行。

优点是具有最快的引导速度,占用最少的RAM空间,适用于RAM空间有限的目标板。但由于该映像在ROM中运行,运行速度在三种映像中是最慢的。

————————————————————————————————————

起始引导程序驻留在ROM中(1.3),主要包含:

汇编级的硬件初始化程序romInit.s,用于系统的基本初始化,设置一些重要寄存器的初始值,进行存储器映射

搬移程序bootInit.c,将ROM引导程序拷贝至RAM的高端地址RAM_HIGH_ADRS,然后跳转到此处执行ROM引导程序。

ROM引导程序起初存放在ROM中,初始化时被拷贝到RAM中,主要用于系统的进一步初始化,并配置加载方式,将映像加载至RAM。

引导过程成功以后,RAM中ROM引导程序占用的空间(从RAM_HIGH_ADRS开始)可以重新被系统利用。

RAM_HIGH_ADRS是ROM引导程序的加载点,RAM_LOW_ADRS是vxworks的加载点。

————————————————————————————————————

vxworks启动过程

bootstrap在ROM中执行

romInit.s:romInit

设置机器状态字及其他硬件相关寄存器,关闭中断,禁止程序和数据cache,初始化内存,并设置堆栈指针。

bootInit.c:romStart()

将ROM中的程序搬移至RAM中。

——————————————————————

ROM Boot程序被搬移到RAM中执行:引导程序

bootConfig.c:usrInit()

RAM入口地址

设置cache工作模式,板级硬件初始化,调用sysHwInit(),usrKernelInit(),KernekInit(),初始化Win内核,产生根任务usrRoot()

bootConfig.c:usrRoot()

初始化内存,系统时钟,I/O系统,标准输入输出,异常处理,外围设备初始化,产生任务bootCmdLoop.

bootConfig.c:bootCmdLoop()

调用自动引导程序autoboot(),此函数若成功则不返回。

bootConfig.c:autoboot()

延迟7S,以默认参数启动,若等待超时,执行bootLoad(),加载vxworks映像,并转向它进行重启;

若用户按键中断,执行bootCmdLoop(),启动命令用于配置vxworks启动参数,用户输入@,则进入bootLoad()。

——————————————————————————

开始在RAM中执行:映像

sysALib.s:sysInit()

锁住中断,关闭cache(如果使用了话),初始化处理器的寄存器(包括C堆栈指针)至缺省值。

prjConfig.c:usrInit()

设置cache工作模式,板级硬件初始化,初始化win内核,启动usrRoot()

prjConfig.c:usrRoot()

初始化内存,系统时钟,I/O系统,标准输入输出,异常处理,添加用户应用程序。

——————————————————————————————————

可加载vxworks映像的BOOT过程

BOOT中几个关键宏定义:

#define LOCAL_MEM_LOCAL_ADRS


#define ROM_TEXT_ADRS  :ROM boot程序执行起始地址(romStart())

#define ROM_OFFSET(adr)

#define BOOT_LINE_OFFSET

#define BOOT_LINE_ADRS :ldFileFromMch时,从该起始地址读取加载要用到的tBootParams

#define RM_LOW_ADRS:boot Rom将控制权交给vxworks的起始进入点(usrInit().boot启动之后,将系统映像从FLASH上copy或解压到RAM_LOW_ADRS地址处,并跳转到该地址执行

#define VERSION_START_ADRS :版本加载完后的执行入口地址

#define FREE_RAM_ADRS :start right after bss of vxworks

#define  FREE_MEM_START_ADRS:bootRom 中的pMemPoolStart

_______________________________________________________________

BOOTROM启动过程

1、romInit.s

目标板加电后,程序指针指向RESET中断程序入口处,开始执行初始化程序romInit.s,设置机器状态字及其他硬件相关寄存器,关闭中断,禁止程序和数据CACAHE,初始化内存,并设置堆栈指针,保存启动类型,调用romStart.c中的romStart()。

romInit中首先会将这个默认值改为自定义的一个内存映像基地址。原是0xFF400000

2、romStart()

sync程序跳到第一个C程序romStart.c函数的romStart()入口地址,根据堆栈中的参数决定是否清零内存RAM(如果是冷启动cold start,则清零),根据不同的bootRom文件,把ROM中数据段和文本段拷贝到RAM,(如果ROM代码是压缩的,还要解压)。

3、usrInit()

程序跳到RAM入口地址(usrConfig.c中函数usrInit()),usrInit()中清零bss段(这也是未赋初始值得全局变量在编译后初始值为0的原因),调用execVecInit()安装异常向量,初始化异常处理程序,调用cacheLibInit(),设置cache的指令与数据工作模式,调用sysHwInit()对板级硬件初始化,调用usrKernelInit()配置wind Kernel,调用KernelInit()进行内核初始化。

4、KernelInit()

初始化内核及内存池,主要是中断堆栈及根任务堆栈初始化,初始化任务Tcb并生成根任务usrRoot().

kernelInit()调用intLockLevelSet(),关闭循环模式,创建一个中断堆栈(如果结构支持的话)。然后从内存池的顶部创建一个根堆栈和TCB,创建一个根任务usrRoot,并终止usrInit()线程的执行。此时使能中断,所有的中断源已被关闭,未决中断已被清除。


PowerPC体系结构的内存结构分为5大部分,分别为:系统映像之前的系统启动相关的低端内存,系统映像,Host Memory Pool,中断堆栈以及系统内存池。

1)、系统映像之前的低端内存

包括中断向量表、共享内存标志、自启动参数、异常信息和初始化堆栈。

中断向量表(异常向量表):0x0-0x3000的12K空间,保存有重要的中断向量信息。

共享内存标志:0x4100-0x4200地址,作用是标志是否有网络共享内存和VxMP共享内存对象。

启动参数是保留vxworks启动时所用的参数。

异常信息,起始地址是0x4300.用 d 0x4300查看其中记录的内容。

初始化堆栈:是给useInit()使用的初始化堆栈,直到usrRoot()分配堆栈,起始地址是0x4c00

2)、系统映像

是ELF格式的文件,boot启动之后,将系统映像从flash上拷贝或者解压到RAM_LOW_ADRS地址处,并跳转到该地址执行,

系统映像包括三部分:TEXT段、DATA段、BSS段。其中TEXT段是代码段,使用的内存基本是必须的;DATA段是数据段,包括已经初始化的全局变量和数组;而BSS段是未初始化的数据段,包括未初始化的全局变量和数组,实际上基本不占用flash存储空间,在vxworks系统启动的时候在内存将其进行扩展为全零。

代码段的起始地址:RAM_LOW_ADRS,终止地址:vxworks定义的 char etext[];

数据段的起始地址:vxworks定义的char etext[],终止地址vxworks定义的char edata[];

BSS段的起始地址:vxworks定义的char edata[],终止地址:vxworks定义的char end[]。

FREE_RAM_ADRS指向vxworks定义的char end[],即BSS段的最后,也是映像的最后。

end是由loader在动态加载时确定的,从源码里找不到,首先取得end变量地址,再减去RAM_LOW_ADRS的空间,即得到系统映像的大小:dwImageSize=(WORD32)end-RAM_LOW_ADRS。

3)、HOST Memory Pool

是在vxworks上驻留的调试工具使用的内存空间,可以根据WDB_POOL_SIZE宏得到,一般有十几M左右。

起始地址是char end[],终止地址是end+WDB_POOL_SIZE.

4)、中断堆栈:中断堆栈的大小可以由宏ISR_STACK_SIZE定义得到。

5)、系统内存池

是给vxworks用户程序使用的存储空间,用户通过malloc动态申请获得,可以说是最大的内存空间,当物理内存不够需要优化时,要重点考虑。


5、usRoot()

本系统的根任务函数usrRoot()是在prjConfig.h中。在该任务中初始化内存,系统时钟时,I/O系统,标准输入输出,异常处理,外围设备等。

最后会调用usrAppInit.c中的usrAppInit()进行用户级应用模块的初始化。

6、usrAppInit()

调用BspFlashInit()以及usrMiiWrite()对flash以及PHY进行初始化;调用MacIpReset()获取在flash中设置的本板IP地址值,并把本板IP地址设置为该值;调用extUartPPPInit()初始化tty设备;调用BootBoardInit()(对主控板初始化文件系统、受控板初始化flash、通讯串口、获取槽位号、IP地址信息等);最后会调用BootApp.c中的BootAppStart()进入autoboot,根据单板设计方式选择不同方式加载vxworks映像文件,如通过串口、网口、硬盘等方式加载。

————————————————————————————————

vxworks映像启动过程

1、vxworks进入点sysInit()

第一步将系统映像加载到主存。vxworks映像被加载到ram后,Bootram会复位并将控制权交给vxworks起始进入点sysInit(),在makefile和config.h文件中,已将这个进入点设置成位于地址RAM_LOW_ADRS.

sysInit()位于sysALib.s中,可以锁住中断,关闭cache(如果使用了的话),初始化处理器的寄存器(包括C堆栈指针)至缺省值。

调用usrConfig.c中usrInit()。

2、初始化代码usrInit()

储存有关引导类型信息,处理在内核启动之前必须执行的初始化,而后启动内核执行,是运行在vxworks内的第一个c函数,此时所有的中断都已被锁住

仅做一些创建初始化任务usrRoot()所必须的工作,然后由usrRoot()完成启动过程。

usrInit()中初始化过程是:

cache初始化,在函数结束时,缺省情况下,指令cache和数据cache被使能。

对系统的BSS段清零

。。。。

3、初始任务usrRoot()

当多任务内核启动后,所有的VXWORKS多任务工具就可以用了。控制权被传送到usrRoot()任务,并完成初始化系统。

a)初始化系统时钟:

sysClkInit ()

sysClkRateSet():将系统时钟频率设置为60HZ

b)初始化I/O系统和驱动

c)创建控制台设备:

ttyDrv()(prjParams.h)

CONSOLE_TTY指定哪个口作为控制台口(缺省是0)

#define CONSOLE_BAUD_RATE 115200

NUM_TTY定义了tty口数量(缺省是2)

d)设置标准输入和标准输出

e)安装异常处理和登录

。。。

f)创建文件系统设备并初始化设备驱动

许多vxworks配置至少包含一个磁盘驱动器,或带有dosFs/rt11Fs/rawFs文件系统的RAM磁盘。首先,通过调用驱动器的初始化代码安装一个磁盘驱动器。驱动器的设备创建代码会定义一个设备。这个调用会返回一个指向描述设备的BLK_DEV结构指针。

然后就可以调用文件系统的设备初始化代码--dosFsDevInit(),rt11FsDevInit(),or rawFsDevInit()初始化和命名设备。在初始化一个设备之前,必须用dosFsInit(),rt11FsInit()或rawFsInit()初始化文件系统模块。

g)初始化网络

如果配置头文件中定义了INCLUDE_NET_INIT,usrRoot()就会调用usrNetInit()函数初始化网络。

。。。

h)执行一个启动脚本

如果vxworks配置了目标驻留的shell,定义了INCLUDE_STARTUP_SCRIPT,并且在boot引导过程中,在启动脚本参数中输入了脚本文件的名称,usrRoot()函数就可以执行一个用户提供的启动脚本。如果在引导过程中忽略了启动脚本参数,就不会执行启动脚本。

——————————————————————————————

使用基于ROM的VXWORKS映像启动过程

此时BOOTROM中包含了引导程序和vxworks映像。vxworks的入口点由两个函数romInit()和romStart()(需要搬移)来完成.(sysInit()是可加载映像的初始化入口)。

VXWORKS——启动过程_第1张图片


你可能感兴趣的:(VxWorks)