您的位置:首页 > 编程语言

VxWorks启动代码romStart()函数分析

2013-06-14 00:47 288 查看

VxWorks启动代码romStart()函数分析

DanielLee_USTB 2013-6-14

QQ:382899443
好几天没有学习Vxworks了,真的有点悔恨。每每因各种原因止步梦想的跑道,上班的路上还真是充满了羁绊。还好串口服务器以及完成关键性验证,暂时告一段落,继续潜心学习。今天去一个复用器公司了解他们的产品,觉得他们做的很不错,可以看出没有多年积累不可能达到这么高的技术水平。个人也一样,在长跑的路上你偷懒了,慢下来,不想跑了,那么什么都不可能实现,只有坚持做认为对的事儿,才不后悔。

言归正传,开始研究bootInit.c中romStart()这个函数。

当romInit.s执行到LDR pc, L$_rStrtInRom时,就跳转到这个位置去执行:

L$_rStrtInRom:.long ROM_TEXT_ADRS + FUNC(romStart)- FUNC(romInit)

可以看出显然romStart显然定位在了RAM,通过以上运算,计算出其在ROM中的位置,romInit应该对应于romInit.s在RAM中的位置。

VolatileFUNCPTR absEntry;

VOIDFUNCPTR ramfillLongs = fillLongs; /*force call to RAM */

#definefillLongs(a,b,c) ramfillLongs(a,b,c)

这里面定义了一个函数指针ramfillLongs,只是对fillLongs换个名字而已。

暂时不管ROM_RESIDENT类型的镜像,看看UNCOMPRESS类型。

(1) UNCOMPRESS

((FUNCPTR)ROM_OFFSET(copyLongs))(ROM_TEXT_ADRS, (UINT)romInit,

ROM_COPY_SIZE/ sizeof (long));

此时就直接把从ROM_TEXT_ADRS开始的ROM中的整个镜像都拷贝到RAM中romInit的位置,比较容易理解,此时romInit应该定位在了RAM_LOW_ADRS处。

(2) COMPRESS

可以看到主要实现了两段程序的拷贝,第一段是:

((FUNCPTR)ROM_OFFSET(copyLongs))(ROM_TEXT_ADRS, (UINT)romInit,

((UINT)binArrayStart- (UINT)romInit)/ sizeof (long));

这一部分是拷贝bootstrap,也就是romInit.s以及bootInit编译后未经压缩的目标文件,这部分要在RAM中去执行;

第二部分是:

((FUNCPTR)ROM_OFFSET(copyLongs))

((UINT *)((UINT)ROM_TEXT_ADRS + ((UINT)BINARRAYEND_ROUNDOFF -

(UINT)romInit)), (UINT *)BINARRAYEND_ROUNDOFF,

((UINT)wrs_kernel_data_end - (UINT)binArrayEnd) / sizeof (long));

这段程序其实是跳过了压缩的vxworks二进制文件,从二进制的顶端BINARRAYEND_ROUNDOFF把数据段拷贝到了BINARRAYEND_ROUNDOFF在RAM中的位置。如此看来就剩下压缩的vxworks代码段没有解压拷贝了。

(3)清除内存

由于启动类型是coldbooting先不研究ROM_RESIDENT类型镜像,可以看到主要执行了三段程序,第一个是:

fillLongs((UINT *)(SYS_MEM_BOTTOM),

((UINT)romInit - STACK_S***E -(UINT)SYS_MEM_BOTTOM) /

sizeof(long), 0);

这实现了从SYS_MEM_BOTTOM到STACK_S***E之前RAM的清零。

如图灰色部分:

-------------- 0x00100000 = LOCAL_MEM_SIZE = sysMemTop()

| |

| RAM |

| 0 filled |

| |

|------------|= (romInit+ROM_COPY_SIZE) or binArrayStart

| ROM image |

|----------- | 0x00090000 = RAM_HIGH_ADRS = romInit

| STACK_S***E |

|------------|

| | 0x00080000 = 0.5 Megabytes

| |

| |

| 0 filled |

| |

| | 0x00001000 = RAM_ADRS &RAM_LOW_ADRS

| |

| | exc vectors, bp anchor, exc msg, bootline

| |

| |

-------------- 0x00000000 = LOCAL_MEM_LOCAL_ADRS

第二部分是对于非压缩方式UNCOMPRESS,清零了***的一段内存。

#if defined (UNCOMPRESS)

fillLongs((UINT *)((UINT)romInit + ROM_COPY_SIZE),

((UINT)SYS_MEM_TOP - ((UINT)romInit +ROM_COPY_SIZE))

/ sizeof(long), 0);

#else

第三部分是针对压缩方式COMPRESS:

fillLongs((UINT *)wrs_kernel_data_end,

((UINT)SYS_MEM_TOP- (UINT)wrs_kernel_data_end) / sizeof (long), 0);

#endif /*UNCOMPRESS */

清零的是vxworks数据段到SYS_MEM_TOP的RAM区。

(4)执行下一段程序

对于UNCOMPRESS方式,可以直接到absEntry= (FUNCPTR)usrInit;去执行;

对于COMPRESS方式,执行解压程序,把从binArrayStart到binArrayEnd的二进制文件解压出来,放到RAM_DST_ADRS的位置,这时候应该定位到RAM_HIGH_ADRS上。

volatile FUNCPTRabsUncompress = (FUNCPTR) UNCMP_RTN;

if ((absUncompress) ((UCHAR*)ROM_OFFSET(binArrayStart),

(UCHAR *)RAM_DST_ADRS, binArrayEnd- binArrayStart) != OK)

不必担心解压出来的文件过大在RAM里面没地方放,因为有((UINT)SYS_MEM_TOP- ((UINT)romInit这么大的地方可以放解压出来的代码。

absEntry =(FUNCPTR)RAM_DST_ADRS;这时候程序的入口地址就是RAM_HIGH_ADRS。

最后通过(absEntry) (startType)跳转到相应的入口函数,对于COMPRESS方式也应该去执行usrInit函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: