【IT168专稿】近期,我所负责的一个嵌入式开发项目遇到了一点麻烦。这个嵌入式系统用的是ARM处理器+WinCE平台,我这次项目的目的是要把WinCE平台从旧版本移植到WinCE6.0平台上。但结果是这个WinCE系统在启动的时候经常会出现失败,而且每次失败的原因都莫明其妙和不尽相同。这使到我们开发团队每个人在启动WinCE系统时都心惊肉跳,非常担心系统又再一次出现让人意想不到的失败。这种频繁的启动失败对开发团队来说显然是一种让人难以忍受的折磨。
为什么会出现这种情况呢?经过几个晚上通宵达旦的加班分析和研究,原来主因是系统的引导过程、内核加载过程、OAL启动过程和硬件驱动加载过程时都存在可能导致的失败的隐忧。本文通过对以上因素进行分析,并提出相应的解决办法。但由于WinCE启动失败会非常取决于硬件平台,因此在具体应用时需要综合考虑和分析。
一.什么是WinCE启动过程?
WinCE系统在启动时一般需要三个基本元素:引导初始化、内核加载和OAL初始化等。它们的作用是要完成引导过程的初始化和操作系统执行环境的初始化。其中引导初始化是由引导工具BootLoader完成,主要是完成板级、片级的初始化。例如,通过设置寄存器来完成硬件的初始化,如设置时钟、设置中断控制寄存器、完成内存映射和初始化MMU的工作方式等。内核加载是指将操作系统内核映像从只读存储器加载或者拷贝到系统的RAM中并执行。OAL(OEM Adaption Layer,即原始设备制造商适配层)是位于操作系统的内核与硬件之间的适配层,也是连接系统内核与硬件的枢纽,它具有屏蔽硬件设备细节以及抽象硬件功能的作用。而OAL初始化则是指通过一组函数来体现出0AL屏蔽和抽象硬件设备的作用。
此外,如果要WinCE系统成为完整的操作系统,还得加上硬件驱动程序、硬件接口程序和应用程序组。因此,即使在一个简单的嵌入式系统里,WinCE系统启动时是需要加载内核和加载许多组件或驱动程序。
现在让我们来看看WinCE系统在启动时调用函数的顺序:①CPU执行引导向量,跳转到硬件初始化代码,即Startup函数。②在start up函数完成最小硬件环境初始化后跳转到KernelStart函数,来对内核进行初始化。③Kernelstart函数调用OEMInitDebugSerial完成对调试串口的初始化;同时调用0EMInit函数来完成硬件初始化工作以及设置时钟、中断;最后,调用OEMGetExtensionDRAM函数来判断是否还有另外一块DRAM。至此,内核加载完毕。由此可见,WinCE系统启动的重中之重是Startup函数的正确加载,如果这个Startup函数调用失败,则会使到系统在启动频繁出错。WinCE启动时调用函数顺序如下图所示:
因此,WinCE启动失败可能会存在于引导初始化失败、内核加载失败、0AL函数初始化失败、驱动程序加载失败、组件加载失败和应用程序加载失败。也就是说,WinCE启动失败一方面可能是在Startup函数的处理上,例如引导初始化和OAL初始化。另一方面还存在于驱动程序和组件自启动的失败上,例如基本的驱动程序、注册表配置或自运行的程序等。
就不能被使用。所以,当注册表在启动时加载错误或者注册表配置有错误时,也是会导致WinCE系统启动失败的。