2440bsp wince启动分析

来源:互联网 发布:大推力火箭 知乎 编辑:程序博客网 时间:2024/06/06 09:41

Clone一个BSP.

WinCE6.0安装armv4i架构后,里面提供了一个名字为DeviceEmulatorBSP.这个BSPs3c2410BSP.我的是s3c2440a,就克隆这个吧.

下面是WinCE6.0的内核启动过程:

OAL不能调用内核的KernelStart()函数了,所以自己要实现一个KernelStart() (nkldr.lib替我们完成了这个,nkldr.lib链接到OAL),调用nkldr.lib中的KernelStart().然后执行的ARMInit()函数有一个很重要的任务,它将位于OALOEMinitGlobals()函数指针赋值到Kdata,后面内核需要这个指针.接下来根据Kdata找到并跳转到内核kernel.dll的入口点NKStartup().

Kernel.dll开始执行NKStartUp(),首先要把和OAL的桥梁打通.也就是把内核的NKGlobal数据结构指针交给OAL,并且获得OALOEMGlobal的数据结构指针.怎么实现的? 内核根据Kdata找到OAL中一个函数OEMInitGlobals() —还记得吗,前面说到OALARMInit()曾经郑重的把OEMInitGlobals函数指针赋值给了Kdata,就是为了这一天...然后,NKGlobal指针作为参数执行这个函数,这个函数返回OALOEMGlobal的指针.(嗯哼~ OAL要实现OEMInitGlobals(), oemmain.lib替我们完成了这个,oemmain.lib链接到OAL).

这个Kdata是个什么玩意?它是内核数据结构, 简单理解成共享内存好了, oal kernel都可访问到.再往后没啥好说了,内核可以访问OAL,痛快的调用OEM函数,和以前WinCE5.0差不多.最后调用KernelStart(),这回这个函数可是在内核里面了,WinCE6.0起来了……

这个流程和WinCE5.0有点点差别.都是因为OALkernel分离了.

[编译OAL]

空谈了这么久,来做实质性的工作吧,开始编译WinCE6.0OAL.微软希望它的设计使得移植OAL时候尽可能少工作量,所以oal.exe2个步骤来实现.第一步:编译oal.lib.第二步:编译oal.exe.第一步的oal.lib可以就是原来版本的,你拷贝原来的oal目录代码到OALLIB目录编译一个oal.lib.关键是第二步,原来在WinCE5.0时候,oal.lib+nk.lib编译成了kern.exe,然后改名成nk.exe.现在,要把oal+nkstub.lib,编译成oal.exe.nk.lib也不是说不要就可以直接不要的.在编译oal.lib时候可是大量使用了nk.lib的东东.你不会想全文重新改变函数和变量的调用形式吧? ok,nkstub.lib链接上.这么一来,OALEXE目录下的SOURCES文件里面,4个库被添加进来.

TARGETLIBS= oal.lib oemmain.lib nkldr.lib nkstub.lib ……(路径省略)

Nkldr.liboemmain.lib是干吗的?回溯前面的启动过程吧. nkldr.lib提供了KernelStart()的实现, oemmain.lib提供了OEMInitGlobals()的实现.当然还有更多的,不罗列了.

[定制OAL]

没有oal.lib咋办?做一个吧……前面提到OALKernel分离,使得接口更加明显了,kernel到底需要OEMs提供哪些函数,可以参照着oemglobal.h文件里面OEMGLOBAL结构体来完成.并且在oemglobal.c里面对这个结构体初始化.这个文件位于oemmain.lib.发扬愚公移山的精神,我来抽丝拨茧一下,下面根据我的2440来分析最重要的必须的几个接口:

[Init相关接口]

要提供OEMInit(), OEMInitDebugSerial(),

OEMInit()函数,建立一个init.c,然后实现这个函数.

OEMInitDebugSerial()放到下面debug.c中实现.

[Debug相关接口]

OEMWriteDebugString

OEMInitDebugSerial

OEMWriteDebugByte

OEMReadDebugByte

OEMWriteDebugLED

PQOALoal_other.lib提供了OEMWriteDebugString(),

OALLIB下创建debug.c ,然后实现OEMInitDebugSerial, OEMWriteDebugByte, OEMReadDebugByte, OEMWriteDebugLED4个函数.

[Cache相关接口]

需要提供OEMCacheRangeFlush,根据自己的架构去已有的PQOAL找吧,我的是oal_cache_arm920t.lib

[Time相关接口]

需要提供

InitClock

OEMGetRealTime

OEMSetRealTime

OEMSetAlarmTime

OEMQueryPerfCounter

OEMQueryPerfFreq

OEMGetTickCount

InitClock,这个功能已经废除了,相关功能被移到OEMPowerOff.所以可以实现一个空函数,在初始化OemGlobal时候,把这个指针赋值RetuanFalse()函数也是一样的效果.OEMGetRealTime ,OEMSetRealTime是设置读取rtc的日期功能.OEMSetAlarmTime是设置rtc的报警时刻,找到oal_rtc_s3c2440a.lib

OEMQueryPerfCounter,OEMQueryPerfFreq是提供更高精度时间的查询,

OEMGetTickCount返回当前CurMSec,系统运行了多少毫秒.oal_time.lib中已经有实现.特别强调的是,这个函数在WinCE5.0里面是SC_GetTickCount.需要把名字改了.这个是OAL的一个区别.

[Scheduler相关接口]

OEMIdle, OEMNotifyThreadExit, OEMNotifyIntrOccurs, OEMUpdateReschedTime,一个变量DefaultThreadQuantum.

[power相关接口]

OEMPowerOff,这个还要说啥, 挂起时候会执行这个函数. PQOALoal_power_s3c2440a.lib已经帮忙实现了最基础的工作,会调用BSPPowerOff来完成平台相关的动作,建立一个文件power.c来实现这个BSPPowerOff.

[DRAM相关接口]

OEMGetExtensionDRAM, OEMEnumExtensionDRAM, CalcFSPages,变量MainMemoryEndAddress

这组函数询问扩展RAM的情况,如果OEMEnumExtensionDRAM函数提供了,就执行这个函数,否则执行OEMGetExtensionDRAM, CalcFSPages计算pages,这个功能内核自己实现了,已经不要了,指向一个空函数即可.

[interrupt相关接口]

OEMInterruptEnable, OEMInterruptDisable, OEMInterruptDone,

OEMIniterruptMask,OEMInterruptHandler

基本工作PQOAL已经做好了,PQOAL下面几个接口完成平台相关工作,BSPIntrInit, BSPIntrRequestIrq, BSPINtrEnableIrq, BSPIntrDisableIrq, BSPIntrDoneIrq, BSPIntrActiveIrq.最后一个OEMInterruptHandler就是系统ISR,将物理irq转换成逻辑中断SYSINTR_XXX.

[other ]

OEMIoControl .PQOAL里面已经实现了这个功能.如果OEMs要添加新的控制命令,建立一个ioctl.c,定义一个全局数组g_oalIoCtlTable,然后往数组里面填入命令字和对应命令执行的函数的名称.这个对应命令的执行函数当然要自己实现了.驱动或者应用使用KernelIOControl这个api时候,相应命令的函数就会执行.

[总结]

1.WinCE6.0不只是将OALkernel分离.还将kitl也分离成为了kitl.dll.所以,OAL也不能直接使用kitl的资源.首先把kitl.ckitl相关代码从OAL里面给放到kitl目录去.然后在OEMInit中不能调用OALKitlStart(),KITLIoctl(IOCTL_KITL_STARTUP, NULL, 0, NULL, 0, NULL);这一句来替代.

2.OAL需要使用的数据结构定义,和外部函数声明都在头文件nkexport.h.可以在oal.hinclude这个nkexport.h头文件.

3. PQOALoal_log库有了变化,如果使用了这个库的要注意,它不在使用g_oalLogMask这个全局变量了.

4. timertimer_dvs目录下的watchdog.c文件和nkexport.h中重复定义了pfnOEMRefreshWatchDog,dwOemWatchDogPeriod.一个解决办法是去掉watchdog.c.反正也可以不使用这个接口.默认传过去的是空接口ReturnFalse()

5. 编译smflash.dll出错,需要fal.lib一起编译成为smflash.dll. fal的源代码位于private\winceos\driver\msflash\src.这个fal.lib.好像和以前的不一样.从错误信息中观察,好像多出来2个接口.fmd.cpp里面增加这2个接口:

LPVOID FMDHOOK_HookInterface(PFMDInterface pInterface)

{ return (LPVOID) pInterface;}

Void FMDHOOK_UnhookInterface(LPVOID pContext, FMDInterface *pInterface){}

至此,在给oal加上一个启动代码startup.s.一个oal.lib就完成了.

 

原创粉丝点击