微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > S3C2410下WinCE6.0的启动过程详解

S3C2410下WinCE6.0的启动过程详解

时间:11-20 来源:互联网 点击:
通过前两篇文章的介绍,我们已经知道NBOOT用来引导EBOOT,继而EBOOT加载并引导WinCE操作系统(NK)。那么,WinCE6.0启动过程又是怎样的呢?本文基于S3C2410的平台做一个详细的分析。需要说明的是,WinCE6.0的整个启动过程对于同一类型的MCU来说大同小异,如S3C2410和PXA270同属ARM平台的MCU,所以他们的启动过程是类似的,可以说唯一的不同就在OAL处,而WinCE操作系统的启动正是从OAL开始的。

OAL(OEM Adaptation Layer)即OEM适配层,它的主要作用是在移植WinCE到新的硬件平台时减少操作系统的修改,通俗的说就是为WinCE操作系统抹平MCU的差异,使其能很方便的在不同MCU上运行。所以,OAL包括了和系统硬件通讯的最底层代码。内核则通过OAL跟硬件进行交互。逻辑上,OAL是介于CE内核和设备硬件之间的一个代码层,是一个抽象的概念。物理上,OAL和其他一些库一起链接成可执行文件,在WinCE6.0中对应的文件是OAL.exe,这是OAL的客观存在。WinCE6.0中的OAL跟先前的OAL比,是有一些变化的,它从内核中分离出来成为OAL.exe,而内核则变成了Kernel.dll。这样做的好处是可以单独升级OAL。但整体的OAL结构并没有改变,OEM函数保持一致,OAL和Kernel的接口由共享结构NKGLOBAL实现。这一部分的具体内容下一篇再做介绍。下图所示为WinCE6.0的OAL设计。

在移植WinCE到新的硬件平台时,创建OAL是最复杂的任务之一。一般来说,最简单的方法是拷贝一个跟新的硬件平台类似的且成熟的OAL,然后根据硬件的不同进行修改,使其满足目标硬件的特定要求。这里不展开说明,回头再单独整理。
从EBOOT到OAL.exe的跳转是从OEMLaunch()开始的,函数OEMLaunch()中调用Launch(dwPhysLaunchAddr),它的实现代码如下:



Code
LEAF_ENTRYLaunch

ldrr2,=PhysicalStart
ldrr3,=(VIR_RAM_START-PHY_RAM_START)

subr2,r2,r3

movr1,#0x0070;DisableMMU
mcrp15,0,r1,c1,c0,0
nop
movpc,r2;JumptoPStart
nop

;MMU&cachesnowdisabled.

PhysicalStart

movr2,#0
mcrp15,0,r2,c8,c7,0;FlushtheTLB
movpc,r0;Jumptoprogramwearelaunching.

函数Launch()的参数为物理地址,因为在跳转之前已将MMU关闭。该地址可通过VIEWBIN来查看,如下图所示:


如何确定这个地址对应的是NK.bin中的哪一个文件呢,先前说是OAL.exe,证据何在。在PB6.0中增加了浏览NK.bin的功能,我们可以利用此功能查看NK.bin的详细情况,如下图所示:



从上图中可以看出0x80205394处对应的是NK.exe,而这里的NK.exe即为OAL.exe。
至此,我们已经知道EBOOT是如何跳转到OAL.exe中的了。接下来继续看OAL.exe的执行过程。
OAL的启动代码如下:

Code
LEAF_ENTRYStartUp

;ComputetheOEMAddressTablesphysicaladdressand
;loaditintor0.KernelStartexpectsr0tocontain
;thephysicaladdressofthistable.TheMMUisnt
;turnedonuntilwellintoKernelStart.

addr0,pc,#g_oalAddressTable-(.+8)
blKernelStart

OAL的启动代码和EBOOT的启动代码经常复用,但为了代码的简洁,最好还是分开实现,而且在EBOOT中如果已经初始化了相关硬件,那么OAL的启动代码就可以省去那部分工作,可以很简练,如上面的代码所示。

可以看出,OAL的启动代码又调用了函数KernelStart(),而这个函数是在文件C:\WINCE600\PRIVATE\WINCEOS\COREOS\NK\LDR\ARM\armstart.s中实现的,代码如下:

Code
LEAF_ENTRYKernelStart

movr11,r0;(r11)=&OEMAddressTable(savepointer)

;figureoutthevirtualaddressofOEMAddressTable
movr1,r11;(r1)=&OEMAddressTable(2ndargumenttoVaFromPa)
blVaFromPa
movr6,r0;(r6)=VAofOEMAddressTable

;convertbaseofPTstoPhysicaladdress
ldrr4,=PTs;(r4)=virtualaddressofFirstPT
movr0,r4;(r0)=virtualaddressofFirstPT
movr1,r11;(r1)=&OEMAddressTable(2ndargumenttoPaFromVa)
blPaFromVa

movr10,r0;(r10)=ptrtoFirstPT(physical)

;Zerooutpagetables&kerneldatapage

movr0,#0;(r0-r3)=0stostore
movr1,#0
movr2,#0
movr3,#0
movr4,r10;(r4)=firstaddresstoclear
addr5,r10,#KDEnd-PTs;(r5)=lastaddress+1
18stmiar4!,{r0-r3}
stmiar4!,{r0-r3}
cmpr4,r5
blo%B18

;readthearchitectureinformation
blGetCpuId
movr5,r0LSR#16;r5>>=16
andr5,r5,#0x0000000f;r5&=0x0000000f==architectureid

;Setup2ndlevelpagetabletomapthehighmemoryareawhichcontainsthe
;firstlevelpagetable,2ndlevelpagetables,kerneldatapage,etc.
;(r5)=architectureid

addr4,r10,#HighPT-PTs;(r4)=ptrtohighpagetable

cmpr5,#ARMv6;v6orlater?
;ARMV6_MMU
orrger0,r10,#PTL2_KRW+PTL2_SMALL_PAGE+ARMV6_MMU_PTL2_SMALL_XN
;(r0)=PTEfor4K,kr/wu-/-page,uncachedunbuffered,nonexecutable
;PREARMV6_MMU
orrltr0,r10,#PTL2_KRW+(PTL2_KRW<2)+(PTL2_KRW<4)+(PTL2_KRW<6)
;NeedtoreplicateAPbitsintoall4fields
orrltr0,r0,#PTL2_SMALL_PAGE+PREARMV6_MMU_PTL2_SMALL_XN
;(r0)=PTEfor4K,kr/wu-/-page,uncachedunbuffered,nonexecutable
strr0,[r4,#0xD0*4];storetheentryinto4slotstomap16Kofprimarypagetable
addr0,r0,#0x1000;steponthephysicaladdress
strr0,[r4,#0xD1*4]
addr0,r0,#0x1000;steponthephysicaladdress
strr0,[r4,#0xD2*4]
addr0,r0,#0x1000;steponthephysicaladdress
strr0,[r4,#0xD3*4]

addr8,r10,#ExceptionVectors-PTs;(r8)=ptrtovectorpage
orrr0,r8,#PTL2_SMALL_PAGE;constructthePTE(C=B=0)

;;Theexceptionstacksandthevectorsaremappedasasinglekr/wpage.
;;Anyalternativewillusemorephysicalmemory.
;;Multiplemappingsdontprovideanyrealprotection:ifthevectorswereinar/opage,
;;theycouldstillbecorruptedviathekr/wsettingr

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top