收藏 分销(赏)

VxWorks及BSP启动流程与顺序.doc

上传人:a199****6536 文档编号:1282875 上传时间:2024-04-20 格式:DOC 页数:33 大小:781.51KB 下载积分:12 金币
下载 相关 举报
VxWorks及BSP启动流程与顺序.doc_第1页
第1页 / 共33页
VxWorks及BSP启动流程与顺序.doc_第2页
第2页 / 共33页


点击查看更多>>
资源描述
目 录 1 vxworks映像类型 1 1.1 可加载的映像类型(vxwoks) 1 2 vxworks映像启动顺序 1 2.1 可加载型vxworks映像启动顺序 2 2.2 基于ROM的vxworks映像启动顺序 2 2.3 基于ROM驻留型vxworks映像启动顺序 3 3 BSP基础知识 3 3.1 BSP的定义 3 3.2 BSP的功能 3 3.3 BSP的组成 4 4 BSP的启动 4 4.1 BSP的启动流程 4 4.2.1 romInit.s:romInit()函数 5 4.2.2 bootInit.c:romStart()函数 14 4.2.3 bootConfig.c分析 24 4.2.4 sysLib.s:sysInit()函数 26 4.2.5 usrconfig.c:usrInit()函数 27 4.2.6 usrconfig.c:usrRoot()函数 28 5 总结 31 32 VxWorks及BSP启动流程与顺序 ———李守轩 摘要:本文首先介绍vxworks映像的类型及各类型vxworks映像的启动顺序;然后介绍BSP的启动流程与初始化顺序。 关键词:vxworks映像;BSP启动;代码分析 1 vxworks映像类型 对于vxworks映像的启动情况,从根本上看,在初始化和装载vxworks映像的过程中,处理器所执行的步骤在逻辑上是一样的。对于有些处理器可能需要增加一些额外的步骤,而另一些处理器可能会省略掉某些步骤。 当构造vxworks映像时,根据需要可以构造不同类型的映像,系统把这些映像划分成以下三种类型。 1.1 可加载的映像类型(vxwoks) 可加载型映像的执行需要通过引导代码把它装载到目标机RAM中,然后才开始执行。而引导代码分为两种: (1) 引导代码固化在ROM或FLASH中; (2) 引导代码是一个独立的vxworks应用; 引导代码通常也是一种vxworks映像,也被称为引导映像。它的作用就是把包含应用的vxworks映像装入到RAM中。引导映像可能在ROM/FLASH中执行,也可能在RAM中执行。 1.2 基于ROM的映像类型(vxworks_Rom & vxwoks_RomCompress) 基于ROM的vxworks映像在执行前首先把自己从ROM/FLASH中装载到RAM中,这种类型的映像通常在启动阶段较慢,但在执行阶段比ROM驻留型要快。 1.3 基于ROM驻留映像类型(vxwoks_RomResident) ROM驻留型映像在启动时把数据段拷贝到目标机RAM中,这种类型的映像在启动阶段比较快,当RAM空间比较小的时候通常使用它。在嵌入式应用中通常会使用该类型的映像,然而,它在目标机上执行的速度要比其他类型要慢,原因是CPU访问ROM比访问RAM要慢。 2 vxworks映像启动顺序 在目标机加电启动时发生的顺序启动事件是一个典型vxworks映像需要执行的功能。所有类型的vxworks映像在初始化阶段启动顺序是一样的,处理器通过“jump”跳转指令跳转到ROM或Flash中引导带代码入口处,这段引导代码所要执行的操作包括: (1) 关中断; (2) 初始化目标机内存; (3) 装载适当的vxworks映像段; (4) 跳转到设置目标机为静止状态的代码处。 不同类型的vxworks映像启动顺序略有不同,下面介绍vxworks映像的启动顺序。 2.1 可加载型vxworks映像启动顺序 可加载型vxworks映像引导的详细过程如下: (1)数据段和代码段的装入。系统加电后执行引导带代码,首先把引导代码的代码段和数据段从ROM或Flash里装入RAM中。此时需要考虑下列情况: ● 压缩型引导代码,这种类型的引导代码在拷贝时,需要对它进行解压缩; ● 非压缩型引导代码,这种类型的引导代码直接进行拷贝即可; ● 驻留型引导代码,这种类型的引导代码在拷贝时,仅仅拷贝它的数据段。 (2)vxworks映像的装入。引导代码执行后,把vxworks映像装入到RAM中,然后跳转到vxworks映像装入点。 (3)系统初始化。执行静态链接在vxworks映像里的系统初始化代码,最终完成系统初始化操作。 2.2 基于ROM的vxworks映像启动顺序 基于ROM的vxworks映像启动详细过程如下: (1)VxWorks映像的装入。系统加电后执行引导带代码,首先把VxWorks映像的代码段和数据段从ROM或Flash里装入RAM中。此时需要考虑下列情况: ● 压缩型VxWorks映像,这种类型的VxWorks映像在拷贝时,需要对它进行解压操作; ● 非压缩型VxWorks映像,这种类型的VxWorks映像直接进行拷贝操作; (2)控制权转移。VxWorks映像被装入后,系统控制权转移给RAM中的vxworks映像的初始化代码。 (3)系统初始化。执行静态链接在vxworks映像里的系统初始化代码,最终完成系统初始化操作。 2.3 基于ROM驻留型vxworks映像启动顺序 基于ROM驻留型的vxworks映像启动详细过程如下: (1)VxWorks映像数据段的装入。系统加电后执行引导带代码,首先把VxWorks映像的数据段从ROM或Flash里装入RAM中。 (2)控制权转移。VxWorks映像数据段被装入后,系统控制权转移给ROM或Flash中的vxworks映像的初始化代码。 (3)系统初始化。执行ROM或Flash中的静态链接在vxworks映像里的系统初始化代码,最终完成系统初始化操作。 3 BSP基础知识 BSP是VxWorks的一个重要组成部分,在目标机加电后,首先执行的代码就是BSP,可以说VxWorks的启动流程就是BSP的启动流程。 3.1 BSP的定义 BSP(board support package)即板级支持包,是介于底层硬件环境和VxWorks之间的一个软件接口。 3.2 BSP的功能 BSP主要功能是系统加电后初始化目标机硬件、初始化操作系统及提供部分硬件的驱动程序。具体如下。 (1)初始化。 ● CPU初始化。初始化CPU内部寄存器。 ● 目标机初始化。初始化控制芯片的寄存器,为整个软件系统提供底层硬件环境的支持。 ● 系统资源初始化。为操作系统及系统的正常运行做准备,进行资源初始化。 (2)使VxWorks能够访问硬件驱动程序。主要是指BSP包含部分必要的设备驱动程序和相关设备的初始化操作。 (3)在VxWorks系统中,集成了与硬件相关的软件和部分硬件无关的软件。 3.3 BSP的组成 开发板上电后首先跑的就是BSP的代码,BSP主要由源文件、头文件、派生文件、Makefile文件组成。BSP包含的具体文件请参考相关资料。BSP在Tornado安装目录中的位置如图3.1中所示。 4 BSP的启动 下面首先给出BSP的启动流程,然后对启动过程执行的函数进行具体分析,这是本文的重点和难点,是建立在作者自己理解角度和深度基础之上的。 4.1 BSP的启动流程 BSP的启动流程如图3.2所示,从代码执行的角度描述了BSP的启动过程及启动过程中先后调用函数的功能。 4.2 BSP的启动过程分析 从BSP的启动流程图中可以看出BSP启动过程中先后执行的函数,上面对这些函数进行详细描述。 4.2.1 romInit.s:romInit()函数 1. romInit()函数的功能 romInit()函数与包含在romInit.s文件中,且用汇编语言编写。它是系统加电后首先执行的代码,也是所有从ROM/FLASH启动的VxWorks映像的入口点。它执行目标机最小的初始化操作及调用romStart()函数,其它硬件初始化操作推迟到sysHwInit()函数中进行。romInit()函数必须包含下列功能:(1)屏蔽处理器中断及处理器复位;(2)初始化内存系统;(3)初始化堆栈指针和其它寄存器,开始执行romStart()函数及传递启动类型。 2. 冷启动与热启动 (1)冷启动。所谓冷启动是指硬件环境通过加电启动。在romInit()函数中需要保存系统启动类型,启动类型的宏定义为BOOT_COLD。 (2)热启动。所谓热启动是通过调用reboot()、Ctrl+X或异常中断重新启动目标机系统。实际上这些操作是把控制权传递给ROM中的监控函数——sysToMonitor(),这个函数包含在sysLib.c文件中,如执行sysToMonitor(2),则系统执行热启动。 3. 代码分析 (1)X86硬件相关知识 ● IDT是中断描述表,是由门描述符组成的一个数组,每个门描述符对应一个中断/ 异常向量,其可以保存在内存中的任何位置,CPU通过访问IDTR寄存器获取IDT的位置。IDTR寄存器的长度为48位,其中包括保存IDT的32位线性地址和16位的大小。对于IDTR寄存器的操作包括两个指令:一个是LIDT,另一个是SIDT。LIDT用来将指定IDT所在线性地址和其长度装入LDTR寄存器;而SIDT则是将IDTR寄存器的内容读出。 ● 从实模式切换到保护模式之前,必须将基址和限长的值用指令LGDT装入GDTR,一旦系统切换到保护模式,则表所在的物理地址就不再改变,同时立即启用全局描述表,IDT表的基址用指令IDTR。 ● 32位控制器CR0的0位为保护允许位PE(protected enable),用于启动保护模式,pe=1,保护模式启动;pe=0,实模式下运行。 ● 实模式进入保护模式的步骤:初始化段描述符—准备并加载GDTR—打开地址线A20—设置CR0寄存器,进入保护模式—跳转32位代码段。 ● A20地址线的激活请查阅相关资料。 上述相关知识是作者在理解代码过程中了解的,当然与硬件相关的知识很多,详细请查阅相关资料。 (3) 代码分析 从作者理解的角度给出了romInit()函数的流程图,如图4.1所示。具体的代码分下如下: 包含C的4个头文件。 vxWorks.h为系统头文件 sysLib.h为系统提供给BSP的头文件 config.h是BSP的头文件 Asm.h是系统头号文件 开始数据段。以下内容出现在数据段里: .globl copyright_wind_river .long copyright_wind_river /* the first in .data */ .globl romwait .globl _romInit .globl _sdata 等等 申明全局变量_romInit和_sdata等 定义一个以0结尾的字符串”start of data”。这个串出现在数据段的第一个无名变量之后 .text .align 16 .text开始代码段,以下内容出现在代码段里。 .align 16使对齐编译器进行填充,使得下一条指令出现在能被16整除的地址上。对齐可使CPU取指令快一点。 进入rominit处: Cli关中断 jmp cold 跳转到cold处。这是段内相对跳转。 balign 16 在32-bit代码前加这样的前缀可以让它变为16-bit代码;在16-bit代码前可以变为32-bit代码 进入romWarmHigh处: Cli关中断 movl SP_ARG1(%esp),%ebx 把esp+ SP_ARG1偏移处的值赋予ebx寄存器 jmp warm 跳转到warm处。这是段内相对跳转. balign 16 在32-bit代码前加这样的前缀可以让它变为16-bit代码;在16-bit代码前可以变为32-bit代码 进入romWarm Low处: cli 关中断 cld 清方向标志 movl $ RAM_LOW_ADRS,%esi /* 把RAM_LOW_ADRS 地址赋给esi movl $ ROM_TEXT_ADRS,%edi /*把RAM_LOW_ADRS 地址赋给edi movl $ ROM_SIZE,%ecx /*把RAM_size 地址赋给ecx shrl $2,%ecx /* ecx 右移两位256字节变成64个双字 rep movsl 循环执行esi->edi 真到ecx==0 movl SP_ARG1(%esp),%ebx 把esp+ SP_ARG1偏移处的值赋予ebx寄存器 jmp warm /* jump to warm */ .ascii "Copyright 1984-2002 Wind River Systems, Inc." .balign 16,0x90 cold: //cold处 .byte 0x67, 0x66 与blign16功能相同 lidt %cs:(romIdtr - romInit) 将中断和量表加载到cs:(romIdtr - romInit)处 .byte 0x67, 0x66 与blign16功能相同 lgdt %cs:(romGdtr - romInit) 将断描述表加载到cs:( romGdtr - romInit)处 mov %cr0,%eax /* move CR0 to EAX */ .byte 0x66 /* next inst has 32bit operand */ or $0x00000001,%eax /* set the PE bit */ mov %eax,%cr0 /* move EAX to CR0 */ //以上代码的作用是将控制寄存器 cr0的PE位 置1 jmp romInit1 /*跳转到rominit1处。 Rominit1:进入rominit1处 .byte 0x66 /* next inst has 32bit operand */ mov $0x0010,%eax /* set data segment 0x10 is 3rd one */ mov %ax,%ds /* set DS */ mov %ax,%es /* set ES */ mov %ax,%fs /* set FS */ mov %ax,%gs /* set GS */ mov %ax,%ss /* set SS */ .byte 0x66 /* next inst has 32bit operand */ mov $ ROM_STACK,%esp /* set lower mem stack pointer */ .byte 0x67, 0x66 /* next inst has 32bit operand */ ljmp $0x08, $ ROM_TEXT_ADRS + romInit2 - romInit 现在已进入保护模式。然而各个段寄存器的值,以及它们的高速缓存寄存器中的值还是实模式下的。把DS, ES, FS, GS, SS寄存器设为0x0010,即指向GDT的第2项(从0开始),DPL=0。它们都指向一个段。把堆栈指针esp设为ROM_STACK,由于CS还是以前的值,意味着目前代码段的属性还是16-bit代码。所以使用指令前缀以执行32-bit代码。执行一个远程段间跳转修改CS。CS的新值为0x08,即GDT的第1项,DPL=0。修改CS时它的高速缓存寄存器也会自动更新。 romIDT(Interrupt Description Table),中断描述符表,空的。 romGdtr: .word 0x0027 .long ROM_TEXT_ADRS + ROM_GDT //设置段描述表的大小及基地址 balign 16,0x90 romGdt: 段描述表 /* 0(selector=0x0000): Null descriptor */ .word 0x0000 .word 0x0000 .byte 0x00 .byte 0x00 .byte 0x00 .byte 0x00 /* 1(selector=0x0008): Code descriptor */ .word 0xffff /* limit: xffff */段界限低16位 .word 0x0000 /* base : xxxx0000 */ 基地址低16位 .byte 0x00 /* base : xx00xxxx */基地址中间8位 .byte 0x9a //段属性 .byte 0xcf //段属性 含段界限高4位 .byte 0x00 /* base : 基地址高8位 /* 2(selector=0x0010): Data descriptor */ .word 0xffff /* limit: xffff */ .word 0x0000 /* base : xxxx0000 */ .byte 0x00 /* base : xx00xxxx */ .byte 0x92 /* Data r/w, Present, DPL0 */ .byte 0xcf /* limit: fxxxx, Page Gra, 32bit */ .byte 0x00 /* base : 00xxxxxx */ /* 3(selector=0x0018): Code descriptor, for the nesting interrupt */ .word 0xffff /* limit: xffff */ .word 0x0000 /* base : xxxx0000 */ .byte 0x00 /* base : xx00xxxx */ .byte 0x9a /* Code e/r, Present, DPL0 */ .byte 0xcf /* limit: fxxxx, Page Gra, 32bit */ .byte 0x00 /* base : 00xxxxxx */ /* 4(selector=0x0020): Code descriptor, for the nesting interrupt */ .word 0xffff /* limit: xffff */ .word 0x0000 /* base : xxxx0000 */ .byte 0x00 /* base : xx00xxxx */ .byte 0x9a /* Code e/r, Present, DPL0 */ .byte 0xcf /* limit: fxxxx, Page Gra, 32bit */ .byte 0x00 /* base : 00xxxxxx */ .balign 16,0x90 romInit2://进入rominit2处 cli 关中断 movl $ ROM_STACK,%esp 设置esp成rom_stack 0x8000h #if defined (TGT_CPU) && defined (SYMMETRIC_IO_MODE) movl $ MP_N_CPU, %eax lock incl (%eax) #endif 定义 TGT_CPU 和SYMMETRIC_IO_MODE #ifdef INCLUDE_WINDML /* WindML + VesaBIOS initialization */ Movl $ VESA_BIOS_DATA_PREFIX,%ebx /* move BIOS prefix addr to EBX */ movl $ VESA_BIOS_KEY_1,(%ebx) /* store "BIOS" */ addl $4, %ebx /* increment EBX */ movl $ VESA_BIOS_KEY_2,(%ebx) /* store "DATA" */ movl $ VESA_BIOS_DATA_SIZE,%ecx /* load ECX with nBytes to copy */ shrl $2,%ecx /* get nLongs to copy */ movl $0,%esi /* load ESI with source addr */ movl $ VESA_BIOS_DATA_ADDRESS,%edi /* load EDI with dest addr */ rep movsl /* copy BIOS data to VRAM */ #endif /* INCLUDE_WINDML */ */定义INCLUDE_WINDML 并初始化VesaBIOS #ifndef INCLUDE_IACSFL call FUNC(romA20on) /* enable A20 */ cmpl $0, %eax /* is A20 enabled? */ jne romInitHlt /* no: jump romInitHlt */ #endif 定义 INCLUDE_IACSFL warm://进入warm处 ARCH_REGS_INIT /* 初始化 DR[0-7] 标志位寄存器 */ #if (CPU == PENTIUM) || (CPU == PENTIUM2) || (CPU == PENTIUM3) || \ (CPU == PENTIUM4) xorl %eax, %eax /* zero EAX */ movl %eax, %cr4 #endif 如果是奔腾系列初将cr4清零 movl $romGdtr,%eax 加载前面的romGdt表 subl $ FUNC(romInit),%eax addl $ ROM_TEXT_ADRS,%eax pushl %eax call FUNC(romLoadGdt) movl $ STACK_ADRS, %esp /* initialise the stack pointer */ movl $ ROM_TEXT_ADRS, %esi /* get src addr(ROM_TEXT_ADRS) movl $ romInit, %edi /* get dst addr(romInit) */ cmpl %esi, %edi /* is src and dst same? */ je romInit4 如果rom_text_adrs和rominit处相同的话就跳转到 rominit4处执行 movl $ FUNC(end), %ecx /* get "end" addr */ subl %edi, %ecx /* get nBytes to copy */ shrl $2, %ecx /* get nLongs to copy */ cld /* clear the direction bit */ rep /* repeat next inst ECX time */ movsl 如果rom_text_adrs和rominit处不相同的话 将rom_text_adrs处拷贝至(end-rominit)处 romInit4:进入rominit4处 xorl %ebp, %ebp ebp清零 pushl $0 popfl //清标志寄存器 pushl %ebx ebx进栈 movl $ FUNC(romStart),%eax /* jump to romStart */ call *%eax //跳转到romStart处执下一步。 romInitHlt: pushl %eax call FUNC(romEaxShow) //调用romEaxShow显示eax寄存器的内容 hlt jmp romInitHlt 死循环,当机 .balign 16,0x90 FUNC_LABEL(romA20on) //进入romA20on处:打开a20以扩大寻址范围空间 call FUNC(romWait) //调用romwait等待 movl $0xd1,%eax /* 向64h寄存器写入 d1h*/ outb %al,$0x64 call FUNC(romWait) movl $0xdf,%eax /* Enable A20 */ outb %al,$0x60 向60h寄存器写入 dfh*/ call FUNC(romWait) 调用romwait等待 movl $0xff,%eax 向64h寄存器写入 ffh*/ outb %al,$0x64 call FUNC(romWait) 调用romwait等待 movl $0x000000,%eax /* Check if it worked */ movl $0x100000,%edx pushl (%eax) pushl (%edx) movl $0x0,(%eax) movl $0x0,(%edx) movl $0x01234567,(%eax) cmpl $0x01234567,(%edx) popl (%edx) popl (%eax) jne romA20on0 以上代码是检查A20地址线是否打开,就是检查000000h和100000是否相同,即当超过20位时看看会不会和第0位时相同,如果不相同说明打开了A20地址线。否则没打开。尝试别一种方法打开 /* another way to enable A20 */ movl $0x02,%eax outb %al,$0x92 //向92H寄存器写入02 xorl %ecx,%ecx ecx清零 romA20on1://接着上面向92H寄存器写入02后 inb $0x92,%al andb $0x02,%al loopz romA20on1 //确保92H为02 movl $0x000000,%eax /* Check if it worked */ movl $0x100000,%edx pushl (%eax) pushl (%edx) movl $0x0,(%eax) movl $0x0,(%edx) movl $0x01234567,(%eax) cmpl $0x01234567,(%edx) popl (%edx) popl (%eax) jne romA20on0 movl $ 0xdeaddead,%eax /* error, can't enable A20 */ ret 以上代码是检查A20地址线是否打开,就是检查000000h和100000是否相同,即当超过20位时看看会不会和第0位时相同,如果不相同说明打开了A20地址线。否则没打开。不再尝试 无法打开A20 romA20on0: xorl %eax,%eax ret //成功打开A20同进EAX清零 .balign 16,0x90 FUNC_LABEL(romLoadGdt) movl SP_ARG1(%esp),%eax lgdt (%eax) movw $0x0010,%ax /* a selector 0x10 is 3rd one */ movw %ax,%ds movw %ax,%es movw %ax,%fs movw %ax,%gs movw %ax,%ss ret 把DS, ES, FS, GS, SS寄存器设为0x0010,即指向GDT的第2项(从0开始),DPL=0。它们都指向一个段。 FUNC_LABEL(romWait) //等待状态 xorl %ecx,%ecx ecx清零 romWait0: movl $0x64,%edx /* Check if it is ready to write */ inb %dx,%al andb $2,%al loopnz romWait0 //确保64h寄存器的值为02 ret .balign 16,0x90 同上一次 FUNC_LABEL(romEaxShow) //显示eax寄存器的内容 /* show EAX register in your display device available */ ret 4.2.2 bootInit.c:romStart()函数 1. romStart()函数的功能 romStart()函数包含在bootInit.c文件中,且用C语言编写。它是系统最先执行的第一个C语言程序,为ROM映像执行必要的代码重定位、解压和RAM初始化操作。其具体操作如下: (1) 拷贝适当的ROM映像段到RAM中; (2) 清理没有被使用的那部分内存(冷启动时); (3) 执行解压操作(如果需要); (4) 调用预内核的通用初始化程序——usrInit()。 2. romStart()函数相关知识 (1) ROM的布局。如图4.2所示。 从上图中可以发现压缩型映像和非压缩型映像处于不同的ROM空间。 (2) RAM的布局。如图4.3所示。 从图4.3中可以发现用户保留区处于RAM空间的顶端和底部,映像重新定位区位于保留堆栈区的上面。 3. 代码分析 (1) 代码综述 bootrom有三种类型:ROM_RESIDENT、UMCOMPRESS和COMPRESS。第一种是一直运行在rom中的映象,只把data段拷贝到ram里面;第二种是非压缩方式的映象,data段和text段都要拷贝到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等,这在后面清内存时会用到。函数一开始定义了一个函数指针变量absEntry,它最后指向的就是ursInit()或compressedEntry()函数。接下来就是对三种bootrom映象类型进行不同的操作,下面我们以arm为例来分别说明。 1.ROM_RESIDENT:它要拷贝的只是data段。直接调用“ copyLongs ((UINT *)(etext + 4), (UINT *) RESIDENT_DATA, ((UINT) edata - (UINT) RESIDENT_DATA) / sizeof (long));”来实现。这时系统是运行在rom上的,链接器把所有的函数都定位在rom空间上,所以调用copyLongs时没有计算偏移,而拷贝的目标地址是RESIDENT_DATA,对于arm而言RESIDENT_DATA就是sdata,这是在romInit.s中定义的。通过objdumparm这个工具可以看到sdata定位在RAM_HIGH_ADRS+0x4这个位置上。而etext + 4则是rom上data段的起始地址。这样,完成data段的拷贝。然后如果startType为冷启动,那么清零SYS_MEM_BOTTOM到栈底(RESIDENT_DATA - STACK_SAVE)以及data段结束之后(edata到SYS_MEM_TOP)的内存空间。然后将函数开始定义的指针absEntry指向usrInit(在rom中):absEntry = (FUNCPTR)usrInit;并带上startType跳过去运行:(absEntry)(startType),完成。 2.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上的偏移ROM_OFFSET(copyLongs)。然后象ROM_RESIDENT一样,它也要清零栈底(romInit - STACK_SAVE)以下和映象之上(SYS_MEM_TOP - (romInit + ROM_COPY_SIZE))的内存空间。然后将函数开始定义的指针absEntry指向usrInit(在ram中):absEntry = (FUNCPTR)usrInit;并带上startType跳过去运行:(absEntry)(startType),完成。 3.COMPRESS:开始的时候把从ROM_TEXT_ADRS起始的长度为romInit到binArrayStart的内容拷贝到romInit位置上。注意,由于romInit被链接器定位到RAM_LOW_ADRS的位置上,这时相当于把romInit.o、bootInit.o和version.o的内容拷贝到了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将在rom上的(binArrayEnd - binArrayStart)之间的内容解压到RAM_DST_ADRS(RAM_HIGH_ADRS)的位置上:binArrayStart(absUncompress) ((UCHAR *)ROM_OFFSET(binArrayStart),(UCHAR *)R
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服