CE5,6的移植,build等等,有条理。

来源:互联网 发布:k均值聚类算法 编辑:程序博客网 时间:2024/06/02 05:48

 转自《http://www.cnblogs.com/Torres_fans/archive/2009/10/13.html》:

 

2009年10月13日

关于2440从5.0到6.0的移植之OAL篇

这几天一直忙着移植,说实话,这个想法已经有一个月了,只是半个月前才开始行动而已。一开始以为很简单的事情,首先,我已经看了好几本

书了,当然也是大概看了一遍,比如李大为,周健设,何宗健老师,张冬泉老师的书我都有看过,七剑还看了很多论坛,可是结果依然令人失望

,往往事情和想象的不一样!
开始我从网上先搜了一下关于移植有没有现成的,我好直接拿过来用,然后再进行一定程度的修改,当然希望越少越好,可惜行不通。原因很明

显:1,CPU不一致,有的是2410的,有2443的,当然也有2440的。于是我选择了2440进行移植。因为我的板子是友善之臂的mini2440.
    2,找别人移植好的BSP。去哪找?各个论坛我已经转个遍,下了许多,这期间我要BS下TONY论坛的一些人,他们上传的一些资料聊相当不负

责任,完全是为了骗金币,当然对于TONY我还是很崇拜的!
    3,资料有了,却不知道从何下手,因为可以选择的余地多了,烦恼也就多了,这个人有这个得看法,那个人有那样的做法,我该如何进行

选择呢?
......还有许多问题,就不列举了!
今天总算把OAL调通了,算是成功了一小步吧。因为我听一个牛人说过,把OAL何KITL调通就已经成功了一半,呵呵,我不知道是不是真的,但是

我希望我能坚持下去。
首先,参考http://www.cnblogs.com/we-hjb/archive/2008/10/29/1322509.html的帖子,把这个牛人的博客的帖子调通了,刚开始怎么调也调

不通,最后过了几天无意中又调试了一下,居然调通了。
接着,参考gooogleman的移植文档,按照他的思路进行了相应的修改。
中间也出过许多错误,下面我把我的错误贴出来和大家一起探讨一下:

首先,按照http://www.cnblogs.com/we-hjb/archive/2008/10/29/1322509.html这个帖子,大家进行OAL的快速调试,通过这个操作,我想大家

可以学到更多,最起码VS2005的一些功能我现在才知道。
其次,参照gooolman的帖子进行移植,在他的个人博客里面有说明。按着来就行了。
一、先编译后模拟器的精简版本,然后把模拟器的OAL相关的代码进行删除,换成5.0BSP的代码(把KITL相关的代码删除)并修改相应的sources

文件。COMMON目录下主要有smartmedia\dll和smartmedia\fmd两个source文件。OAL目录下主要有:OALEXE和OALLIB两个文件下的SOURCE文件。

把KITL在DIR目录里面屏蔽。

二、把C:\WINCE500\PLATFORM\SMDK2440A\Src\Common代替D:\WINCE600\PLATFORM\mini2440\SRC\Common
C:\WINCE500\PLATFORM\SMDK2440A\Src\Inc代替D:\WINCE600\PLATFORM\mini2440\SRC\Inc

三、编译OAL的时候会调用D:\WINCE600\PLATFORM\mini2440\SRC\Common下的很多代码生成的lib,所以我现在首先编译D:\WINCE600

\PLATFORM\mini2440\SRC\Common下面的所有代码,在VS2005 上点中Common然后右键选择“rebuild”,有错误了(有错误才是正常的,

(*^__^*) 嘻嘻……)
警告的内容:
BUILD: [Thrd:Sequence:Type  ] Message
BUILD: [01:0000000039:WARNN ] D:\WINCE600\PLATFORM\mini2440\src\common\Intr\.\intr.c(379) : warning C4013: 'NKCallIntChain'

undefined; assuming extern returning int
BUILD: [01:0000000058:WARNN ] D:\WINCE600\PLATFORM\mini2440\src\common\Intr_dvs\.\intr.c(628) : warning C4013:

'NKCallIntChain' undefined; assuming extern returning int
BUILD: [01:0000000192:WARNN ] D:\WINCE600\PLATFORM\mini2440\src\common\Smartmedia\fmd\.\fmd.cpp(940) : warning C4018: '<' :

signed/unsigned mismatch
BUILD: [01:0000000193:WARNN ] D:\WINCE600\PLATFORM\mini2440\src\common\Smartmedia\fmd\.\fmd.cpp(941) : warning C4244: '=' :

conversion from 'unsigned long' to 'USHORT', possible loss of data
BUILD: [01:0000000194:WARNN ] D:\WINCE600\PLATFORM\mini2440\src\common\Smartmedia\fmd\.\fmd.cpp(945) : warning C4018: '<' :

signed/unsigned mismatch
BUILD: [01:0000000195:WARNN ] d:\wince600\platform\mini2440\src\common\smartmedia\fmd\fmd.cpp(956) : warning C4700:

uninitialized local variable 'pLockInfo' used
BUILD: [00:0000000445:WARNN ] D:\WINCE600\PLATFORM\mini2440\src\common\Smartmedia\Dll\: Missing source file: D:\WINCE600

\public\cesysgen\sdk\lib\ARMV4I\debug\coredll.lib.
BUILD: [00:0000000446:WARNN ] D:\WINCE600\PLATFORM\mini2440\src\common\Smartmedia\Dll\: Missing source file: D:\WINCE600

\public\cesysgen\oak\lib\ARMV4I\debug\fal.lib.


(这个VS2005 唯一不好的地方就是编译错误不是红色显示的)
出错地方
 // First find if IRQ is claimed by chain
        sysIntr = NKCallIntChain((UCHAR)irq);

晕,上面仅仅是警告,但是估计也有问题。跑到Common下打开build.err看看,有错误。
BUILD: [Thrd:Sequence:Type  ] Message
BUILD: [01:0000000480:ERRORE] fal.lib(falmain.obj) : error LNK2019: unresolved external symbol FMDHOOK_UnhookInterface

referenced in function DSK_Deinit
BUILD: [01:0000000481:ERRORE] fal.lib(falmain.obj) : error LNK2019: unresolved external symbol FMDHOOK_HookInterface

referenced in function "void __cdecl GetFMDInterface(struct _DEVICE *)" (?GetFMDInterface@@YAXPAU_DEVICE@@@Z)
BUILD: [01:0000000482:ERRORE] smflash_lib.lib(fmd.obj) : error LNK2019: unresolved external symbol ReadPage512 referenced in

function "int __cdecl FMD_SB_ReadSector(unsigned long,unsigned char *,struct _SectorInfo *,unsigned long,int)" (?

FMD_SB_ReadSector@@YAHKPAEPAU_SectorInfo@@KH@Z)
BUILD: [01:0000000483:ERRORE] smflash_lib.lib(fmd.obj) : error LNK2019: unresolved external symbol WritePage512 referenced in

function "int __cdecl FMD_SB_WriteSector(unsigned long,unsigned char *,struct _SectorInfo *,unsigned long,int)" (?

FMD_SB_WriteSector@@YAHKPAEPAU_SectorInfo@@KH@Z)
BUILD: [01:0000000484:ERRORE] D:\WINCE600\platform\mini2440\target\ARMV4I\debug\smflash.dll : fatal error LNK1120: 4

unresolved externals

 

怎么回事呢?
接着参考http://bbs.driverdevelop.com/simple/index.php?t112006.htmlztg0021的帖子,发现他也遇见类似的错误,按照他的思路进行修改


Src\Common\Smartmedia\Dll中的sources文件修改
在SOURCELIBS语句段中原有的两个库的基础上增加下面的库
$(_COMMONOAKROOT)\lib\$(_CPUINDPATH)\fmdhooklib.lib \
之后又有新的错误了。
BUILD: [Thrd:Sequence:Type  ] Message
BUILD: [01:0000000432:ERRORE] D:\WINCE600\PLATFORM\mini2440\src\common\Smartmedia\Dll\sources(12) :  U1033: syntax error :

'$(_COMMONOAKROOT)\lib\$(_CPUINDPATH)\fmdhooklib.lib' unexpected
BUILD: [01:0000000434:ERRORE] NMAKE.EXE TargetLibFiles  -i -c BUILDMSG=Stop.  BUILDROOT=D:\WINCE600\PLATFORM\mini2440

CLEANBUILD=1 LINKONLY=1 NOPASS0=1 failed - rc = 2

警告:
BUILD: [Thrd:Sequence:Type  ] Message
BUILD: [01:0000000039:WARNN ] D:\WINCE600\PLATFORM\mini2440\src\common\Intr\.\intr.c(379) : warning C4013: 'NKCallIntChain'

undefined; assuming extern returning int
BUILD: [01:0000000058:WARNN ] D:\WINCE600\PLATFORM\mini2440\src\common\Intr_dvs\.\intr.c(628) : warning C4013:

'NKCallIntChain' undefined; assuming extern returning int
BUILD: [01:0000000192:WARNN ] D:\WINCE600\PLATFORM\mini2440\src\common\Smartmedia\fmd\.\fmd.cpp(940) : warning C4018: '<' :

signed/unsigned mismatch
BUILD: [01:0000000193:WARNN ] D:\WINCE600\PLATFORM\mini2440\src\common\Smartmedia\fmd\.\fmd.cpp(941) : warning C4244: '=' :

conversion from 'unsigned long' to 'USHORT', possible loss of data
BUILD: [01:0000000194:WARNN ] D:\WINCE600\PLATFORM\mini2440\src\common\Smartmedia\fmd\.\fmd.cpp(945) : warning C4018: '<' :

signed/unsigned mismatch
BUILD: [01:0000000195:WARNN ] d:\wince600\platform\mini2440\src\common\smartmedia\fmd\fmd.cpp(956) : warning C4700:

uninitialized local variable 'pLockInfo' used


晕倒,把D:\WINCE600\PLATFORM\mini2440\SRC\Common目录下的Smartmedia换成ztg0021的那个就好了!
没有错误,编译成功!
警告:
BUILD: [Thrd:Sequence:Type  ] Message
BUILD: [01:0000000039:WARNN ] D:\WINCE600\PLATFORM\mini2440\src\common\Intr\.\intr.c(380) : warning C4013: 'NKCallIntChain'

undefined; assuming extern returning int
BUILD: [01:0000000058:WARNN ] D:\WINCE600\PLATFORM\mini2440\src\common\Intr_dvs\.\intr.c(628) : warning C4013:

'NKCallIntChain' undefined; assuming extern returning int
BUILD: [00:0000000436:WARNN ] D:\WINCE600\PLATFORM\mini2440\src\common\Smartmedia\Dll\: Missing source file: D:\WINCE600

\public\cesysgen\sdk\lib\ARMV4I\debug\coredll.lib.
BUILD: [00:0000000437:WARNN ] D:\WINCE600\PLATFORM\mini2440\src\common\Smartmedia\Dll\: Missing source file: D:\WINCE600

\public\cesysgen\oak\lib\ARMV4I\debug\fal.lib.
BUILD: [00:0000000438:WARNN ] D:\WINCE600\PLATFORM\mini2440\src\common\Smartmedia\Dll\: Missing source file: D:\WINCE600

\public\cesysgen\oak\lib\ARMV4I\debug\fmdhooklib.lib.

 

继续编译OAL。在参考了gooogleman 的移植笔记,在OALlib的时候还是卡住了,始终是8个错误,我贴出来在此向大家求教下:
BUILD: [Thrd:Sequence:Type  ] Message
BUILD: [01:0000000030:ERRORE] D:\WINCE600\PLATFORM\mini2440\src\oal\oallib\.\init.c(53) : error C2065: 'dwNKDrWatsonSize' :

undeclared identifier
BUILD: [01:0000000034:ERRORE] D:\WINCE600\PLATFORM\mini2440\src\oal\oallib\.\intr.c(71) : error C2065:

'BSP_BASE_REG_PA_DM9000_IOBASE' : undeclared identifier
BUILD: [01:0000000035:ERRORE] D:\WINCE600\PLATFORM\mini2440\src\oal\oallib\.\intr.c(71) : error C2051: case expression not

constant
BUILD: [01:0000000045:ERRORE] D:\WINCE600\PLATFORM\mini2440\src\oal\oallib\.\debug.c(73) : error C2065: 'BSP_UART0_UFCON' :

undeclared identifier
BUILD: [01:0000000046:ERRORE] D:\WINCE600\PLATFORM\mini2440\src\oal\oallib\.\debug.c(74) : error C2065: 'BSP_UART0_UMCON' :

undeclared identifier
BUILD: [01:0000000047:ERRORE] D:\WINCE600\PLATFORM\mini2440\src\oal\oallib\.\debug.c(75) : error C2065: 'BSP_UART0_ULCON' :

undeclared identifier
BUILD: [01:0000000048:ERRORE] D:\WINCE600\PLATFORM\mini2440\src\oal\oallib\.\debug.c(76) : error C2065: 'BSP_UART0_UCON' :

undeclared identifier
BUILD: [01:0000000049:ERRORE] D:\WINCE600\PLATFORM\mini2440\src\oal\oallib\.\debug.c(77) : error C2065: 'BSP_UART0_UBRDIV' :

undeclared identifier

晕倒我的没有extern DWORD dwNKDrWatsonSize;会提示dwNKDrWatsonSize未定义错误,加上就好了,但是ztg0021的却要屏蔽
extern DWORD dwNKDrWatsonSize 才行的。希望等下不要出乱子。

这里我加上了这句外部声明,不知道最后的结果如何?先放在这里!但是编译COMMON时没有任何问题的。

在这里我要特别感谢一个人:wlc311
在CSDN的这些日子里,他就像一个老朋友帮了我很多,再次向他致谢!
wlc311搞定了6个错误:解决办法如下:
我提拱其中6个错误的解决方法:
BUILD: [01:0000000034:ERRORE] D:\WINCE600\PLATFORM\mini2440\src\oal\oallib\.\intr.c(71) : error C2065:

'BSP_BASE_REG_PA_DM9000_IOBASE' : undeclared identifier
在SRC->INC->bsp_base_reg_cfg中加上如这样:
#define BSP_BASE_REG_PA_DM9000_IOBASE          0x20000300
#define BSP_BASE_REG_PA_DM9000_MEMBASE          0x20000000
BUILD: [01:0000000045:ERRORE] D:\WINCE600\PLATFORM\mini2440\src\oal\oallib\.\debug.c(73) : error C2065: 'BSP_UART0_UFCON' :

undeclared identifier
BUILD: [01:0000000046:ERRORE] D:\WINCE600\PLATFORM\mini2440\src\oal\oallib\.\debug.c(74) : error C2065: 'BSP_UART0_UMCON' :

undeclared identifier
BUILD: [01:0000000047:ERRORE] D:\WINCE600\PLATFORM\mini2440\src\oal\oallib\.\debug.c(75) : error C2065: 'BSP_UART0_ULCON' :

undeclared identifier
BUILD: [01:0000000048:ERRORE] D:\WINCE600\PLATFORM\mini2440\src\oal\oallib\.\debug.c(76) : error C2065: 'BSP_UART0_UCON' :

undeclared identifier
BUILD: [01:0000000049:ERRORE] D:\WINCE600\PLATFORM\mini2440\src\oal\oallib\.\debug.c(77) : error C2065: 'BSP_UART0_UBRDIV' :

undeclared identifier
在SRC->INC->bsp_cfg中加上
#define BSP_UART0_ULCON        0x03                // 8 bits, 1 stop, no parity
#define BSP_UART0_UCON          0x0005              // pool mode, PCLK for UART
#define BSP_UART0_UFCON        0x00                // disable FIFO
#define BSP_UART0_UMCON        0x00                // disable auto flow control
#define BSP_UART0_UBRDIV        (S3C2440A_PCLK/(115200*16) - 1)

其它两个原因,因为没遇到过这种情况,故不便乱说。
重新编译整个OAL

build.err变成
BUILD: [Thrd:Sequence:Type  ] Message
BUILD: [01:0000000076:ERRORE] D:\WINCE600\PLATFORM\mini2440\src\oal\oallib\.\init.c(53) : error C2065: 'dwNKDrWatsonSize' :

undeclared identifier

关于:NKCallIntChain,我上网搜了一下,大概意思是:
要生成错误报告的dump文件,需要至少有128K的内存。OAL层初始化函数OEMInit中,变量dwNKDrWatsonSize就是记录这个内存的大小。内核会从

主内存区域的最后,保留出这一块内存。设置编译环境变量SYSGEN_WATSON_DMPGEN,让镜像包含有错误报告生成器的功能。

后面再论坛上求助,得到何宗健老师的指导:
何宗健老师:看来出错的代码在oal自己的代码中。其实我感觉,可以把dwNKDrWatsonSize注释掉,禁止dump这个功能,或者自己在任何一个头

文件里面定义一个就好了,看看5.0版本的bsp该变量定义在哪里的。据自己的经验,5.0移植6.0只要参考微软的官方移植文档,基本上工作量不

大。

zhengshijie:5.0里面直接外部引用的全局变量,在6.0里不能用了,而是通过
platform/common/src/inc/oal.h->public/common/oak/inc/oemglobal.h->public/common/oak/inc/bcoemglobal.h
#define dwNKDrWatsonSize                    g_pOemGlobal->cbErrReportSize
在6.0里把extern DWORD dwNKDrWatsonSize去掉就可以了,extern DWORD CEProcessorType;有这个定义的话也去掉。

接着又出现一个小问题:
大概错误是找不到KITL.DLL,所以无法生成OAL.EXE。
我不是屏蔽了嘛?
原来我在省城选项里还是选择了KITL=1,将其勾掉。
然后进行总体编译,生成OSDesign6,天啊,终于成功了!
NK.bin和NK.nb0生成了。
下面我要做的就是移植KITL,当然还要下载到板子里去试试!

忘记说了,Bootloader我直接从网上下了一个通用的,所以也就没有进行修改,后面我打算再研究下,最好再写一个NBOOT,再添加一个自己的LOGO,呵呵,先想想。
最后感谢:
wlc311,gooogleman,何宗健老师,WINCE.he前辈,QQ网名叫2008的朋友,谢谢你们给与我的帮助!

posted @ 2009-10-13 15:42 Raul.c 阅读(212) 评论(0) 编辑
WinCE6.0移植之OAL
引自:http://chenyq2008.spaces.live.com/blog/cns!F73164AC8D0D8D50!200.entry

[克隆BSP]

Clone一个BSP.

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


[移植OAL]

WinCE5.0的OAL是编译成为一个静态库oal.lib,然后与内核nk.lib静态编译成kernel.exe,也就是nk.exe. 而WinCE6.0把OAL从kernel中剥离出来单独编译成为oal.exe,内核则编译成了Kernel.dll. 分离的代价是不能再直接使用相互的资源了,即相互间的全局变量和函数不能直接访问了. OEMGLOBAL和 NKGLOBAL这2个结构体充当了OAL和Kernel的接口桥梁. 分离的好处是更方便内核独立升级(嗯哼~ 这在将来会发生么?设备的架构可是千差万别的.我想替内核升级最有可能的还是OEMs,不是MS),不过另外一个好处是接口更清晰了,内核会需要哪些OEM函数显得更直观明了.

内核的启动和原来略有不同了,简单回顾WinCE5.0的内核启动过程:

image

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

image

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

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

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

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

[编译OAL]

空谈了这么久,来做实质性的工作吧,开始编译WinCE6.0的OAL. 微软希望它的设计使得移植OAL时候尽可能少工作量,所以oal.exe分2个步骤来实现.第一步:编译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.lib和oemmain.lib是干吗的?回溯前面的启动过程吧. nkldr.lib提供了KernelStart()的实现, oemmain.lib提供了OEMInitGlobals()的实现.当然还有更多的,不罗列了.

[定制OAL]

没有oal.lib咋办?做一个吧……前面提到OAL和Kernel分离,使得接口更加明显了,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

PQOAL的oal_other.lib提供了OEMWriteDebugString(),

在OALLIB下创建debug.c ,然后实现OEMInitDebugSerial, OEMWriteDebugByte, OEMReadDebugByte, OEMWriteDebugLED这4个函数.

[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, 这个还要说啥, 挂起时候会执行这个函数. PQOAL的oal_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不只是将OAL和kernel分离.还将kitl也分离成为了kitl.dll. 所以,OAL也不能直接使用kitl的资源. 首先把kitl.c和kitl相关代码从OAL里面给放到kitl目录去.然后在OEMInit中不能调用OALKitlStart()了,用KITLIoctl(IOCTL_KITL_STARTUP, NULL, 0, NULL, 0, NULL);这一句来替代.

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

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

4. timer和timer_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就完成了.

posted @ 2009-10-13 15:30 Raul.c 阅读(111) 评论(0) 编辑
WinCE6.0驱动移植( 驱动模型变化, 以及与WinCE5.0的比较)

WinCE6.0驱动移植( 驱动模型变化, 以及与WinCE5.0的比较)

引自:http://chenyq2008.spaces.live.com/blog/cns!F73164AC8D0D8D50!205.entry

陈永强

[设备管理器]

设备管理代码在private\winceos\coreos\device\目录.右边的WinCE6.0省略INC, IROM, NOPMIF, PMIF4个目录没有列出.这些目录是头文件, io资源管理, 电源管理接口.

clip_image002

看看设备管理器的入口点devmain.c. 在WinCE5.0时代, 设备管理器是作为一个进程来实现的:devece.exe. 所以里面就是一个入口函数WinMain()调用StartDeviceManager()函数. 再看WinCE6.0, devmain.c多出来了DevMainEntry(), DllEntry(), 啊哈~ 看来设备管理器也惨遭kernel的命运.变成了device.dll了.

[设备驱动加载过程]

oal.exe加载了kernel.dll, kernel.dll加载device.dll, device.dll加载devmgr.dll, 这个就是负责加载, 卸载, 管理流驱动的. 流程比较了半天,WinCE6.0的驱动加载和WinCE5.0的加载过程没有发现什么差别.也是分为静态加载和动态加载.静态加载就是启动时候加载.设备管理器找到HKLM\Drivers\BuiltIn下BusEnum.dll加载, 这是一个总线枚举驱动, 依照ORDER值指示的加载顺序,它来完成后续的加载工作, 也是使用ActiveDevice来加载. 至于动态加载,就是在系统起来后, 使用ActiveDevice加载一个驱动.加载后,也是在注册表的Active下面显示设备信息.

驱动在注册表需要提供的信息基本是一样的, 也是Prefix, Dll, Index, Order, Iclass这些基本的都一致,关键区别在Flags, UserProcGroup这2个键.

[FLAGS:驱动加载配置]

注册表里每个驱动可以包含一个键FLAGS, 这个配置决定了驱动的加载.下面是WinCE5.0的FLAGS的可选配置,(可以多项相与得到复合值)说明如下:

DEVFLAGS_NONE

注册表没有指定FLAGS

DEVFLAGS_UNLOAD

指示设备管理器执行完Init后卸掉驱动,并且返回成功.总线枚举驱动都这么干.

DEVFLAGS_LOADLIBRARY

通知设备管理器使用LoadLibrary代替LoadDriver.2者的区别:LoadLibrary加载的可以paged out.

DEVFLAGS_NOLOAD

指示设备管理器,驱动将不会被加载.

DEVFLAGS_NAKEDENTRIES

指示设备管理器前缀不要用.可以用前缀来active,但找函数入口点时候不要用前缀. 比如电池驱动指定这个标记后,设备管理器会用BAT这个前缀去实现驱动,但在调用接口时候不会默认的用BAT_Init,.BAT_***,而是自己去找入口点. 这样的目的是可以自由修改驱动接口函数名,可以不要和前缀相同了.

DEVFLAGS_BOOTPHASE_1

要求加载驱动时候,必须BootPhase大于1. BootPhase就是启动阶段的意思. 设备管理器启动是分阶段的.BootPhase1在找注册表.;BootPhase2 加载驱动;BootPhase3开始运行.(题外话,也可以只分2个阶段.)

DEVFLAGS_IRQ_EXCLUSIVE

在访问IRQ时候再加载.

WinCE6.0在此的基础上增加了几个

DEVFLAGS_LOAD_AS_USERPROC

这个是重头戏, 指示设备管理器,把驱动给加载到user mode. 设备管理器会创建一个Reflector.这个就是WinCE6.0主要的改进了.现在我也不懂, 后面再说说这个.

DEVFLAGS_NOUNLOAD

阻止驱动被卸载.

DEVFLAGS_TRUSTEDCALLRERONLY

指示设备管理器限制驱动只能被信任的应用程序open. 在WinCE5.0的文档里面也说有这个,但代码中没有发现,所以5.0应该是没有实现.(时空错乱?还是文档设计先行?还是ms藏私货了,反正我的版本没有.)

[驱动模型]

WinCE6.0的驱动模型难道没有变化?对比WinCE5.0,所有驱动都是被Device.exe或者GWES.exe加载. 在WinCE6.0, 这二者不存在了,变成了dll被nk.exe加载,自然的想法是, 所有驱动被加载到了nk.exe的进程空间? 仅此而已?

不管怎样,先启动模拟器观察证实一下, WinCE6.0的设备只有nk.exe, shell.exe, servicesd.exe, explorer.exe, 4个udevice.exe .嗯哼~, 不止device.exe没有了, 包括filesys.exe, gwes.exe……全体阵亡了,全变成nk.exe加载的dll. udevice.exe出现4个! 直觉这是驱动. 这些现象反映到驱动模型到底有什么变化?

前面的驱动加载时候提到注册表的Flags差异和新增UserProcGroup.Flags增加了一个DEVFLAGS_LOAD_AS_USERPROC,这个选项指示设备管理器将驱动加载成为user mode driver.再看看下面在devcore.c中StartDeviceManager()的伪代码:

 

StartDeviceManager()

{

初始化设备数据结构, 启动io资源管理,pnp设备管理,电源管理

DevloadInit();// 这儿加载设备驱动.

InitUserProMgr();//CE6新增,这儿初始化 user mode driver handling

While(1)

{

      ProcessAutoDeregisterDevs();

      ProcessDyingDevs();

      ProcessDyingOpens();

}

}

 

嗯哼~ 看来还支持user mode 的驱动.既然叫user mode, 那肯定就不是加载在内核空间,不是在nk.exe空间了. 找到下面这张图, 简单明了.

clip_image004

设备管理器会依据DEVFLAGS_LOAD_AS_USERPROC的指示创建一个新的进程加载一个驱动, 这个进程就是udevice.exe了, 难怪模拟器里面有4个udevice.exe.在看左上边那个udevice.exe, 里面包含一组user-mode driver dll. 嗯哼~ 一个进程的确是可以加载多个dll的. 但哪些user mode驱动会被加载到一个udevice.exe? 呵呵, 一下就能猜到UserProcGroup这个键的作用了:给用户模式驱动分组啊, 相同组的加载到一个进程. 嗯, 顺便想起手册里面user mode driver host是什么了,用户模式驱动的寄主啊即udevice.exe.

具体怎么分组?UserProcGroup要等于什么值? 看看注册表:

[HKLM\Drivers\ProcGroup_0002]

ProcName=”servicesd.exe”

ProcVolPrefix=”$services”

ProcTimeout=20000

[HKLM\Driver\ProcGroup_0003]

ProcName=”udevice.exe”

ProcVolPrefix=”$udevice”

嗯哈~ 逻辑很简单, 在这建立一个组, 比如0003, 如果要加入这个组, 设置UserProcGroup等于这个3即可.0003只是表示代号,不是表示3个驱动哦.ProcName代表加载驱动的host进程名字. 原来udevice.exe和servicesd.exe进程是这么来的.

赶紧总结一下. 如果没有Flags指定DEVFLAGS_LOAD_AS_USERPROC, 那么驱动将被加载到nk.exe,即kernel mode driver;如果指定了,驱动将被加载到一个用户进程udevice.exe,成为user mode driver. 一个udevice.exe可以加载多个user mode driver或者只加载一个.

posted @ 2009-10-13 15:27 Raul.c 阅读(333) 评论(0) 编辑
WinCE6.0 build options
引自:http://chenyq2008.spaces.live.com/blog/cns!F73164AC8D0D8D50!208.entry

Buffer Tracked Events In RAM

选取这个, 将会在image中多出一个OSCapture.exe, 可以记录系统日志到文件

Enable Eboot Space In Memory

选这个,在os启动阶段, Eboot可以传输数据给os

Enable Event Tracking During Boot

选择这个, 系统日志跟踪启动早于内核和文件系统初始化前.

Enable Hardware-Assisted Debugging Support

新增选项.说是第三方硬件调试工具需要的(JTAG probes compiant with exdi2).管它去死.

Enable Kernel Debugger

需要kitl支持, 内核调试器. 可以step through code. 内核可以单步断点?不行吧,,,暂时还不想去调试内核.

Enable KITL

把kitl加入image.

Enable Profiling

在image增加profiler功能, 性能测试功能.

Enable Ship Build

以前看源码, 这个SHIP_BUILD宏, 会把所有的输出, RETAILMSG, DEBUGMSG都给mask掉了.

Flush Tracked Events To Release Directory

往image中加入CeLogFlush.exe, 自动把OSCapture.exe手机到的日子数据写入Celog.clg文件中.注意写入的是你的电脑release目录的文件哦?! 不知道怎么实现的.

Run-Time Image Can Be Larger Than 32MB

自己翻译

Use Xcopy Instead Of Links To Populate Release Directory

用xcopy命令替代copylink. 就是真的拷贝还是只是弄个link的区别.这个link和快捷方式应该不完全一样. 可能是linux的那样的, windows什么时候也支持link了?不知道…

Write Run-Time Image To Flash Memory

指示Eboot下载image到flash…这…到底要干吗?

对比WinCE5.0的, 少了

Enable CE Target control Support.

这个功能还是有用的啊, 没有kitl和activesync时候, 还是可以gi all一下.不过, 我在ce6上面试过了.这个功能并没有取消.可能是默认支持了.所以去掉这个

Enable Full Kernel Mode

嗯哼~. WinCE6.0的内核都重写了. 地址空间也发生天翻地覆的变化.这个肯定要去掉了.

posted @ 2009-10-13 15:24 Raul.c 阅读(126) 评论(0) 编辑
build过程
引自:http://chenyq2008.spaces.live.com/blog/cns!F73164AC8D0D8D50!335.entry
Build过程如下:1:假如cebuild.bat没有设定 -qbsp,cebuild.bat根据环境变量_DEPTREES包含的模块依次调用cebldtree.bat xxx,__QBLDPASS=preproc。2:假如cebuild.bat没有设定 -q,cebldtree.bat调用cebuild1.bat public xxx,winceos会被换成了common。否则直接跳到步骤4。3:cebuild1.bat进入xxx目录执行build。4:cebldtree.bat发现假如是winceos则调用sysgen -b __QBLDPASS;否则调用sysgen -p xxx -b __QBLDPASS。5:sysgen.bat调用%_PROJECTROOT%\oak\misc\cesysgen.bat,假如存在的话。6:cesysgen.bat直接调用%_WINCEROOT%\public\cebase\oak\misc\cesysgen.bat。7:后者cesysgen.bat把%_DEPTREES%的各个模块名加入到_REV_DEPTREES中。8:cesysgen.bat调用PlatFile,也就是%_PLATFORMROOT%\%_TGTPLAT%\cebasecesysgen.bat preproc,假如存在的话。9:BSP的cebasecesysgen.bat设置一些环境变量。10:cesysgen.bat再依次调用ProjFile,也就是_REV_DEPTREES中各个模块的xxx.bat preproc。 首先寻找__CESYSGEN_PATH\xxx.bat,也就是D:\WCE_PROGS\WM5.0\PUBLIC\smartfon\oak\MISC\xxx.bat。 其次寻找%_PUBLICROOT%\cebase\oak\misc\xxx.bat, 最后寻找%_PUBLICROOT%\xxx\cebasecesysgen.bat 这些批处理文件设置一些环境变量。11:重复步骤8~10,参数分别是pass1,pass2。12:sysgen.bat接着步骤5往下,各个%_WINCEROOT%\public\common\oak\lib\%_TGTCPU%\%WINCEDEBUG%\langid目录下假如有coreres.res,就调用bldlist langid。13:bldlist.bat把langid加进_LANGIDLIST。14:sysgen.bat进入%_PUBLICROOT%\%___PUBLICPROJECT%\cesysgen,调用nmake __QBLDPASS。15:重复步骤1~14,__QBLDPASS=postproc16:cebuild.bat调用sysgenplatform.bat %_TARGETPLATROOT% preproc17:sysgenplatform.bat调用%_PROJECTROOT%\oak\misc\cesysgen.bat,然后进入%_TARGETPLATROOT%\cesysge nnmake preproc18:cebuild.bat调用cebuild1 platform %_PLATFORMROOT%\common19:cebuild.bat调用sysgenplatform.bat %_TARGETPLATROOT% postproc20:同17,变为postproc 

 

原创粉丝点击