VxWorks启动过程描述.docx
《VxWorks启动过程描述.docx》由会员分享,可在线阅读,更多相关《VxWorks启动过程描述.docx(31页珍藏版)》请在冰豆网上搜索。
VxWorks启动过程描述
VxWorks启动过程描述及主要宏开关含义
1三种不同的VxWorks映象比较
VxWorks是一种灵活的、可裁剪的嵌入式实时操作系统。
用户可以根据需要创建自己的VxWorks映象,由它来引导目标系统,而后下载并运行应用程序。
根据应用场合的不同,VxWorks映象可分为三类:
可加载的VxWorks映象、基于ROM的VxWorks映象和驻留ROM的VxWorks映象。
1.1可加载的VxWorks映象
这是一种运行于RAM的VxWorks映象。
它不包含搬移程序,需要借助于一些外部的程序如bootRom才能加载到RAM的低端RAM_LOW_ADRS地址处。
这是缺省的开发映象。
在开发的初期阶段,用户可以根据需要添加或删除一些VxWorks组件,生成自己的可加载的VxWorks映象,存放在开发主机的某个目录下。
目标板上电后,由烧结在BOOT中的起始引导程序(BootStrapPrograms)将BOOT中的ROM引导程序(ROMBootPrograms)拷贝到RAM的高端地址RAM_HIGH_ADRS处,并跳转至该地址执行ROM引导程序,配置好所选的加载方式(缺省为网络方式),将指定的主机目录下的可加载的VxWorks映象下载到目标板的RAM地址RAM_LOW_ADRS处,并跳转到此处执行。
如图1所示。
图1、可加载的VxWorks映象
这种映象的优点是生成的VxWorks映象可以存放在开发主机PC机上,不用烧到BOOT中,节省了BOOT容量,也便于随时修改不同的VxWorks映象,适用于调试的初期阶段。
不足之处是需要在主机上维护一个正确的VxWorks映象,对于调试硬件无关的上层应用程序显得不是很方便。
在Tornado工作台的Build窗口中,选择Rules属性页中的VxWorks即可生成可加载的VxWorks映象。
1.2基于ROM的VxWorks映象
这是一种运行于RAM中,但起初存放于ROM中的VxWorks映象。
即该映象需要和搬移程序一起固化在BOOT中。
目标板上电后,首先运行BOOT中的引导搬移程序,将整个VxWorks映象拷贝到RAM地址RAM_LOW_ADRS处,并跳转到此处执行。
如图2所示。
图2基于ROM的VxWorks映象
该映象根据是否被压缩又可分为:
●基于ROM的未压缩的VxWorks映象,可直接从ROM拷贝到RAM中
●基于ROM的压缩的VxWorks映象,这种映象主要是为了节约BOOT空间,在从ROM拷贝到RAM的过程中需要解压缩,因此与上述未压缩的映象相比,它的引导过程相对较慢,但两者在RAM中的运行速度是一样的。
1.3驻留ROM的VxWorks映象
这种映象起初也和搬移程序一起固化在BOOT中。
目标板上电后,首先运行BOOT中的引导搬移程序,但仅将VxWorks映象的数据段和BSS段拷贝到RAM地址RAM_LOW_ADRS处,映象的代码段仍旧留在ROM中,从ROM中开始执行。
如图3所示。
这种映象的优点是具有最快的引导速度,占用最少的RAM空间,适用于RAM空间有限的目标板。
但是由于该映象在ROM中运行,运行速度在三种映象中是最慢的。
图3驻留ROM的VxWorks映象
2几种不同的BOOTROM的比较
针对上述三种不同的VxWorks映象,可以生成以下几种不同的BOOTROM,主要体现在执行搬移程序romStart()(位于bootInit.c文件中)时不同:
2.1用于可加载VxWorks映象的BOOTROM
由图1所示可知,用于可加载VxWorks映象的BOOTROM包含两部分:
起始引导程序(BootStrapPrograms)和ROM引导程序(ROMBootPrograms)。
起始引导程序驻留在ROM中,主要包含:
●汇编级的硬件初始化程序romInit.s,用于系统的基本初始化,设置一些重要寄存器的初始值,进行存储器的映射
●搬移程序bootInit.c,将ROM引导程序拷贝至RAM的高端地址RAM_HIGH_ADRS,然后跳转到此处执行ROM引导程序。
ROM引导程序起初存放在ROM中,初始化时被拷贝到RAM中,主要用于系统的进一步初始化,并配置加载方式,将VxWorks映象加载至RAM。
可分为三种不同的类型:
●压缩的ROM引导程序,在拷贝的过程中需要解压缩,在RAM中执行
●未压缩的ROM引导程序,可直接拷贝,在RAM中执行
●驻留ROM的ROM引导程序,仅拷贝ROM引导程序的数据段,代码段仍旧在ROM中执行
在Tornado开发环境中,通过在主窗口点击Build|BuildBootROM…可以选择生成以上
三种BOOTROM,分别为:
bootrom_uncmp.hex(未压缩的BOOTROM),bootrom.hex(压缩的BOOTROM),bootrom_res.hex(驻留的BOOTROM)。
静态连接到可加载的VxWorks映象的系统初始化代码执行并完成整个初始化过程。
引导过程成功以后,RAM中ROM引导程序占用的空间(从RAM_HIGH_ADRS开始)可以重新被系统利用。
图1中所示的各地址含义为:
●LOCAL_MEM_LOCAL_ADRS是RAM的起始地址
●RAM_LOW_ADRS是VxWorks的加载点,也是VxWorks代码段的起始位置
●FREE_RAM_ADRS是VxWorks映象的结束点。
通常也是系统内存池和目标服务器内存池的起始地址
●RAM_HIGH_ADRS是ROM引导程序的加载点。
它也是ROM引导程序(除驻留ROM引导程序之外)的代码段的起始位置,或驻留ROM引导程序数据段的起始位置。
2.2用于基于ROM的VxWorks映象的BOOTROM
由图2所示可知,用于该映象的BOOTROM包含两部分:
起始引导程序(BootStrapPrograms)和基于ROM的VxWorks映象。
搬移程序bootInit.c负责将VxWorks映象的文本段和数据段搬移到用户定义的低端内存地址RAM_LOW_ADRS,如果需要进行必要的解压缩,然后直接启动VxWorks映像。
因此BOOTROM的容量相对于2.1中描述的BOOTROM要大一些,但无需在主机目录下维护一个可用的VxWorks映象。
基于ROM的VxWorksBOOTROM有压缩和未压缩之分。
在Tornado工作台的Build窗口中,选择VxWorks映象Rules属性页中的VxWorks_rom即可生成基于ROM的未压缩的VxWorksBOOTROM,选中VxWorks_romCompress即可生成基于ROM的压缩的VxWorksBOOTROM。
2.3用于驻留ROM的VxWorks映象的BOOTROM
由图3所示可知,用于该映象的BOOTROM包含两部分:
起始引导程序(BootStrapPrograms)和驻留ROM的VxWorks映象,VxWorks系统文本段驻留在ROM,搬移程序bootInit.c负责将数据段和bss段搬移到用户定义的低端内存地址RAM_LOW_ADRS,直接启动VxWorks映像(含符号表)。
此时,RAM_LOW_ADRS是VxWorks映象的加载点,它也是VxWorks数据段的起始点。
在Tornado工作台的Build窗口中,选择VxWorks映象Rules属性页中的VxWorks_romResident即可生成驻留ROM的VxWorksBOOTROM。
3VxWorks的启动过程
根据上述所采用的BOOTROM的不同,VxWorks的启动过程会有所不同,下面主要介绍一下使用可加载VxWorks映像的启动过程。
此时,从目标板上电复位到启动用户定义的任务的整个流程如下:
ROMBoot程序
被搬移到RAM中执行
usrConfig.c:
usrRoot()
初始化内存,系统时钟,I/O系统,标准输入输出错,异常处理,添加用户应用程序
3.1可加载VxWorks映象的BOOT过程
Boot中几个关键宏定义:
#defineLOCAL_MEM_LOCAL_ADRS0x00000000
#defineROM_TEXT_ADRS0x100ROMBoot程序执行起始地址(romStart())
#defineROM_OFFSET(adr)(((UINT)adr-(UINT)romInit)+ROM_TEXT_ADRS)
#defineBOOT_LINE_OFFSET0x1200
#defineBOOT_LINE_ADRS((char*)(LOCAL_MEM_LOCAL_ADRS+BOOT_LINE_OFFSET))
ldFileFromMch时,从该起始地址读取加载要用到的tBootParams
#defineRAM_LOW_ADRS0x10000bootRom将控制权交给VxWorks的起始进入点(usrInit()).boot启动之后,将系统映像从Flash上copy或解压到RAM_LOW_ADRS地址处,并跳转到该地址执行
#defineVERSION_START_ADRS0x10000版本加载完后的执行入口地址.
#defineFREE_RAM_ADRS(end)startrightafterbssofVxWorks
#defineFREE_MEM_START_ADRS(FREE_RAM_ADRS+WDB_POOL_SIZE)
bootRom中的pMemPoolStart
在本系统中,BPC以及FS单板的启动流程可概括如下:
3.1.1BOOTROM的启动过程
1、romInit.s
目标板加电之后,程序指针指向RESET中断程序入口处,开始执行初始化程序romInit.s,设置机器状态字及其它硬件相关寄存器,关闭中断,禁止程序和数据CACHE,初始化内存,并设置堆栈指针,保存启动类型,调用romStart.c中的romStart()。
Thedefaultbaseaddressfortheinternalmemorymapregister(IMMR)is0xFF40_0000.BecauseIMMRBARisatoffset0x0fromthebeginningofthelocalaccessregisters,IMMRBARalwayspointstoitself.,在romInit中首先会将这个默认值改为我们自定义的一个内存映像基地址,在本系统中这个歌基地址定义为0xE0000000。
/*initializetheIMMRregister*/
lisr4,HI(CCSBAR)
orir4,r4,LO(CCSBAR)
lisr8,HI(CCSBAR_INIT)/*IMMRwasat0xff400000*/
orir8,r8,LO(CCSBAR_INIT)/*IMMRnowatCCSBAR*/
stwr4,0(r8)
isync
/*setwindowssizeandattribute,configbootat0xfff00000~0xffffffff*/
WRITEADR(r6,r7,M83XX_LBLAWBARn(CCSBAR,0),0x80000000)
WRITEADR(r6,r7,M83XX_LBLAWARn(CCSBAR,0),(LAWAR_ENABLE|LAWAR_SIZE_2GB))
/*DUART波特率设定0x6c8for266M*/
WRITEADRB(r17,r18,MPC83XX_UDMB1(CCSBAR),0x06)WRITEADRB(r17,r18,MPC83XX_UDLB1(CCSBAR),0xc8)
SPMF4:
1ie4*66.67Mhz=266MhzCSB.thedesiredbaudrate=platformclockfrequency/(16x[UDMB||UDLB]=266M/(16×0x06c8)=9600
2、romStart()
sync程序跳到第一个C程序romStart.c的函数romStart()入口地址,根据堆栈中的参数决定是否清零内存RAM(如是冷启动coldstart,则清零),根据不同的bootRom文件,把ROM中数据段和文本段拷贝到RAM(如果ROM代码是压缩的,还要解压);
3、usrInit()
程序跳到RAM入口地址(usrConfig.c中的函数usrInit()),usrInit()中清零bss段(这也是未赋初始值的全局变量在编译后初始值为0的原因),调用excVecInit()安装异常向量(excVecInit会将excIntHandle注册到相应的异常上),初始化异常处理程序,调用cacheLibInit(),设置cache的指令与数据工作模式,调用sysHwInit()对板级硬件初始化,调用usrKernelInit()配置windKernel,调用KernelInit()进行内核初始化。
4、KernelInit()
初始化内核及内存池,主要是中断堆栈及根任务堆栈初始化,初始化任务Tcb并生成根任务usrRoot()。
*kernelInit-initializethekernel.TheroutinekernelRoot()iscalledbeforetheuser'srootroutineso*thatmemorymanagementcanbeinitialized.
*ThememorysetupisasfollowsFor_STACK_GROWS_DOWN:
*-HIGHMEMORY-
*----------------------------------<---pMemPoolEnd
*||Wehavetoleaveroomforthisblockheaders
*|1BLOCK_HDR|sowecanaddtheroottaskmemorytothepool.
*----------------------------------
*|WIND_TCB|
*----------------------------------<---pRootStackBase;
*|ROOTSTACK|
*----------------------------------
*|1FREE_BLOCK|Wehavetoleaveroomfortheseblockheaders
*|1BLOCK_HDR|sowecanaddtheroottaskmemorytothepool.
*----------------------------------<---pRootMemStart;
*----------------------------------
*~FREEMEMORYPOOL~poolinitializedinkernelRoot()
*----------------------------------<---pMemPoolStart+intStackSize;vxIntStackBase
*|INTERRUPTSTACK|
*-----------------------------------<---pMemPoolStart;vxIntStackEnd
*-LOWMEMORY-
kernelInit()函数参数包括:
FUNCPTRrootRtn,/*userstart-uproutine*/
UnsignedrootMemSize,/*memoryforTCBandrootstack*/
char*pMemPoolStart,/*beginningofmemorypool*/
char*pMemPoolEnd,/*endofmemorypool*/
unsignedintStackSize,/*interruptstacksize*/
intlockOutLevel/*interruptlock-outlevel(1-7)*/
●rootRtn:
用以产生作为根任务的应用程序,典型的为usrRoot()
●rootMemSize:
使用的堆栈大小
●pMemPoolStart:
可用的起始内存地址,位于VxWorks映象(bootRom启动过程中,位于从ROM中搬迁过来的boot镜像)的代码段,数据段和bss段之后,如果包含可选的主机内存池,则还要加上WDB_POOL_SIZE。
●pMemPoolEnd:
由sysMemTop()定义的内存顶部
●intStackSize:
中断堆栈的大小
●lockOutLevel:
中断封锁级别
kernelInit()调用intLockLevelSet(),关闭循环模式,创建一个中断堆栈(如果结构支持的话)。
然后从内存池的顶部创建一个根堆栈和TCB,创建一个根任务usrRoot,并终止usrInit()线程的执行。
此时使能中断,所有的中断源已被关闭,未决中断已被清除。
VxWorksRAM空间分配图,斜线部分可以被malloc申请:
VxWorksforPowerPC的内存分配图:
PowerPC体系结构的内存结构包括5大部分,分别为系统映像(SystemImage)之前的系统启动相关的低端内存,系统映像,HostMemoryPool,中断堆栈以及系统内存池(SystemMemoryPool)。
下面就各部分进行介绍。
1.系统映像之前的低端内存
包括中断向量表(InterruptVectorTable),共享内存标志(SMAnchor),启动参数(BootLine),异常信息(ExceptionMessage)和初始化堆栈(InitialStack)。
中断向量表(异常向量表)占据0x0到0x3000地址的12KB的空间,保存有重要的中断向量信息;
共享内存标志占据0x4100到0x4200地址的100字节,它的作用是标志是否有网络共享内存和VxMP共享内存对象;
启动参数是保留VxWorks启动的时候所用的参数,如:
qefcc(0,0)host:
vxWorksh=192.1.1.1e=192.254.0.4u=ccapw=ccatn=cca
异常信息,起始地址是0x4300,如果启动过程中出现致命异常,则系统将异常信息保留在这段内存中。
如果系统启动过程中失败,我们首先要看的是这段地址中记录的异常信息,可以使用d0x4300命令查看其中记录的内容。
初始化堆栈,是给usrInit()使用的初始化堆栈,直到usrRoot()分配堆栈。
起始地址是0x4C00。
2.系统映像
系统映像是ELF格式的文件,boot启动之后,将系统映像(boot映像或版本映像)从Flash上copy或解压(如果是压缩版本)到RAM_LOW_ADRS地址处,并跳转到该地址执行。
系统映像包括三部分:
TEXT段、DATA段、BSS段。
其中TEXT段是代码段,使用的内存基本是必须的;DATA段是数据段,包括已经初始化的全局变量和数组;而BSS段是未初始化的数据段,包括未初始化的全局变量和数组,实际上基本不占用Flash存储空间,在VxWorks系统启动的时候在内存将其进行扩展为全零。
代码段的起始地址:
RAM_LOW_ADRS,终止地址:
VxWorks定义的charetext[];
数据段的起始地址:
VxWorks定义的charetext[],终止地址:
VxWorks定义的charedata[];
BSS段的起始地址:
VxWorks定义的charedata[],终止地址:
VxWorks定义的charend[]。
FREE_RAM_ADRS指向VxWorks定义的charend[],即BSS段的最后,也是映像的最后。
end是由loader在动态加载时确定的,从源码里找不到。
首先取得end变量的地址,再减去低RAM_LOW_ADRS的空间,即得到系统映像的大小:
dwImageSize=(WORD32)end-RAM_LOW_ADRS;
3.HostMemoryPool
HostMemoryPool是在VxWorks上驻留的调试工具使用的内存空间,可以根据WDB_POOL_SIZE宏值得到。
该部分大小一般有十几M左右。
起始地址:
VxWorks定义的charend[],终止地址:
end+WDB_POOL_SIZE。
4.中断堆栈:
中断堆栈的大小可以由宏ISR_STACK_SIZE定义可以得出。
5.系统内存池
这部分是给VxWorks用户程序使用的存储空间,用户通过malloc动态申请获得,这部分可以说是最大的内存空间,当物理内存不够需要优化时需要重点考虑。
5、usrRoot()
本系统的根任务函数usrRoot()在prjConfig.c中。
在该任务中初始化内存,系统时钟,I/O系统,标准输入输出错,异常处理,外围设备等。
BPC初始任务usrRoot具体所处理的内容如下:
voidusrRoot(char*pMemPoolStart,unsignedmemPoolSize)
{
excIntNestLogInit();
vxMsrSet(vxMsrGet()|taskMsrDefault);/*Enableinterruptsatappropriatepointinroottask*/
usrKernelCoreInit();/*corekernelfacilities*/
memInit(pMemPoolStart,memPoolSize);/*fullfeaturedmemoryallocator*/
memPartLibInit(pMemPoolStart,memPoolSize);/*corememorypartitionmanager*/
usrMmuInit();/*basicMMUcomponent*/
sysClkInit();/*Systemclockcomponent*/
selectInit(NUM_FILES);/*select*/
usrIosCoreInit();/*coreI/Osystem*/
usrKernelExtraInit();/*extendedkernelfacilities*/
usrIosExtraInit();/*extendedI/Osystem*/
usrNetworkInit();/*Initializethenetworksubsystem*/
selTaskDeleteHoo