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

 好几天没有学习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函数。

你可能感兴趣的:(VxWorks启动代码romStart()函数分析)