Wince启动失败的原因分析

来源:互联网 发布:燕氏姓名学软件 编辑:程序博客网 时间:2024/05/21 14:02
①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.EXE。OAL
包括了和系统硬件通讯的最底层代码,内核是通过OAL跟硬件进行交互。逻辑上,OAL
是介于CE内核和设备硬件之间的一个代码层,是一个抽象的概念。物理上,OAL
和其它一些库一起链接成可执行文件。
  与以前的Win CE旧版本不同的是,在Win CE 6.0中内核(Kenerl)和OEM代码被分成oal
.exe、kernel.dll和kitl.dll三个部分,其中启动代码(startup)和 OAL
层的实现部分不再与内核链接生成NK.exe,取而代之的是启动代码(startup)
和硬件相关且独立于内核的OAL层的实现部分编译成 oal.exe;
而与内核相关且独立于硬件的OAL层代码包含在kernel.dll中,内核无关传输层(KITL)
的支持代码从OAL层分离出来编译成 kitl.dll。因此,WinCE6.0的启动只与oal.exe和
kernel.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个模块:BLCOMMON、Download Function、FLASH
Function。其中BLCOMMON模块是由微软提供的,执行一些逻辑上的功能。而Download
Function、FLASH Function
中的函数与硬件平台息息相关。因此,对于每种硬件平台都要将函数的实现进行适当修改?
庵中薷氖切枰杂布浅J煜さ摹5毙薷某鱿执砦笫保突岬贾孪低称舳О芰恕?
  在硬件平台初始化完成后,oal.exe
的启动任务基本完成,余下的启动工作由内核相关且独立于内核的OAL层实现体kernel.
dll接管。也就是说,这时Startup会调用OALStartUp函数,OALStartUp函数主要完成将
OEMAddressTable表传递给内核,然后调用KernelStart函数跳转到内核。因此,如果此时
OAL的启动Startup函数调用失败的话,就也会导致系统的启动失败了。
  这里需要特别注意的是,Bootloader和OAL中均包含启动Startup
函数。它的功能大致相同,都是要初始化最小硬件环境。Bootloader的启动Startup
函数是在为自己的执行准备硬件环境,OAL的启动Startup函数则是为kernel
的执行准备硬件环境。由于这两种硬件环境要求基本相同,所以它们的代码也有很大部分?
梢韵嗷ソ杓5Ω妹靼譈ootloader与OAL
在物理上是独立的,它们并不是同一段代码。当然,如果可以确定这一部分在Bootloader
已经初始化过如热启动,则在OAL中不必重复执行。
  ②OAL入口位置定位失误导致的失败
  从上述WinCE启动流程可知,在OAL初始化硬件后而在内核启动前,系统是需要调用
KernelStart函数来跳转到内核。因此,这里有一个要点,就是WinCE需要找到OAL
的入口位置,然后才能调用入口函数与全局块进行指针交换,这样内核才能使用OAL
层中的信息,同样OAL层也才能访问内核(kernel)导出的函数。
  OAL入口位置函数的调用实际上是通过OEMGLOBAL结构体实现的,实际调用位置为
OEMInitDebugSerial和OEMInit。也就是说,OEMGLOBAL结构体构建了内核和OAL
层之间进行通信的桥梁。OEMGLOBAL结构体定义了OAL层所有必须的函数,该结构体在
oemglobal.c文件中被初始化,并会被编译在OEMMain.lib和 OEMMain_StaticKITL.lib
两个库中。如果OAL
链接这两个库,则必须要有正确的该结构体的函数实现体,同时还需要调用ARMSetup
来设置物理地址和非缓冲的虚拟内存地址的映像、arm
中断向量以及内核模式所需要的堆栈、调用OEMInitDebugSerial
函数初始化调试串口、调用OEMInit进行平台初始化等。否则,如果OAL
入口位置函数有误,则内核和OAL
层之间的访问就会失败,也就会导致系统在启动时出错和失败。
  三.导致的WinCE启动失败的其它相关因素
  (1)驱动程序加载错误导致的失败
  在调试中,我们还发现系统在启动时执行到OEMInit
时也经常会出现错误。一般来说,系统调用OEMInit运行完成之后,就会跳回Private或
Public下的代码继续运行,然后再启动device.exe
加载各个驱动程序。由于这一段代码是微软提供的default
代码,基本上不会有问题。所以,我们就有理由怀疑如果加载的驱动程序出了问题,是也?
嵩斐上低称舳О艿摹R话憷此担庑┘釉氐那绦蛑饕?BSP中的Audio、Display
、SDMMC、Serial、USB等。
  (2)启动时加载配置有误的注册表导致的失败
  在WinCE中注册表在启动过程中也扮演着非常重要的角色。与桌面Windows一样,
WinCE注册表(Registry)也是一个系统数据库,
用来保存应用程序、驱动程序、用户的设定以及其它一些系统的配置信息,通常还存储着?
僮飨低吃俗骱偷饔贸绦虻淖刺畔ⅰ@纾扛鲇没У呐渲梦募沧暗挠τ贸绦蛞约懊?
个应用程序可以创建的文档类型、文件夹和应用程序图标的属性表设置、系统上存在哪些?
布约罢谑褂媚男┒丝诘取?
因此,对于硬件外设来说注册表是一个记录驱动程序设置和位置的数据库。当WinCE
系统在启动时需要启动某些必要的硬件设备时,就会需要使用外设驱动程序。但如果在
WinCE中这个外设驱动是独立于操作系统的,WinCE
系统就需要知道从哪里找到它们,例如文件名、版本号、其它设置和信息。因此,注册表?
厦挥写松璞傅募锹际保蔷筒荒鼙皇褂谩K裕弊⒉岜碓谄舳奔釉卮砦蠡蛘咦⒉岜?
配置有错误时,也是会导致WinCE系统启动失败的。
原创粉丝点击