VxWorks及BSP启动流程与顺序_第1页
VxWorks及BSP启动流程与顺序_第2页
VxWorks及BSP启动流程与顺序_第3页
VxWorks及BSP启动流程与顺序_第4页
VxWorks及BSP启动流程与顺序_第5页
已阅读5页,还剩29页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、1目录TOC o 1-5 h z HYPERLINK l bookmark0 1vxworks映像类型1可加载的映像类型(vxwoks)1 HYPERLINK l bookmark6 vxworks映像启动顺序1可加载型vxworks映像启动顺序2 HYPERLINK l bookmark8 基于ROM的vxworks映像启动顺序2 HYPERLINK l bookmark10 基于ROM驻留型vxworks映像启动顺序3 HYPERLINK l bookmark12 BSP基础知识4 HYPERLINK l bookmark14 BSP的定义4 HYPERLINK l bookmark16

2、BSP的功能4 HYPERLINK l bookmark18 BSP的组成4 HYPERLINK l bookmark20 BSP的启动5 HYPERLINK l bookmark22 4.1BSP的启动流程5 HYPERLINK l bookmark30 romlnit.s:romlnit()函数6 HYPERLINK l bookmark34 bootInit.c:romStart()函数14 HYPERLINK l bookmark40 bootConfig.c分析24 HYPERLINK l bookmark52 sysLib.s:sysInit()函数27 HYPERLINK l b

3、ookmark58 usrconfig.c:usrInit()函数28 HYPERLINK l bookmark60 usrconfig.c:usrRoot()函数29 HYPERLINK l bookmark66 总结32 1VxWorks及BSP启动流程与顺序李守轩摘要:本文首先介绍vxworks映像的类型及各类型vxworks映像的启动顺序;然后介绍BSP的启动流程与初始化顺序。关键词:vxworks映像;BSP启动;代码分析vxworks映像类型对于vxworks映像的启动情况,从根本上看,在初始化和装载vxworks映像的过程中,处理器所执行的步骤在逻辑上是一样的。对于有些处理器可能

4、需要增加一些额外的步骤,而另一些处理器可能会省略掉某些步骤。当构造vxworks映像时,根据需要可以构造不同类型的映像,系统把这些映像划分成以下三种类型。1.1可加载的映像类型(vxwoks)可加载型映像的执行需要通过引导代码把它装载到目标机RAM中,然后才开始执行。而引导代码分为两种:(1)引导代码固化在ROM或FLASH中;(2)引导代码是一个独立的vxworks应用;引导代码通常也是一种vxworks映像,也被称为引导映像。它的作用就是把包含应用的vxworks映像装入到RAM中。引导映像可能在ROM/FLASH中执行,也可能在RAM中执行。基于ROM的映像类型(vxworks_Rom&

5、vxwoks_RomCompress)基于ROM的vxworks映像在执行前首先把自己从ROM/FLASH中装载到RAM中,这种类型的映像通常在启动阶段较慢,但在执行阶段比ROM驻留型要快。基于ROM驻留映像类型(vxwoks_RomResident)ROM驻留型映像在启动时把数据段拷贝到目标机RAM中,这种类型的映像在启动阶段比较快,当RAM空间比较小的时候通常使用它。在嵌入式应用中通常会使用该类型的映像,然而,它在目标机上执行的速度要比其他类型要慢,原因是CPU访问ROM比访问RAM要慢。vxworks映像启动顺序在目标机加电启动时发生的顺序启动事件是一个典型vxworks映像需要执行的功

6、能。所有类型的vxworks映像在初始化阶段启动顺序是一样的,处理器通过“jump”跳转指令跳转到ROM或Flash中引导带代码入口处,这段引导代码所要执行的操作包括:(1)关中断;(2)初始化目标机内存;(3)装载适当的vxworks映像段;(4)跳转到设置目标机为静止状态的代码处。不同类型的vxworks映像启动顺序略有不同,下面介绍vxworks映像的启动顺序。可加载型vxworks映像启动顺序ROM/Flash引导带程序RAMROM引导程序、.Vxworks映像引导程序LOCAL_MEM_LOCAL_ADRSRAM_LOW_ADRSFREE_RAM_ADRSRAM_HIGH_ADRS图

7、2.1可加载型vxworks映像启动顺序可加载型vxworks映像引导的详细过程如下:(1)数据段和代码段的装入。系统加电后执行引导带代码,首先把引导代码的代码段和数据段从ROM或Flash里装入RAM中。此时需要考虑下列情况:压缩型引导代码,这种类型的引导代码在拷贝时,需要对它进行解压缩;非压缩型引导代码,这种类型的引导代码直接进行拷贝即可;驻留型引导代码,这种类型的引导代码在拷贝时,仅仅拷贝它的数据段。(2)vxworks映像的装入。引导代码执行后,把vxworks映像装入到RAM中,然后跳转到vxworks映像装入点。(3)系统初始化。执行静态链接在vxworks映像里的系统初始化代码,

8、最终完成系统初始化操作。2.2基于ROM的vxworks映像启动顺序ROM/Flash引导带程序RAMLOCAL_MEM_LOCAL_ADRSRAM_LOW_ADRS基于ROM的VxWorks映像Vxworks映像FREE_RAM_ADRS图2.2基于ROM的VxWorks映像启动顺序基于ROM的vxworks映像启动详细过程如下:VxWorks映像的装入。系统加电后执行引导带代码,首先把VxWorks映像的代码段和数据段从ROM或Flash里装入RAM中。此时需要考虑下列情况:压缩型VxWorks映像,这种类型的VxWorks映像在拷贝时,需要对它进行解压操作;非压缩型VxWorks映像,这

9、种类型的VxWorks映像直接进行拷贝操作;控制权转移。VxWorks映像被装入后,系统控制权转移给RAM中的vxworks映像的初始化代码。系统初始化。执行静态链接在vxworks映像里的系统初始化代码,最终完成系统初始化操作。2.3基于ROM驻留型vxworks映像启动顺序ROM/FlashRAMLOCAL_MEM_LOCAL_ADRSRAM_LOW_ADRSFREE_RAM_ADRS图2.3基于ROM驻留型的VxWorks映像启动顺序基于ROM驻留型的vxworks映像启动详细过程如下:(1)VxWorks映像数据段的装入。系统加电后执行引导带代码,首先把VxWorks映像的数据段从RO

10、M或Flash里装入RAM中。(2)控制权转移。VxWorks映像数据段被装入后,系统控制权转移给ROM或Flash中的vxworks映像的初始化代码。(3)系统初始化。执行ROM或Flash中的静态链接在vxworks映像里的系统初始化代码,最终完成系统初始化操作。3BSP基础知识BSP是VxWorks的一个重要组成部分,在目标机加电后,首先执行的代码就是BSP,可以说VxWorks的启动流程就是BSP的启动流程。BSP的定义BSP(boardsupportpackage)即板级支持包,是介于底层硬件环境和VxWorks之间的一个软件接口。BSP的功能BSP主要功能是系统加电后初始化目标机硬

11、件、初始化操作系统及提供部分硬件的驱动程序。具体如下。(1)初始化。CPU初始化。初始化CPU内部寄存器。目标机初始化。初始化控制芯片的寄存器,为整个软件系统提供底层硬件环境的支持。系统资源初始化。为操作系统及系统的正常运行做准备,进行资源初始化。(2)使VxWorks能够访问硬件驱动程序。主要是指BSP包含部分必要的设备驱动程序和相关设备的初始化操作。(3)在VxWorks系统中,集成了与硬件相关的软件和部分硬件无关的软件。BSP的组成开发板上电后首先跑的就是BSP的代码,BSP主要由源文件、头文件、派生文件Makefile文件组成BSP包含的具体文件请参考相关资料BSP在Tornado安装

12、目录中的位置如图3.1中所示。hostTornado主机驻留工具Tornadoshare共享XDR代码Target.Vxworks系统、BSPh(VxWorks头文件)idllib(VxWorks库文件)proj(tornado工程文件)src(VxWorks部分源代码)unsupported(工具、驱动程序)config(配置和构造VxWorks的文件)一all(通用配置文件)bspname(针对不同CPU的班级支持包)图3.1tornado目录结构4BSP的启动下面首先给出BSP的启动流程,然后对启动过程执行的函数进行具体分析,这是本文的重点和难点,是建立在作者自己理解角度和深度基础之上的

13、。4.1BSP的启动流程BSP的启动流程如图3.2所示,从代码执行的角度描述了BSP的启动过程及启动过程中先后调用函数的功能。rominit.s:romInit初始化CPU,初始化RA控制器,检测内存及大小bootInit.c:romStart将ROM中的程序搬移到RAM中bootConfig.c:usrInit初始化Cache库、VEC、系统硬件、wind内核、启动usrRootJbootConfig.c:usrRoot初始化内存、系统时钟、I/O和文件系统、标准输入输出及出错、异常处理、log任务、ELF文件格式支持bootConfig.c:autoboot延时7秒,以默认参数启动boot

14、Config.c:bootLoad加载VxWorks的ELF文件并转向它进行重启bootConfig.c:bootCmdLoop启动命令行用于配置VxWorks启动参数usrConfig.c:sysInit初始化CPU及l2cache、stackJusrConfig.c:usrInit初始化cache、VEC、异常消息、硬件、wind内核、启动usrRootusrConfig.c:usrRoot用户可定义的系统根任务图3.2BSP启动流程图BSP的启动过程分析从BSP的启动流程图中可以看出BSP启动过程中先后执行的函数,上面对这些函数进行详细描述。4.2.1romlnit.s:romlnit(

15、)函数romlnit()函数的功能romlnit()函数与包含在romlnit.s文件中,且用汇编语言编写。它是系统加电后首先执行的代码,也是所有从ROM/FLASH启动的VxWorks映像的入口点。它执行目标机最小的初始化操作及调用romStart()函数,其它硬件初始化操作推迟到sysHwInit()函数中进行。romInit()函数必须包含下列功能:(1)屏蔽处理器中断及处理器复位;(2)初始化内存系统;(3)初始化堆栈指针和其它寄存器,开始执行romStart()函数及传递启动类型。冷启动与热启动冷启动。所谓冷启动是指硬件环境通过加电启动。在romInit()函数中需要保存系统启动类型

16、,启动类型的宏定义为BOOT_COLD。热启动。所谓热启动是通过调用reboot()、Ctrl+X或异常中断重新启动目标机系统。实际上这些操作是把控制权传递给ROM中的监控函数sysToMonitor(),这个函数包含在sysLib.c文件中,如执行sysToMonitor(2),则系统执行热启动。代码分析(1)X86硬件相关知识IDT是中断描述表,是由门描述符组成的一个数组,每个门描述符对应一个中断/异常向量,其可以保存在内存中的任何位置,CPU通过访问IDTR寄存器获取IDT的位置。IDTR寄存器的长度为48位,其中包括保存IDT的32位线性地址和16位的大小。对于IDTR寄存器的操作包括

17、两个指令:一个是LIDT,另一个是SIDT。LIDT用来将指定IDT所在线性地址和其长度装入LDTR寄存器;而SIDT则是将IDTR寄存器的内容读出。从实模式切换到保护模式之前,必须将基址和限长的值用指令LGDT装入GDTR,一旦系统切换到保护模式,则表所在的物理地址就不再改变,同时立即启用全局描述表,IDT表的基址用指令IDTR。32位控制器CR0的0位为保护允许位PE(protectedenable),用于启动保护模式,pe=1,保护模式启动;pe=0,实模式下运行。实模式进入保护模式的步骤:初始化段描述符一准备并加载GDTR打开地址线A20设置CR0寄存器,进入保护模式一跳转32位代码段

18、。A20地址线的激活请查阅相关资料。上述相关知识是作者在理解代码过程中了解的,当然与硬件相关的知识很多,详细请查阅相关资料。(3)代码分析从作者理解的角度给出了romInit()函数的流程图,如图4.1所示。具体的代码分下如下:包含C的4个头文件。vxWorks.h为系统头文件sysLib.h为系统提供给BSP的头文件config.h是BSP的头文件Asm.h是系统头号文件开始数据段。以下内容出现在数据段里.globlcopyright_wind_river.longcopyright_wind_river/*thefirstin.data*/.globlromwait.globl_romIn

19、it.globl_sdata等等申明全局变量_romlnit和_sdata等冷启动热启动图4.1romlnit()函数流程图定义一个以0结尾的字符串startofdata”。这个串出现在数据段的第一个无名变量之后.text.align16.text开始代码段,以下内容出现在代码段里。.align16使对齐编译器进行填充,使得下一条指令出现在能被16整除的地址上。对齐可使CPU取指令快一点。进入rominit处:Cli关中断jmpcold跳转到cold处。这是段内相对跳转。balign16在32-bit代码前加这样的前缀可以让它变为16-bit代码;在16-bit代码前可以变为32-bit代码进

20、入romWarmHigh处:Cli关中断movlSP_ARG1(%esp),%ebx把esp+SP_ARG1偏移处的值赋予ebx寄存器jmpwarm跳转到warm处。这是段内相对跳转.balign16在32-bit代码前加这样的前缀可以让它变为16-bit代码;在16-bit代码前可以变为32-bit代码进入romWarmLow处:cli关中断cld清方向标志movl$RAM_LOW_ADRS,%esi/*把RAM_LOW_ADRS地址赋给esimovl$ROM_TEXT_ADRS,%edi/*把RAM_LOW_ADRS地址赋给edimovl$ROM_SIZE,%ecx/*把RAM_size地

21、址赋给ecxshrl$2,%ecx/*ecx右移两位256字节变成64个双字repmovsl循环执行esi-edi真到ecx=0movlSP_ARG1(%esp),%ebx把esp+SP_ARG1偏移处的值赋予ebx寄存器jmpwarm/*jumptowarm*/.asciiCopyright1984-2002WindRiverSystems,Inc.balign16,0 x90cold:/cold处.byte0 x67,0 x66与blign16功能相同lidt%cs:(romldtr-romlnit)将中断和量表加载到cs:(romldtr-romlnit)处.byte0 x67,0 x6

22、6与blign16功能相同lgdt%cs:(romGdtr-romlnit)将断描述表加载到cs:(romGdtr-romlnit)处mov%cr0,%eax/*moveCR0toEAX*/.byte0 x66or$0 x00000001,%eax/*nextinsthas32bitoperand*/*setthePEbit*/mov%eax,%cr0/*moveEAXtoCR0*/以上代码的作用是将控制寄存器crO的PE位置1jmpromInit1/*跳转到rominit1处。Rominit1:进入rominit1处.byte0 x66/*nextinsthas32bitoperand*/m

23、ov$0 x0010,%eax/*setdatasegment0 x10is3rdone*/mov%ax,%ds/*setDS*/mov%ax,%es/*setES*/mov%ax,%fs/*setFS*/mov%ax,%gs/*setGS*/mov%ax,%ss/*setSS*/.byte0 x66/*nextinsthas32bitoperand*/mov$ROM_STACK,%esp/*setlowermemstackpointer*/.byte0 x67,0 x66/*nextinsthas32bitoperand*/ljmp$0 x08,$ROM_TEXT_ADRS+romInit2

24、-romInit现在已进入保护模式。然而各个段寄存器的值,以及它们的高速缓存寄存器中的值还是实模式下的。把DS,ES,FS,GS,SS寄存器设为0 x0010,即指向GDT的第2项(从0开始),DPL=0。它们都指向一个段。把堆栈指针esp设为ROM_STACK,由于CS还是以前的值,意味着目前代码段的属性还是16-bit代码。所以使用指令前缀以执行32-bit代码。执行一个远程段间跳转修改CS。CS的新值为0 x08,即GDT的第1项,DPL=0。修改CS时它的高速缓存寄存器也会自动更新。romIDT(InterruptDescriptionTable),中断描述符表,空的。romGdtr:

25、.word0 x0027.longROM_TEXT_ADRS+ROM_GDT/设置段描述表的大小及基地址balign16,0 x90romGdt:段描述表/*0(selector=0 x0000):Nulldescriptor*/.word0 x0000.word0 x0000.byte0 x00.byte0 x00.byte0 x00.byte0 x00/*1(selector=0 x0008):Codedescriptor*/.word0 xffff/*limit:xffff*/段界限低16位.word0 x0000/*base:xxxx0000*/基地址低16位.byte0 x00/*b

26、ase:xx00 xxxx*/基地址中间8位.byte0 x9a/段属性.byte0 xcf/段属性含段界限高4位.byte0 x00/*base:基地址高8位/*2(selector=0 x0010):Datadescriptor*/.word0 xffff/*limit:xffff*/.word0 x0000/*base:xxxx0000*/.byte0 x00/*base:xx00 xxxx*/.byte0 x92/*Datar/w,Present,DPL0*/.byte0 xcf/*limit:fxxxx,PageGra,32bit*/.byte0 x00/*base:00 xxxxx

27、x*/*3(selector=0 x0018):Codedescriptor,forthenestinginterrupt*/.word0 xffff/*limit:xffff*/.word0 x0000/*base:xxxx0000*/.byte0 x00/*base:xx00 xxxx*/.byte0 x9a/*Codee/r,Present,DPL0*/.byte0 xcf/*limit:fxxxx,PageGra,32bit*/.byte0 x00/*base:00 xxxxxx*/*4(selector=0 x0020):Codedescriptor,forthenestingint

28、errupt*/.word0 xffff/*limit:xffff*/.word0 x0000/*base:xxxx0000*/.byte0 x00/*base:xx00 xxxx*/.byte0 x9a/*Codee/r,Present,DPL0*/.byte0 xcf/*limit:fxxxx,PageGra,32bit*/.byte0 x00/*base:00 xxxxxx*/.balign16,0 x90romlnit2:进入rominit2处cli关中断movl$ROM_STACK,%esp设置esp成rom_stack0 x8000h#ifdefined(TGT_CPU)&defi

29、ned(SYMMETRIC_IO_MODE)movl$MP_N_CPU,%eaxlockincl(%eax)#endif定义TGT_CPU和SYMMETRIC_IO_MODE#ifdefINCLUDE_WINDML/*WindML+VesaBIOSinitialization*/Movl$VESA_BIOS_DATA_PREFIX,%ebx/*moveBIOSprefixaddrtoEBX*/movl$VESA_BIOS_KEY_1,(%ebx)/*storeBIOS*/addl$4,%ebx/*incrementEBX*/movlmovl*/$VESA_BIOS_KEY_2,(%ebx)/*

30、storeDATA*/*loadECXwithnBytestocopy$VESA_BIOS_DATA_SIZE,%ecxshrl$2,%ecx/*getnLongstocopy*/movl$0,%esi/*loadESIwithsourceaddr*/movl$VESA_BIOS_DATA_ADDRESS,%edi/*loadEDIwithdestaddr*/repmovsl/*copyBIOSdatatoVRAM*/#endif/*INCLUDE_WINDML*/*/定义INCLUDE_WINDML并初始化VesaBIOS#ifndefINCLUDE_IACSFLcallFUNC(romA2

31、0on)/*enableA20*/cmpl$0,%eax/*isA20enabled?*/jneromInitHlt/*no:jumpromInitHlt*/#endif定义INCLUDE_IACSFLwarm:/进入warm处ARCH_REGS_INIT/*初始化DR0-7标志位寄存器*/#if(CPU=PENTIUM)|(CPU=PENTIUM2)|(CPU=PENTIUM3)|(CPU=PENTIUM4)xorl%eax,%eax/*zeroEAX*/movl%eax,%cr4#endif如果是奔腾系列初将cr4清零movl$romGdtr,%eax加载前面的romGdt表subl$FU

32、NC(romInit),%eaxaddl$ROM_TEXT_ADRS,%eaxpushl%eaxcallFUNC(romLoadGdt)movl$STACK_ADRS,%esp/*initialisethestackpointer*/movl$ROM_TEXT_ADRS,%esi/*getsrcaddr(ROM_TEXT_ADRS)movl$romInit,%edi/*getdstaddr(romInit)*/cmpl%esi,%edi/*issrcanddstsame?*/jeromInit4如果rom_text_adrs和rominit处相同的话就跳转到rominit4处执行movl$FU

33、NC(end),%ecx/*getendaddr*/subl%edi,%ecx/*getnBytestocopy*/ shrl$2,%ecx/*getnLongstocopy*/cld/*clearthedirectionbit*/rep/*repeatnextinstECXtime*/movsl如果rom_text_adrs和rominit处不相同的话将rom_text_adrs处拷贝至(end-rominit)处romlnit4:进入rominit4处xorl%ebp,%ebpebp清零pushl$0popfl/清标志寄存器pushl%ebxebx进栈movl$FUNC(romStart)

34、,%eax/*jumptoromStart*/call*%eax/跳转到romStart处执下一步。romInitHlt:pushl%eaxcallFUNC(romEaxShow)/调用romEaxShow显示eax寄存器的内容hltjmpromInitHlt死循环,当机/调用romwait等待/*向64h寄存器写入dlh*/.balignl6,0 x90FUNC_LABEL(romA20on)/进入romA20on处:打开a20以扩大寻址范围空间callFUNC(romWait)movl$0 xdl,%eaxoutb%al,$0 x64callFUNC(romWait)movl$0 xdf,

35、%eaxoutb%al,$0 x60callFUNC(romWait)movl$0 xff,%eaxoutb%al,$0 x64callFUNC(romWait)向64h寄存器写入ffh*/调用romwait等待/*EnableA20*/向60h寄存器写入dfh*/调用romwait等待movl$0 x000000,%eax/*Checkifitworked*/movl$0 xl00000,%edxpushl(%eax)pushl(%edx)movl$0 x0,(%eax)movl$0 x0,(%edx)movl$0 x0l234567,(%eax)l3cmpl$0 x01234567,(%e

36、dx)popl(%edx)popl(%eax)jneromA20on0以上代码是检查A20地址线是否打开,就是检查000000h和100000是否相同,即当超过20位时看看会不会和第0位时相同,如果不相同说明打开了A20地址线。否则没打开。尝试别一种方法打开/*anotherwaytoenableA20*/movl$0 x02,%eaxoutb%al,$0 x92/向92H寄存器写入02xorl%ecx,%ecxecx清零romA20onl:接着上面向92H寄存器写入02后inb$0 x92,%alandb$0 x02,%alloopzromA20onl/确保92H为02movl$0 x000

37、000,%eax/*Checkifitworked*/movl$0 xl00000,%edxpushl(%eax)pushl(%edx)movl$0 x0,(%eax)movl$0 x0,(%edx)movl$0 x0l234567,(%eax)cmpl$0 x0l234567,(%edx)popl(%edx)popl(%eax)jneromA20on0movl$0 xdeaddead,%eax/*error,cantenableA20*/ret以上代码是检查A20地址线是否打开,就是检查000000h和l00000是否相同,即当超过20位时看看会不会和第0位时相同,如果不相同说明打开了A20

38、地址线。否则没打开。不再尝试无法打开A20romA20on0:xorl%eax,%eaxret/成功打开A20同进EAX清零.balignl6,0 x90FUNC_LABEL(romLoadGdt)movlSP_ARGl(%esp),%eaxlgdt(%eax)movw$0 x00l0,%ax/*aselector0 xl0is3rdone*/ movw%ax,%dsmovw%ax,%esmovw%ax,%fsmovw%ax,%gsmovw%ax,%ssret把DS,ES,FS,GS,SS寄存器设为0 x0010,即指向GDT的第2项(从0开始),DPL=O。它们都指向一个段。FUNC_LAB

39、EL(romWait)/等待状态xorl%ecx,%ecxecx清零romWait0:movl$0 x64,%edx/*Checkifitisreadytowrite*/inb%dx,%alandb$2,%alloopnzromWait0/确保64h寄存器的值为02ret.balign16,0 x90同上一次FUNC_LABEL(romEaxShow)/显示eax寄存器的内容/*showEAXregisterinyourdisplaydeviceavailable*/retbootlnit.c:romStart()函数romStart()函数的功能romStart()函数包含在bootlnit

40、.c文件中,且用C语言编写。它是系统最先执行的第一个C语言程序,为ROM映像执行必要的代码重定位、解压和RAM初始化操作。其具体操作如下:拷贝适当的ROM映像段到RAM中;清理没有被使用的那部分内存(冷启动时);执行解压操作(如果需要);调用预内核的通用初始化程序usrInit()。romStart()函数相关知识(1)ROM的布局。如图4.2所示。压缩型映像区ROM_BASE_ADRS+ROMSIZEbinArrayEndbinArrayStart图4.2ROM布局非压缩型映像区ROM_TEXT_ADRSROM_BASE_ADRS从上图中可以发现压缩型映像和非压缩型映像处于不同的ROM空间。

41、(2)RAM的布局。如图4.3所示。从图4.3中可以发现用户保留区处于RAM空间的顶端和底部,映像重新定位区位于保留堆栈区的上面。sysPhyMemTop()SYS_MEM_TOP用户保留区冷启动填充为0ROM型映像重新定位区RAM_DST_ADRS保留堆栈区冷启动填充为0用户保留区SYS_MEM_BOTTOMLOCAL_MEM_LOCAL_ADRS图4.3RAM布局3.代码分析(1)代码综述bootrom有三种类型:ROM_RESIDENT、UMCOMPRESS和COMPRESS。第一种是一直运行在rom中的映象,只把data段拷贝到ram里面;第二种是非压缩方式的映象,data段和text

42、段都要拷贝到ram里面,并在ram里面运行;第三种是压缩方式的映象,生成的时候编译器会把除掉romInit.s和bootInit.c之外的目标文件压缩并汇编成一个bootrom.Z.s,最后和romInit.o,bootInit.o,version.o进行链接,生成bootrom映象。所以它也是要全部拷贝到ram中,且必须要进行压缩的工作。而这些工作基本上都是在bootInit.c中进行的。bootInit.c里面主要就是romStart()这个函数,让我们来分析一下它。它的入口参数是startType,是一个启动类型标志,如BOOT_CLEAR、BOOT_NORMAL等,这在后面清内存时会用

43、到。函数一开始定义了一个函数指针变量absEntry,它最后指向的就是ursInit()或compressedEntry()函数。接下来就是对三种bootrom映象类型进行不同的操作,下面我们以arm为例来分别说明。ROM_RESIDENT:它要拷贝的只是data段。直接调用“copyLongs(UINT*)(etext+4),(UINT*)RESIDENT_DATA,(UINT)edata-(UINT)RESIDENT_DATA)/sizeof(long)”来实现。这时系统是运行在rom上的,链接器把所有的函数都定位在rom空间上,所以调用copyLongs时没有计算偏移,而拷贝的目标地址是

44、RESIDENT_DATA对于arm而言RESIDENT_DATA就是sdata,这是在romlnit.s中定义的。通过objdumparm这个工具可以看到sdata定位在RAM_HIGH_ADRS+0 x4这个位置上。而etext+4则是rom上data段的起始地址。这样,完成data段的拷贝。然后如果startType为冷启动,那么清零SYS_MEM_BOTTOM到栈底(RESIDENT_DATA-STACK_SE)以及data段结束之后(edata到SYS_MEM_TOP)的内存空间。然后将函数开始定义的指针absEntry指向usrlnit(在rom中):absEntry=(FUNCP

45、TR)usrlnit;并带上startType跳过去运行:(absEntry)(startType),完成。UMCOMPRESS:一开始它将text段和data段都拷贝到ram中:(FUNCPTR)ROM_OFFSET(copyLongs)(ROM_TEXT_ADRS,(UINT)romInit,ROM_COPY_SIZE/sizeof(long)。这时的ROM_TEXT_ADRS就是代码段在rom上的开始位置,而romInit则是由链接器定位到了RAM_HIGH_ADRS的地址上,所以这时的确是按我们常规的思路拷贝的。并且由于copyLongs函数是定位到ram空间的,所以要计算它在rom上

46、的偏移ROM_OFFSET(copyLongs)。然后象ROM_RESIDENT样,它也要清零栈底(romInit-STACK_SAVE)以下和映象之上(SYS_MEM_TOP-(romInit+ROM_COPY_SIZE)的内存空间。然后将函数开始定义的指针absEntry指向usrlnit(在ram中):absEntry=(FUNCPTR)usrInit;并带上startType跳过去运行:(absEntry)(startType),完成。COMPRESS:开始的时候把从ROM_TEXT_ADRS起始的长度为romInit到binArrayStart的内容拷贝到romInit位置上。注意,

47、由于romInit被链接器定位到RAM_LOW_ADRS的位置上,这时相当于把romInit.o、bootInit.o和version.。的内容拷贝到了RAM_LOW_ADRS上。然后和UMCOMPRESS一样清零栈底(romInit-STACK_SAVE)以下的内存空间,不同之处是它接下来清除binArrayStart之上(SYS_MEM_TOP-binArrayStart)的内存空间:fillLongs(UINT*)binArrayStart,(UINT)SYS_MEM_TOP-(UINT)binArrayStart)/sizeof(long),0)。然后调用解压程序inflate将在ro

48、m上的(binArrayEnd-binArrayStart)之间的内容解压到RAM_DST_ADRS(RAM_HIGH_ADRS)的位置上:binArrayStart(absUncompress)(UCHAR*)ROM_OFFSET(binArrayStart),(UCHAR*)RAM_DST_ADRS,&binArrayEnd-binArrayStart)。这样,解完压后函数compressedEntry()刚好就在RAM_DST_ADRS(RAM_HIGH_ADRS)的位置上,所以接下来将指针absEntry指向它:absEntry=(FUNCPTR)RAM_DST_ADRS。最后带上st

49、artType跳过去运行:(absEntry)(startType),完成。压缩的ROMablelinage的启动标准的bootioni程序A(2)代码分析代码中针对不同类型的ROM程序有不同的copy类型,不同的CPU有不同的地址转换,RAM清零与最后的入口函数也有所不同。具体的代码分析如下:Bootinit.里面主要看romstart这个函数。实现把rom中的内容拷贝到ram中去,同时把把ram其它未用的部分清零,对于压缩的rom在必要时还要进行解压。这段代码由前面的rominit.s跳转到这来的。ROMANDRAMMEMORYLAYOUT,Examplememorylayoutfora1

50、-megabyteboard:0 x00100000=LOCAL_MEM_SIZE=sysMemTop()|RAM|0filled|1=(romInit+ROM_COPY_SIZE)orbinArrayStart|ROMimage|0 x00090000=RAM_HIGH_ADRS|STACK_SAVE|0 x00080000=0.5Megabytes|0filled|1|0 x00001000=RAM_ADRS&RAM_LOW_ADRS1|excvectors,bpanchor,excmsg,bootline|0 x00000000=LOCAL_MEM_LOCAL_ADRS|ROM|0 xf

51、f8xxxxx=binArrayStart|0 xff800008=ROM_TEXT_ADRS0 xff800000=ROM_BASE_ADRS在时入romstart之前先是定义了一些变量SYS_MEM_TOP,SYS_MEM_BOTTOM,BINARRAYEND_ROUNDOFF等等。再接下来就是声明了一些系统函数,再接下来又是定义了romstart相关的定义如:RESIDENT_DATA=RAM_DST_ADRS(mips)/定义体系结构特殊信息=压缩映象最终重定位的地址RESIDENT_DATA=wrs_kernel_data_startRAM_DST_ADRS=RAM_HIGH_ADR

52、S/压缩映象最终重定位的地址=拷贝引导映象的入口地址ROM_TEXT_ADRS=(UINT)romInit)ROM_BASE_ADRS=(UINT)romInit)引导rom的入口地址ROM_COPY_SIZE=(ROM_SIZE-(ROM_TEXT_ADRS-ROM_BASE_ADRS)ROM_OFFSET(adr)=(UINT)adr-(UINT)romInit)+ROM_TEXT_ADRS)/rom-ram时涉及到计算偏移地址函数接着又声明了三个函数拷贝rom-ram函数:copyLongs()往ram填零函数:fillLongs()比较函数:checkLongs()voidromSta

53、rt(FASTintstartType/*启动类形*/它的入口参数是startType,是一个启动类型标志,如BOOT_CLEAR、BOOTNORMAL等,这在后面清内存时会用到。)#if(CPU_FAMILY=SPARC)|(CPU_FAMILY=MIPS)|(CPU_FAMILY=I80X86)|(CPU_FAMILY=PPC)|(CPU_FAMILY=ARM)volatile/*toforceabsoluteadressing*/注释:volatile关键字的作用是使编译器不对被指定的变量做优化,这样可以确保该变量每次被取到新的值。Volatile经常用来修饰全局的或者静态的或者在多任务

54、环境下允许被改变的变量。#endif/*(CPU_FAMILY=SPARC)*/FUNCPTRabsEntry;函数一开始定义了一个函数指针变量absEntry,它最后指向的就是usrlnit()或compressedEntry()函数#if(CPU_FAMILY=ARM)&(!defined(ROM_RESIDENT)&!defined(BOOTCODE_IN_RAM)VOIDFUNCPTRramfillLongs=fillLongs;/*forcecalltoRAM*/#definefillLongs(a,b,c)ramfillLongs(a,b,c)#endif/*(CPU_FAMILY

55、=ARM)*/#if(CPU_FAMILY=MC680X0)&!defined(ROM_RESIDENT)&!defined(BOOTCODE_IN_RAM)volatileVOIDFUNCPTRromcopyLongs=©Longs;/*forcecalltoROM*/#definecopyLongsromcopyLongs#endif/*(CPU_FAMILY=MC680X0)*/*CopyfromROMtoRAM,minusthecompressedimageifcompressedbootROMwhichreliesonbinArrayappearinglastinDATAse

56、gment.*/#ifdefROM_RESIDENT/*IfROMresidentcode,thencopyonlydatasegmentfromROMtoRAM,initializememoryandjumptousrInit.*/#if(CPU_FAMILY=SPARC)copyLongs(UINT*)(etext+8),(UINT*)RESIDENT_DATA,#else/*对于ROM_RESIDENT,则只拷贝数据段到ram。因为系统在ROM中运行,所有函数被定位到ROM空间。所以copyLongs没有计算偏移量。RESIDENT_DATA就是sdata,被LD定位到RAM_HIGH_

57、ADRS。又定义为wrs_kernel_data_start。etext则是ROM上的data起始位置。则直接拷贝ROM上的data数据到RAM上的RAM_HIGH_ADRS.*/copyLongs(UINT*)etext,(UINT*)RESIDENT_DATA/*RAM_HIGH_ADRS*/,#endif(UINT)wrs_kernel_data_end-(UINT)RESIDENT_DATA)/sizeof(long);#else/*ROM_RESIDENT*/#ifdefUNCOMPRESS#if(CPU_FAMILY=MIPS)/*copytexttouncachedlocatio

58、nstoavoidproblemswithcopybackcaches*/(FUNCPTR)ROM_OFFSET(copyLongs)(ROM_TEXT_ADRS,(UINT)K0_TO_K1(romInit),ROM_COPY_SIZE/sizeof(long);#else/*CPU_FAMILY=MIPS*/*对于不是ROM_RESIDENT,并且没有被压缩,则拷贝代码段和数据段到ram.因为系统在RAM中运行,所以copyLongs函数是定位到ram空间的,所以要计算ROM的偏移量。ROM_TEXT_ADRS就是代码段在rom上的开始位置。romlnit则是由链接器定位到了RAM_HIG

59、H_ADRS的地址上。*/(FUNCPTR)ROM_OFFSET(copyLongs)(ROM_TEXT_ADRS,(UINT)romInit,ROM_COPY_SIZE/sizeof(long);#endif/*CPU_FAMILY=MIPS*/#else/*UNCOMPRESS*/#if(CPU_FAMILY=MIPS)/*copytexttouncachedlocationstoavoidproblemswithcopybackcachescopytheentiredatasegmentbecausethereisnowaytoensurethatbinArrayisthelastthi

60、nginthedatasegmentbecauseofGPrelativeaddressing*/(FUNCPTR)ROM_OFFSET(copyLongs)(ROM_TEXT_ADRS,(UINT)K0_TO_K1(romInit),(UINT)wrs_kernel_data_end-(UINT)romInit)/sizeof(long);#else/*CPU_FAMILY=MIPS*/*对于不是ROM_RESIDENT但是被压缩.要分开拷贝。因为系统在RAM中运行,所以copyLongs函数是定位到ram空间的,所以要计算ROM的偏移量。开始的时候把从ROM_TEXT_ADRS起始的长度为

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论