好几天没有学习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_SAVE -(UINT)SYS_MEM_BOTTOM) /
sizeof(long), 0);
这实现了从SYS_MEM_BOTTOM到STACK_SAVE之前RAM的清零。
如图灰色部分:
-------------- 0x00100000 = LOCAL_MEM_SIZE = sysMemTop()
| |
| RAM |
| 0 filled |
| |
|------------|= (romInit+ROM_COPY_SIZE) or binArrayStart
| ROM image |
|----------- | 0x00090000 = RAM_HIGH_ADRS = romInit
| STACK_SAVE |
|------------|
| | 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函数。