首页 » 技术文章 » WinCE启动失败原因与解决办法

WinCE启动失败原因与解决办法

作者:  时间:2011-03-30 21:58  来源:EDN

  BootLoader初始化硬件失败

  BootLoader第一个功能是要实现板级和片级初始化硬件,主要是把CPU初始化到一已知状态。在BootLoader目录下,会发现一些.s文件,可能会是init.s或者是reset.s等,这样的文件是CPU加电后最先执行的代码。StartUp 函数是BootLoader的入口函数。该函数一般是使用汇编语言编写,与CPU关系非常紧密,能完成初始化CPU、内存等核心硬件。然后,BootLoader在平台初始化完毕后就可以在不用人工干预的情况下自动加载WinCE内核了。但如果BootLoader在初始化硬件时失败,就会直接导致系统的启动失败了。

  BootLoader加载内核时失败

  一般在平台调试完毕后,BootLoader就会加载WinCE内核映像,这也是BootLoader的功能之一。WinCE内核映像文件通常叫做nk.bin,它是Windows CE二进制数据格式文件,不仅包含了有效的程序代码,还有按照一定规则加入的控制信息。

  在系统启动时BootLoader可以通过两种不同的方式来加载WinCE内核文件nk.bin。一种是下载模式,另一种是本地启动模式。本地启动模式也称为自主模式,即 BootLoader 从目标机上的某个固态存储设备上将操作系统加载到 RAM 中运行,整个过程并没有用户的介入。而下载模式则是目标机上的 BootLoader 将通过串口连接或网络连接等通信手段从主机(Host)下载文件。当BootLoader正确的把nk.bin解压到RAM后,就会把CPU控制权交给CE内核。因此,如果Boot Loader处理不当,就可能会造成加载和解压nk.bin文件的失败,这样自然也就会造成系统启动的失败了。

  (2)OAL导致的启动失败

  OAL(OEM Adaptation Layer)是指OEM 适配层,它是位于Windows CE内核和硬件之间的一层适配层,是OAL各个模块代码被编译后(.lib)和其它内核库链接到一起形成Windows CE的内核可执行文档NK.EXEOAL包括了和系统硬件通讯的最底层代码,内核是通过OAL跟硬件进行交互。逻辑上,OAL是介于CE内核和设备硬件之间的一个代码层,是一个抽象的概念。物理上,OAL和其它一些库一起链接成可执行文件。

  与以前的Win CE旧版本不同的是,在Win CE 6.0中内核(Kenerl)OEM代码被分成oal.exekernel.dllkitl.dll三个部分,其中启动代码(startup) OAL层的实现部分不再与内核链接生成NK.exe,取而代之的是启动代码(startup)和硬件相关且独立于内核的OAL层的实现部分编译成 oal.exe;而与内核相关且独立于硬件的OAL层代码包含在kernel.dll中,内核无关传输层(KITL)的支持代码从OAL层分离出来编译成 kitl.dll。因此,WinCE6.0的启动只与oal.exekernel.dll有关。至于kitl.dll,只有将操作系统编译成具有 KITL功能时才用到。这样做的好处是可以单独升级OAL,但整体的OAL结构并没有改变。

  OAL初始化硬件时失败

  oal.exe是通过Startup函数来完成硬件的初始化。一般来说,OAL的启动代码(Startup.s)与该硬件平台的Bootloader的启动代码(Startup.s)是可以共享的。例如,其中PreInit 函数主要完成将ARM处理器工作模式切换到管理员模式,同时关闭MMU,并检测系统启动原因。如果是热启动,即在该函数调用之前已经启动过 Bootloader的启动代码(Startup.s),相当基本硬件初始化已经完成,则可直接跳转到OALStartUp函数中;否则需要进行硬件中断屏蔽、内存、系统时钟频率、电源管理等硬件的基本初始化过程。

  在StartUp 函数初始化CPU等核心硬件并跳转到Main函数后,系统就会转入C语言代码执行环境。这时Main函数分为3个模块:BLCOMMONDownload FunctionFLASH Function。其中BLCOMMON模块是由微软提供的,执行一些逻辑上的功能。而Download FunctionFLASH Function中的函数与硬件平台息息相关。因此,对于每种硬件平台都要将函数的实现进行适当修改,这种修改是需要对硬件非常熟悉的。当修改出现错误时,就会导致系统启动失败了。

  在硬件平台初始化完成后,oal.exe的启动任务基本完成,余下的启动工作由内核相关且独立于内核的OAL层实现体kernel.dll接管。也就是说,这时Startup会调用OALStartUp函数,OALStartUp函数主要完成将OEMAddressTable表传递给内核,然后调用KernelStart函数跳转到内核。因此,如果此时OAL的启动Startup函数调用失败的话,就也会导致系统的启动失败了。

  这里需要特别注意的是,BootloaderOAL中均包含启动Startup函数。它的功能大致相同,都是要初始化最小硬件环境。Bootloader的启动Startup函数是在为自己的执行准备硬件环境,OAL的启动Startup函数则是为kernel的执行准备硬件环境。由于这两种硬件环境要求基本相同,所以它们的代码也有很大部分可以相互借鉴。但应该明白BootloaderOAL在物理上是独立的,它们并不是同一段代码。当然,如果可以确定这一部分在Bootloader已经初始化过如热启动,则在OAL中不必重复执行。

  OAL入口位置定位失误导致的失败

  从上述WinCE启动流程可知,在OAL初始化硬件后而在内核启动前,系统是需要调用KernelStart函数来跳转到内核。因此,这里有一个要点,就是WinCE需要找到OAL的入口位置,然后才能调用入口函数与全局块进行指针交换,这样内核才能使用OAL层中的信息,同样OAL层也才能访问内核(kernel)导出的函数。

  OAL入口位置函数的调用实际上是通过OEMGLOBAL结构体实现的,实际调用位置为OEMInitDebugSerialOEMInit。也就是说,OEMGLOBAL结构体构建了内核和OAL层之间进行通信的桥梁。OEMGLOBAL结构体定义了OAL层所有必须的函数,该结构体在oemglobal.c文件中被初始化,并会被编译在OEMMain.lib OEMMain_StaticKITL.lib两个库中。如果OAL链接这两个库,则必须要有正确的该结构体的函数实现体,同时还需要调用ARMSetup来设置物理地址和非缓冲的虚拟内存地址的映像、arm中断向量以及内核模式所需要的堆栈、调用OEMInitDebugSerial函数初始化调试串口、调用OEMInit进行平台初始化等。否则,如果OAL入口位置函数有误,则内核和OAL层之间的访问就会失败,也就会导致系统在启动时出错和失败。

  .导致的WinCE启动失败的其它相关因素

  (1)驱动程序加载错误导致的失败

  在调试中,我们还发现系统在启动时执行到OEMInit时也经常会出现错误。一般来说,系统调用OEMInit运行完成之后,就会跳回PrivatePublic下的代码继续运行,然后再启动device.exe加载各个驱动程序。由于这一段代码是微软提供的default代码,基本上不会有问题。所以,我们就有理由怀疑如果加载的驱动程序出了问题,是也会造成系统启动失败的。一般来说,这些加载的驱动程序主要是 BSP中的AudioDisplaySDMMCSerialUSB等。

  (2)启动时加载配置有误的注册表导致的失败

  在WinCE中注册表在启动过程中也扮演着非常重要的角色。与桌面Windows一样,WinCE注册表(Registry)也是一个系统数据库,用来保存应用程序、驱动程序、用户的设定以及其它一些系统的配置信息,通常还存储着操作系统运作和调用程序的状态信息。例如,每个用户的配置文件、安装的应用程序以及每个应用程序可以创建的文档类型、文件夹和应用程序图标的属性表设置、系统上存在哪些硬件以及正在使用哪些端口等。

  因此,对于硬件外设来说注册表是一个记录驱动程序设置和位置的数据库。当WinCE系统在启动时需要启动某些必要的硬件设备时,就会需要使用外设驱动程序。但如果在WinCE中这个外设驱动是独立于操作系统的,WinCE系统就需要知道从哪里找到它们,例如文件名、版本号、其它设置和信息。因此,注册表上没有此设备的记录时,它们就不能被使用。所以,当注册表在启动时加载错误或者注册表配置有错误时,也是会导致WinCE系统启动失败的。

相关推荐

ARM收购Geomerics 强化行动装置游戏视觉

ARM  游戏视觉  2013-12-18

ARM:2013年Mail芯片出货量将超三亿片

ARM  芯片  2013-12-06

ARM控制智能机及平板芯片市场趋势将持续

ARM  控制智能机  2013-11-28

推动连网与行动创新 ARM聚焦物联网商机

ARM  物联网  2013-11-26

全球75%企业高管关注物联网新机遇

ARM  物联网  2013-11-08

英特尔将代工ARM芯片 或引发芯片价格下跌

英特尔  ARM  2013-10-31
在线研讨会
焦点