Chinaunix首页 | 论坛 | 博客
  • 博客访问: 451347
  • 博文数量: 150
  • 博客积分: 2706
  • 博客等级: 少校
  • 技术积分: 1200
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-09 11:41
文章分类

全部博文(150)

文章存档

2012年(7)

2011年(6)

2010年(68)

2009年(69)

我的朋友

分类:

2010-02-06 14:18:56

再谈WIN CE 6.0 的启动过程 (1) -----估计会比较罗嗦 ^ ^
2009-09-10 17:11

再谈WIN CE 6.0 的启动过程                

                                           之                加载OS镜像                                   BY guly699

一般说来 基于 Windows CE 的嵌入式系统上电或者复位后运行的第一条指令是在Startup.s中的代码。。。。。额,貌似都知道了哈,不过没事这是写给俺看的。。嘿嘿。

Startup函数使用汇编语言写的,这个函数的功能是对目标系统的嵌入式CPU执行最基本的初始化,主要是为CPU准备一个合适的运行环境,如:关中断、清空TBL。。。。。。顺便说一下在WIN CE中还有一个函数是用来初始化硬件的:OEMPlatformInit函数---------它的功能是对目标平台进行初始化(Startup函数主要是用来初始化嵌入式CPU)。

在Startup函数执行的最后会有这样一条语句:    b EbootMain

就是说现在程序跳转到 EbootMain() 这一函数,它是在main.c中的,具体代码如下:

void EbootMain(void)
{
    BootloaderMain();
    SpinForever();      //这个函数是用来输出信息的,属于无限循环,非重点。
}

从上面很容易看书程序会到 BootloaderMain() 这一函数中运行,具体代码如下:

void BootloaderMain (void)
{
    ROMHDR *pRomHdr = NULL; // pTOC for NK image. MUST COPY IT OR CLEANBOOT may erase it
    DWORD dwAction, dwpToc;  
    DWORD dwImageStart = 0, dwImageLength = 0;
    DWORD dwLaunchAddr = 0;

    // relocate globals to RAM
    if (!KernelRelocate (pTOC)) {
        // spin forever
        SPIN_FOREVER;
    }

    // (1) Init debug support. We can use OEMWriteDebugString afterward.
    if (!OEMDebugInit ()) {
        // spin forever
        SPIN_FOREVER;
    }

    // output banner
    EdbgOutputDebugString (NKSignon, CURRENT_VERSION_MAJOR, CURRENT_VERSION_MINOR);

    // (3) initialize platform (clock, drivers, transports, etc)
    if (!OEMPlatformInit ()) {
        // spin forever
        SPIN_FOREVER;
    }

    // system ready, preparing for download
    EdbgOutputDebugString ("System ready!\r\nPreparing for download...\r\n");

    // (4) call OEM specific pre-download function
    switch (dwAction = OEMPreDownload ()) {
    case BL_DOWNLOAD:
        // (5) download image
        if (!DownloadImage (&dwImageStart, &dwImageLength, &dwLaunchAddr)) {
            SPIN_FOREVER;
        }
        // Check for pTOC signature ("CECE") here, after image in place
        if (*(LPDWORD) OEMMapMemAddr (dwImageStart, dwImageStart + PTOC_SIG_OFFSET) == PTOC_SIG)
        {
            EdbgOutputDebugString("Found pTOC signature.\n");
            dwpToc = *(LPDWORD) OEMMapMemAddr (dwImageStart, dwImageStart + PTOC_OFFSET);
            //
            // need to map the content again since the pointer is going to be in a fixup address
            ///
            dwpToc = (DWORD) OEMMapMemAddr (dwImageStart, dwpToc);


            //
            // NOTE: MUST COPY or a CLEAN_BOOT flag will erase it
            //
            memcpy (pRomHdr = &romhdr, (LPVOID) dwpToc, sizeof(ROMHDR));

            EdbgOutputDebugString("ROMHDR at Address %Xh\r\n", dwImageStart + PTOC_SIG_OFFSET + sizeof (DWORD)); // right after signature
            EdbgOutputDebugString("RomHdr.ulRAMStart=%Xh RomHdr.physfirst=%Xh.\r\n", romhdr.ulRAMStart, romhdr.physfirst);

        }
        else
        {
            EdbgOutputDebugString("! Did not Find Windows CE pTOC signature.!\n");
            //
            // In my image the rom header is not used anyway.
            //
            EdbgOutputDebugString("INFO: Jumping to image at 0x%X...\r\n", dwLaunchAddr);
            bEthLaunch =FALSE;

        }


        // fall through
    case BL_JUMP:
        // (5) final call to launch the image. never returned
        OEMLaunch (dwImageStart, dwImageLength, dwLaunchAddr, pRomHdr);
        // should never return
        // fall through
    default:
        // ERROR! spin forever
        SPIN_FOREVER;
    }
}

这个函数在我看来是比较重要的,这里就简单介绍一下好了,毕竟这次的笔记主要是讲启动流程的,我们只要知道系统运行到这里调用这个函数就可以了 ^ ^ ..............

1. KernelRelocate() 函数的功能是将BootLoader的全局变量重定位到RAM的程序内存区域中去,   

     在WindowsCE的OAL模块中还会被调用一次,这最后一次执行的功能是将Windows CE操作系统的全局

     变量重定位到RAM的程序内存区域。具体为什么要这么做。。有空的时候小菜研究下再看看哈。。。。;

2. OEMDebugInit() 函数负责为BootLoader 初始化 调试功能端口,这个函数是最早被 BootLoaderMain

    函数调用的OEM函数,在它被调用运行以后 BootLoader 的代码才可以调用它的调试输出功能函数,

    如OEMWriteDebugString()等;

3. OEMPlatformInit () 这个函数可以说是BootLoader 的最重要的OEM函数,所有与BootLoader所需硬

    件功能有关的目标平台板级外设都在这里进行初始化,也可以初始化嵌入式CPU芯片内置的外设。

4. OEMPreDownload() 函数的功能定位比较灵活,凡是在硬件初始化完成以后、开始下载操作系统镜像

     之前所需要处理的事项都可以在这里进行。有一种说法是这样的:本函数在下载镜像之前被调用,它的

     功能在一定程度上可以由OEM 用户根据实际需要自己定义,最典型的是通过调试串口向用户输出菜单

     选项然后接收用户的响应输入。

5. DownloadImage() 函数的功能是下载并且解包windows CE 的操作系统镜像文件。

6. OEMMapMemAddr() 当BootLoader下载的操作系统镜像自身记录的目的存储位置是Flash存储器时,

     该函数负责将它以重定向的方式暂存到一块RAM内存缓冲区中,待镜像数据下载全部完成以后再一起写

    入Flash存储器中。

7. OEMLaunch() 该函数是最后一个被BootLoaderMain 调用的OEM函数,它负责从BootLoader跳转到下

      载所得的或者从本地存储器加载的操作系统镜像中运行。

----------------------------------------------------------------------------------------------------

通过OEMLaunch() 函数,就像程序的执行流从BootLoader转移到Windows CE的操作系统了。。。。。。。

就先到这,写的比较乱。。。。。。。。。。。

总的来说是这样的:

Startup.s 中通过 B BootMain 语句跳转到void EbootMain(void) 函数;

void EbootMain(void) 函数中主要是调用 BootloaderMain( ) 函数;

BootloaderMain( )函数调用static BOOL KernelRelocate (ROMHDR *const pTOC) 然后调用BOOL OEMDebugInit(void)函数、BOOL OEMPlatformInit(void)函数,然后根据 OEMPreDownload ()的返回值来决定是否下载镜像

执行完以上又跳回BootloaderMain( ) 函数

第二次执行以下流程:BootloaderMain( )函数调用static BOOL KernelRelocate (ROMHDR *const pTOC) 然后调用BOOL OEMDebugInit(void)函数、BOOL OEMPlatformInit(void)函数,然后根据 OEMPreDownload ()的返回值来决定是否下载镜像

不明白的是这里为什么要执行两次,是不是把镜像下载到RAM中后转到RAM中重新运行在RAM中的StartUp 函数。

                                                                                              原创:    

阅读(3296) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~