查看完整版本: WinCE驱动开发问题精华集锦二

zhongqian 2008-6-13 05:51 PM

WinCE驱动开发问题精华集锦二

[align=center]WinCE驱动开发问题精华集锦[/align][table=97%][tr][td=1,1,120][日期:2008-04-30][/td][td]来源:中嵌网  作者:aea22[/td][td=1,1,100][字体:[color=#0000ff]大[/color] [color=#0000ff]中[/color] [color=#0000ff]小[/color]] [/td][/tr][/table][color=#9d7f2e][font=Arial][size=2] [/size][/font][font=宋体][size=9pt]调用[/size][/font][/color][font=Arial][size=9pt]directshow[/size][/font][font=宋体][size=9pt]出现链接错误,如何解决?[/size][/font][font=Arial][size=9pt]   
player.obj : error LNK2001: unresolved external symbol _IID_IVideoWindow  
player.obj : error LNK2001: unresolved external symbol _IID_IMediaControl  

[/size][/font][font=宋体][size=9pt]这是因为链接器没有找到合适的[/size][/font][font=Arial][size=9pt].lib[/size][/font][font=宋体][size=9pt]文件。两种办法:[/size][/font][font=Arial][size=9pt]  
1[/size][/font][font=宋体][size=9pt]、在[/size][/font][font=Arial][size=9pt]EVC[/size][/font][font=宋体][size=9pt]菜单[/size][/font][font=Arial][size=9pt]Tools—options—directories [/size][/font][font=宋体][size=9pt]里把[/size][/font][font=Arial][size=9pt]library files[/size][/font][font=宋体][size=9pt]的路径重新调整一下。如果你只安装了[/size][/font][font=Arial][size=9pt]EVC[/size][/font][font=宋体][size=9pt]自带的[/size][/font][font=Arial][size=9pt] Standard SDK[/size][/font][font=宋体][size=9pt]而没有其它[/size][/font][font=Arial][size=9pt]SDK[/size][/font][font=宋体][size=9pt],可以指定[/size][/font][font=Arial][size=9pt]WINCE[/size][/font][font=宋体][size=9pt]目录中的[/size][/font][font=Arial][size=9pt].lib[/size][/font][font=宋体][size=9pt]文件路径,例如[/size][/font][font=Arial][size=9pt]D:\WINCE500\PUBLIC\DIRECTX\ OAK\LIB\X86\RETAIL[/size][/font][font=宋体][size=9pt]。注意[/size][/font][font=Arial][size=9pt]CPU[/size][/font][font=宋体][size=9pt]的类型。[/size][/font][font=Arial][size=9pt]  
2[/size][/font][font=宋体][size=9pt]、安装[/size][/font][font=Arial][size=9pt]SDK[/size][/font][font=宋体][size=9pt],前提是导出[/size][/font][font=Arial][size=9pt]SDK[/size][/font][font=宋体][size=9pt]的[/size][/font][font=Arial][size=9pt]PB[/size][/font][font=宋体][size=9pt]内核工程必须包括[/size][/font][font=Arial][size=9pt]DirectShow[/size][/font][font=宋体][size=9pt]或者其它组件。[/size][/font]
[font=宋体][size=9pt]在[/size][/font][font=Arial][size=9pt]PB[/size][/font][font=宋体][size=9pt]的[/size][/font][font=Arial][size=9pt]config.bib[/size][/font][font=宋体][size=9pt]文件中,[/size][/font][font=Arial][size=9pt]“IMGFLASH”[/size][/font][font=宋体][size=9pt]表示什么意思呢?[/size][/font]
[font=宋体][size=9pt]表示能够刷[/size][/font][font=Arial][size=9pt]NK[/size][/font][font=宋体][size=9pt]到[/size][/font][font=Arial][size=9pt]ROM[/size][/font][font=宋体][size=9pt]中,具体请查看标题为[/size][/font][font=Arial][size=9pt]“IMG Environment Variables”[/size][/font][font=宋体][size=9pt]的帮助文档。[/size][/font][font=Arial][size=9pt]  
  
x86[/size][/font][font=宋体][size=9pt]平台如何映射各种地址空间?如何编写中断服务例程?[/size][/font]
[font=宋体][size=9pt]如果是[/size][/font][font=Arial][size=9pt]x86[/size][/font][font=宋体][size=9pt]平台,可以调用[/size][/font][font=Arial][size=9pt]HalTranslateBusAddress[/size][/font][font=宋体][size=9pt]转换物理总线地址到物理系统地址,调用[/size][/font][font=Arial][size=9pt] HalTranslateSystemAddress[/size][/font][font=宋体][size=9pt]转换物理系统地址到逻辑总线地址,也可以不调用这两个函数,因为[/size][/font][font=Arial][size=9pt]x86[/size][/font][font=宋体][size=9pt]平台除[/size][/font][font=Arial][size=9pt]32[/size][/font][font=宋体][size=9pt]位物理地址外还有[/size][/font][font=Arial][size=9pt] 16[/size][/font][font=宋体][size=9pt]位的[/size][/font][font=Arial][size=9pt]IO[/size][/font][font=宋体][size=9pt]地址空间,对于[/size][/font][font=Arial][size=9pt]16[/size][/font][font=宋体][size=9pt]位的[/size][/font][font=Arial][size=9pt]IO[/size][/font][font=宋体][size=9pt]地址空间,可以直接调用[/size][/font][font=Arial][size=9pt]WRITE_PORT_UCHAR[/size][/font][font=宋体][size=9pt]或者[/size][/font][font=Arial][size=9pt]READ_PORT_UCHAR[/size][/font][font=宋体][size=9pt]等函数直接读写端口。对于[/size][/font][font=Arial][size=9pt]32[/size][/font][font=宋体][size=9pt]位物理地址可以调用[/size][/font][font=Arial][size=9pt]VirtualAlloc[/size][/font][font=宋体][size=9pt]和[/size][/font][font=Arial][size=9pt]VirtualCopy[/size][/font][font=宋体][size=9pt]来映射。这样做思路清晰,简单明了。[/size][/font]
[font=宋体][size=9pt]在[/size][/font][font=Arial][size=9pt]x86[/size][/font][font=宋体][size=9pt]平台要实现[/size][/font][font=Arial][size=9pt]ISR[/size][/font][font=宋体][size=9pt],有如下几个步骤(以[/size][/font][font=Arial][size=9pt]Geode BSP[/size][/font][font=宋体][size=9pt]为例):[/size][/font][font=Arial][size=9pt]  
1[/size][/font][font=宋体][size=9pt]、用[/size][/font][font=Arial][size=9pt]SETUP_INTERRUPT_MAP[/size][/font][font=宋体][size=9pt]宏关联[/size][/font][font=Arial][size=9pt]SYSINTR[/size][/font][font=宋体][size=9pt]和[/size][/font][font=Arial][size=9pt]IRQ[/size][/font][font=宋体][size=9pt]。以[/size][/font][font=Arial][size=9pt]“SYSINTR_”[/size][/font][font=宋体][size=9pt]为前缀的常量由内核使用,用于唯一标识发生中断的硬件,又称为中断[/size][/font][font=Arial][size=9pt]ID[/size][/font][font=宋体][size=9pt]。在[/size][/font][font=Arial][size=9pt]Nkintr.h[/size][/font][font=宋体][size=9pt]文件中预定义了一些[/size][/font][font=Arial][size=9pt]SYSINTR[/size][/font][font=宋体][size=9pt],[/size][/font][font=Arial][size=9pt]OEM[/size][/font][font=宋体][size=9pt]可以在[/size][/font][font=Arial][size=9pt]Oalintr.h[/size][/font][font=宋体][size=9pt]文件中自定义[/size][/font][font=Arial][size=9pt]SYSINTR[/size][/font][font=宋体][size=9pt]。[/size][/font][font=Arial][size=9pt]  
2[/size][/font][font=宋体][size=9pt]、用[/size][/font][font=Arial][size=9pt]HookInterrupt[/size][/font][font=宋体][size=9pt]函数关联硬件中断号和[/size][/font][font=Arial][size=9pt]ISR[/size][/font][font=宋体][size=9pt]。这里提到的硬件中断号为物理中断号,[/size][/font][font=Arial][size=9pt]IRQ[/size][/font][font=宋体][size=9pt]为逻辑中断号。在[/size][/font][font=Arial][size=9pt]InitPICs[/size][/font][font=宋体][size=9pt]函数的最后调用了[/size][/font][font=Arial][size=9pt]HookInterrupt[/size][/font][font=宋体][size=9pt]函数,如下:[/size][/font][font=Arial][size=9pt]  
for (i = 64; i < 80; i++)  
HookInterrupt(i, (void *)PeRPISR);  ///[/size][/font][font=宋体][size=9pt]用[/size][/font][font=Arial][size=9pt]ISR[/size][/font][font=宋体][size=9pt]关联[/size][/font][font=Arial][size=9pt]16[/size][/font][font=宋体][size=9pt]个中断号[/size][/font][font=Arial][size=9pt]   
3[/size][/font][font=宋体][size=9pt]、调用[/size][/font][font=Arial][size=9pt]InterruptInitialize[/size][/font][font=宋体][size=9pt]函数关联[/size][/font][font=Arial][size=9pt]SYSINTR[/size][/font][font=宋体][size=9pt]和[/size][/font][font=Arial][size=9pt]IST[/size][/font][font=宋体][size=9pt]创建的事件对象,也是[/size][/font][font=Arial][size=9pt]IST[/size][/font][font=宋体][size=9pt]等待的事件对象。详细内容请参考[/size][/font][font=Arial][size=9pt]Geode BSP[/size][/font][font=宋体][size=9pt]源码。[/size][/font]
[font=宋体][size=9pt]在[/size][/font][font=Arial][size=9pt]x86 [/size][/font][font=宋体][size=9pt]平台要实现可安装[/size][/font][font=Arial][size=9pt]ISR[/size][/font][font=宋体][size=9pt],先调用[/size][/font][font=Arial][size=9pt]LoadIntChainHandler[/size][/font][font=宋体][size=9pt]函数注册在注册表中指定的[/size][/font][font=Arial][size=9pt]ISR DLL[/size][/font][font=宋体][size=9pt],然后填充[/size][/font][font=Arial][size=9pt]GIISR_INFO[/size][/font][font=宋体][size=9pt]结构体并调用[/size][/font][font=Arial][size=9pt]KernelLibIoControl[/size][/font][font=宋体][size=9pt]函数将此结构体传递给可安装[/size][/font][font=Arial][size=9pt]ISR[/size][/font][font=宋体][size=9pt]。详细内容请参考[/size][/font][font=Arial][size=9pt]WINCE[/size][/font][font=宋体][size=9pt]帮助文档或者我著的《[/size][/font][font=Arial][size=9pt]Windows CE[/size][/font][font=宋体][size=9pt]下驱动开发基础》。[/size][/font]
[font=宋体][size=9pt]修改了[/size][/font][font=Arial][size=9pt]WINCE[/size][/font][font=宋体][size=9pt]自带的驱动程序后如何编译?如果是自己开发的驱动程序如何编译?[/size][/font][font=Arial][size=9pt]  
1[/size][/font][font=宋体][size=9pt]、分为[/size][/font][font=Arial][size=9pt]IDE[/size][/font][font=宋体][size=9pt]方式和命令行方式。[/size][/font][font=Arial][size=9pt]  
IDE [/size][/font][font=宋体][size=9pt]方式的编译很简单,以[/size][/font][font=Arial][size=9pt]PB5.0[/size][/font][font=宋体][size=9pt]为例,打开定制内核的工程,在左边的[/size][/font][font=Arial][size=9pt]“workspace”—“FileView”[/size][/font][font=宋体][size=9pt]中找到你已经修改了的目录,然后单击右键弹出菜单,在菜单中选择[/size][/font][font=Arial][size=9pt]“Build and Sysgen Current Project”[/size][/font][font=宋体][size=9pt],这样[/size][/font][font=Arial][size=9pt]PB[/size][/font][font=宋体][size=9pt]就会编译指定的目录中的项目源码文件,然后执行[/size][/font][font=Arial][size=9pt]sysgen[/size][/font][font=宋体][size=9pt]命令根据[/size][/font][font=Arial][size=9pt]source[/size][/font][font=宋体][size=9pt]文件中的内容生成目标文件并复制到当前内核工程目录下。[/size][/font]
[font=宋体][size=9pt]命令行方式的编译需要打开[/size][/font][font=Arial][size=9pt]“Build OS” —“Open Release Directory”[/size][/font][font=宋体][size=9pt],以[/size][/font][font=Arial][size=9pt]cd[/size][/font][font=宋体][size=9pt]命令进入你已经修改的驱动程序目录中,然后键入[/size][/font][font=Arial][size=9pt]“build –cfs”[/size][/font][font=宋体][size=9pt],然后键入[/size][/font][font=Arial][size=9pt] “sysgen –p [/size][/font][font=宋体][size=9pt]项目名称[/size][/font][font=Arial][size=9pt]”[/size][/font][font=宋体][size=9pt],一般项目名称为[/size][/font][font=Arial][size=9pt]source[/size][/font][font=宋体][size=9pt]文件中的[/size][/font][font=Arial][size=9pt]“TARGETNAME”[/size][/font][font=宋体][size=9pt]。[/size][/font][font=Arial][size=9pt]  
2[/size][/font][font=宋体][size=9pt]、如果想完全自己开发驱动程序,建议直接采用[/size][/font][font=Arial][size=9pt]EVC[/size][/font][font=宋体][size=9pt]或者[/size][/font][font=Arial][size=9pt]PB[/size][/font][font=宋体][size=9pt]来编写编译。[/size][/font]
[font=宋体][size=9pt]开发[/size][/font][font=Arial][size=9pt]PCI[/size][/font][font=宋体][size=9pt]设备驱动时,[/size][/font][font=Arial][size=9pt]InterruptInitialize[/size][/font][font=宋体][size=9pt]函数的第一参数是否是[/size][/font][font=Arial][size=9pt]PCI[/size][/font][font=宋体][size=9pt]卡配置空间信息中的[/size][/font][font=Arial][size=9pt]InterruptLine [/size][/font][font=宋体][size=9pt]参数?是否需要在[/size][/font][font=Arial][size=9pt]HKLM\Drivers\BuiltIn\PCI\Template [/size][/font][font=宋体][size=9pt]加一個自己的[/size][/font][font=Arial][size=9pt] subkey[/size][/font][font=宋体][size=9pt],并填写相应内容?如何填?[/size][/font][font=Arial][size=9pt]  
1[/size][/font][font=宋体][size=9pt]、[/size][/font][font=Arial][size=9pt]InterruptInitialize[/size][/font][font=宋体][size=9pt]的第一参数是[/size][/font][font=Arial][size=9pt]IRQ[/size][/font][font=宋体][size=9pt],也就是逻辑中断号,而不是物理中断号,[/size][/font][font=Arial][size=9pt]InterruptLine[/size][/font][font=宋体][size=9pt]是指物理中断号[/size][/font][font=Arial][size=9pt]  
2[/size][/font][font=宋体][size=9pt]、需要在[/size][/font][font=Arial][size=9pt]template[/size][/font][font=宋体][size=9pt]下加自己的[/size][/font][font=Arial][size=9pt]PCI[/size][/font][font=宋体][size=9pt]设备的信息,例如:[/size][/font][font=Arial][size=9pt]  
   [HKEY_LOCAL_MACHINE\Drivers\PCI\Template\Serial]  
    "Dll"="Com16550.Dll"  
    "Class"=dword:07  
    "SubClass"=dword:00  
    "ProgIF"=dword:02  
    "VendorID"=multi_sz:"0AF0","B320","B320"  
    "DeviceID"=multi_sz:"0020","0300","0302"  
    "Prefix"="COM"  
[/size][/font][font=宋体][size=9pt]而这些信息就来自于你执行[/size][/font][font=Arial][size=9pt]pcienum.exe[/size][/font][font=宋体][size=9pt]的结果。[/size][/font]
[font=宋体][size=9pt]编译器报错:[/size][/font][font=Arial][size=9pt]error C2065: ''CFileFind'' : undeclared identifier[/size][/font][font=宋体][size=9pt],如何解决?[/size][/font][font=Arial][size=9pt]  
MFC for WINCE[/size][/font][font=宋体][size=9pt]版本没有[/size][/font][font=Arial][size=9pt]CFileFind[/size][/font][font=宋体][size=9pt]类,所以要查找文件只能调用[/size][/font][font=Arial][size=9pt]API FindFirstFile [/size][/font][font=宋体][size=9pt]和[/size][/font][font=Arial][size=9pt]FindNextFile[/size][/font][font=宋体][size=9pt]。[/size][/font]
[font=宋体][size=9pt]如何设置[/size][/font][font=Arial][size=9pt]WINCE[/size][/font][font=宋体][size=9pt]系统字体、字号?如何设置自己开发的软件的字体、字号?[/size][/font][font=Arial][size=9pt]  
1[/size][/font][font=宋体][size=9pt]、系统字体通过注册表设置。如下:[/size][/font][font=Arial][size=9pt]  
[HKEY_LOCAL_MACHINE\System\GDI\SysFnt]   ///[/size][/font][font=宋体][size=9pt]系统字体[/size][/font][font=Arial][size=9pt]  
Wt=420  
Ht=18  
Nm=Arial  
[HKEY_LOCAL_MACHINE\System\GWE\Menu\BarFnt]   ///[/size][/font][font=宋体][size=9pt]菜单栏字体[/size][/font][font=Arial][size=9pt]  
[HKEY_LOCAL_MACHINE\System\GWE\Menu\PopFnt]   ///[/size][/font][font=宋体][size=9pt]弹出窗口字体[/size][/font][font=Arial][size=9pt]  
[HKEY_LOCAL_MACHINE\System\GWE\Menu]         ///[/size][/font][font=宋体][size=9pt]菜单字体[/size][/font][font=Arial][size=9pt]  
HKEY_LOCAL_MACHINE\System\GWE\Button          ///[/size][/font][font=宋体][size=9pt]按钮字体[/size][/font][font=Arial][size=9pt]  
2[/size][/font][font=宋体][size=9pt]、创建字体时把字体高度参数设置大点就可以了。如[/size][/font][font=Arial][size=9pt]CFont::CreateFont(nHeight,...)[/size][/font][font=宋体][size=9pt],也可以在[/size][/font][font=Arial][size=9pt]LOGFONT[/size][/font][font=宋体][size=9pt]结构中设置字体高度或者字体种类。如果是控件,调用控件的[/size][/font][font=Arial][size=9pt]SetFont[/size][/font][font=宋体][size=9pt]成员函数。如果是直接画,在[/size][/font][font=Arial][size=9pt]OnPaint[/size][/font][font=宋体][size=9pt]响应函数中调用[/size][/font][font=Arial][size=9pt]SelectObject[/size][/font][font=宋体][size=9pt]选字体到[/size][/font][font=Arial][size=9pt]DC[/size][/font][font=宋体][size=9pt]。[/size][/font][font=Arial][size=9pt]   
  
nk.bin[/size][/font][font=宋体][size=9pt]和[/size][/font][font=Arial][size=9pt]nk.nb0[/size][/font][font=宋体][size=9pt]有什么区别?[/size][/font]
[font=宋体][size=9pt]这里提到的[/size][/font][font=Arial][size=9pt]bin[/size][/font][font=宋体][size=9pt]是一种二进制镜像格式,以片断([/size][/font][font=Arial][size=9pt]section[/size][/font][font=宋体][size=9pt])为单位组织数据,每个片断都包括一个头,头里指定了起始地址,长度,校验值。[/size][/font][font=Arial][size=9pt]Platform Builder[/size][/font][font=宋体][size=9pt]调用工具将[/size][/font][font=Arial][size=9pt]WINCE[/size][/font][font=宋体][size=9pt]内核所有文件以[/size][/font][font=Arial][size=9pt]bin[/size][/font][font=宋体][size=9pt]格式合并成一个文件,默认文件名为[/size][/font][font=Arial][size=9pt]nk.bin[/size][/font][font=宋体][size=9pt]。[/size][/font][font=Arial][size=9pt]BootLoader[/size][/font][font=宋体][size=9pt]又以同样的格式将[/size][/font][font=Arial][size=9pt]nk.bin[/size][/font][font=宋体][size=9pt]分解成多个文件放到[/size][/font][font=Arial][size=9pt]RAM[/size][/font][font=宋体][size=9pt]中。可以在命令行中键入[/size][/font][font=Arial][size=9pt] “viewbin nk.bin”[/size][/font][font=宋体][size=9pt]来查看[/size][/font][font=Arial][size=9pt]bin[/size][/font][font=宋体][size=9pt]文件中具体包括了哪些内容。键入[/size][/font][font=Arial][size=9pt]Cvrtbin[/size][/font][font=宋体][size=9pt]命令转换[/size][/font][font=Arial][size=9pt].bin[/size][/font][font=宋体][size=9pt]格式文件为[/size][/font][font=Arial][size=9pt].sre[/size][/font][font=宋体][size=9pt]格式或者[/size][/font][font=Arial][size=9pt].abx[/size][/font][font=宋体][size=9pt]格式。[/size][/font][font=Arial][size=9pt]   
nb0[/size][/font][font=宋体][size=9pt]格式是原始的二进制镜像,它不包括头,一般情况下将内核下载到设备的[/size][/font][font=Arial][size=9pt]RAM[/size][/font][font=宋体][size=9pt]中运行都采用[/size][/font][font=Arial][size=9pt]nb0[/size][/font][font=宋体][size=9pt]格式。要生成[/size][/font][font=Arial][size=9pt]nbx[/size][/font][font=宋体][size=9pt]格式的文件,需要在相关[/size][/font][font=Arial][size=9pt].bib[/size][/font][font=宋体][size=9pt]文件中确定如下值:[/size][/font][font=Arial][size=9pt]ROMSTART[/size][/font][font=宋体][size=9pt]、[/size][/font][font=Arial][size=9pt]ROMWIDTH[/size][/font][font=宋体][size=9pt]、[/size][/font][font=Arial][size=9pt]ROMSIZE[/size][/font][font=宋体][size=9pt]。[/size][/font]
[font=宋体][size=9pt]在不采用硬件计时器的情况下如何创建更精确的计时器?最精确周期能否达到[/size][/font][font=Arial][size=9pt]1[/size][/font][font=宋体][size=9pt]毫秒?[/size][/font]
[font=宋体][size=9pt]对于精确值的要求不同,所采用的办法不同。以下阐述几种办法。[/size][/font][font=Arial][size=9pt]  
1[/size][/font][font=宋体][size=9pt]、在单线程中循环调用[/size][/font][font=Arial][size=9pt]API Sleep[/size][/font][font=宋体][size=9pt]函数,[/size][/font][font=Arial][size=9pt]Sleep[/size][/font][font=宋体][size=9pt]函数精确程度为如果[/size][/font][font=Arial][size=9pt]Sleep(N)[/size][/font][font=宋体][size=9pt],那么实际睡眠时间在[/size][/font][font=Arial][size=9pt]N[/size][/font][font=宋体][size=9pt]到[/size][/font][font=Arial][size=9pt]N+1[/size][/font][font=宋体][size=9pt]毫秒之间。而且还要注意调用[/size][/font][font=Arial][size=9pt]Sleep[/size][/font][font=宋体][size=9pt]的线程优先级的问题。如果任务过多并且此线程优先级低,那误差就更大些。[/size][/font][font=Arial][size=9pt]  
2[/size][/font][font=宋体][size=9pt]、调用[/size][/font][font=Arial][size=9pt]API QueryPerformanceCounter[/size][/font][font=宋体][size=9pt]函数,举例如下:[/size][/font][font=Arial][size=9pt]  
LARGE_INTEGER  liFrequency;  
if (QueryPerformanceFrequency(&liFrequency))  // [/size][/font][font=宋体][size=9pt]查询系统时钟的频率,这里将返回[/size][/font][font=Arial][size=9pt]1000  
{  
   liFrequency.QuadPart /= 1000;     
   LARGE_INTEGER  liTimeOut;     
   if (QueryPerformanceCounter(&liTimeOut))   //[/size][/font][font=宋体][size=9pt]得到截至到当前累计发生的系统时钟中断次数[/size][/font][font=Arial][size=9pt]  
   {  
      liTimeOut.QuadPart += liFrequency.QuadPart;   ///[/size][/font][font=宋体][size=9pt]计算下一秒到来时总的中断次数是多少[/size][/font][font=Arial][size=9pt]  
      LARGE_INTEGER  liCurrent;  
      do  
      {           
         QueryPerformanceCounter(&liCurrent);    // [/size][/font][font=宋体][size=9pt]循环查询累计的的中断次数[/size][/font][font=Arial][size=9pt]  
      } while (liCurrent.QuadPart < liTimeOut.QuadPart); ///[/size][/font][font=宋体][size=9pt]到达下一秒[/size][/font][font=Arial][size=9pt]  
   }  
}  
[/size][/font][font=宋体][size=9pt]调用[/size][/font][font=Arial][size=9pt]QueryPerformanceCounter[/size][/font][font=宋体][size=9pt]同调用[/size][/font][font=Arial][size=9pt]Sleep[/size][/font][font=宋体][size=9pt]在本质上都是一样的,都是在单线程中无限循环等到周期一到执行任务,相比较[/size][/font][font=Arial][size=9pt] QueryPerformanceCounter[/size][/font][font=宋体][size=9pt]要比[/size][/font][font=Arial][size=9pt]Sleep[/size][/font][font=宋体][size=9pt]更精确些,越精确就越要求线程的优先级,保障线程能够正常得到处理器。[/size][/font][font=Arial][size=9pt]  
3[/size][/font][font=宋体][size=9pt]、以上办法难以保证周期精确到[/size][/font][font=Arial][size=9pt]1[/size][/font][font=宋体][size=9pt]毫秒并且[/size][/font][font=Arial][size=9pt]WINCE[/size][/font][font=宋体][size=9pt]系统稳定地运行,所以要从中断入手。以[/size][/font][font=Arial][size=9pt]x86[/size][/font][font=宋体][size=9pt]平台为例,先在[/size][/font][font=Arial][size=9pt]Timer.c[/size][/font][font=宋体][size=9pt]中将默认的[/size][/font][font=Arial][size=9pt]SetTimer0 (TIMER_COUNT)[/size][/font][font=宋体][size=9pt]中的[/size][/font][font=Arial][size=9pt]TIMER_COUNT /[/size][/font][font=宋体][size=9pt]=[/size][/font][font=Arial][size=9pt]2[/size][/font][font=宋体][size=9pt],[/size][/font][font=Arial][size=9pt]SetTimer0[/size][/font][font=宋体][size=9pt]函数负责设置系统时钟的频率,默认[/size][/font][font=Arial][size=9pt]1[/size][/font][font=宋体][size=9pt]毫秒发生一次中断,如果除以[/size][/font][font=Arial][size=9pt]2[/size][/font][font=宋体][size=9pt]就是[/size][/font][font=Arial][size=9pt]0.5[/size][/font][font=宋体][size=9pt]毫秒发生一次中断。然后在[/size][/font][font=Arial][size=9pt]fwpc.c[/size][/font][font=宋体][size=9pt]文件中修改[/size][/font][font=Arial][size=9pt]ISR[/size][/font][font=宋体][size=9pt]函数[/size][/font][font=Arial][size=9pt]PeRPISR[/size][/font][font=宋体][size=9pt],因为原来默认是[/size][/font][font=Arial][size=9pt]1[/size][/font][font=宋体][size=9pt]毫秒发生一次中断,在处理[/size][/font][font=Arial][size=9pt]INTR_TIMER0[/size][/font][font=宋体][size=9pt]时系统负责累计计数、管理线程的调度,返回相应的[/size][/font][font=Arial][size=9pt]SYSINTR[/size][/font][font=宋体][size=9pt]值,而我们没有办法再添加代码返回自己定义的[/size][/font][font=Arial][size=9pt]SYSINTR[/size][/font][font=宋体][size=9pt]值,所以现在要修改原来的处理代码,例如设置一个[/size][/font][font=Arial][size=9pt]BOOL[/size][/font][font=宋体][size=9pt]型变量,[/size][/font][font=Arial][size=9pt]TRUE[/size][/font][font=宋体][size=9pt]就执行原来默认的代码,而[/size][/font][font=Arial][size=9pt]FALSE[/size][/font][font=宋体][size=9pt]就返回我们自己定义的[/size][/font][font=Arial][size=9pt]SYSINTR[/size][/font][font=宋体][size=9pt]值,这样即不影响原来的[/size][/font][font=Arial][size=9pt]ISR[/size][/font][font=宋体][size=9pt]处理,又加入了我们的中断响应代码。[/size][/font][font=Arial][size=9pt]ISR[/size][/font][font=宋体][size=9pt]返回我们定义的[/size][/font][font=Arial][size=9pt]SYSINTR[/size][/font][font=宋体][size=9pt]后[/size][/font][font=Arial][size=9pt]WINCE[/size][/font][font=宋体][size=9pt]内核激活相对应的[/size][/font][font=Arial][size=9pt]EVENT[/size][/font][font=宋体][size=9pt]事件,我们就可以在我们编写的[/size][/font][font=Arial][size=9pt]IST[/size][/font][font=宋体][size=9pt]里处理任务了。[/size][/font][font=Arial][size=9pt]  
  
flash[/size][/font][font=宋体][size=9pt]中存放了[/size][/font][font=Arial][size=9pt]BootLoader[/size][/font][font=宋体][size=9pt]和内核镜像,如何把剩余[/size][/font][font=Arial][size=9pt]flash[/size][/font][font=宋体][size=9pt]部分划分为一个存储区域供应用程序读写?[/size][/font]
[font=宋体][size=9pt]以[/size][/font][font=Arial][size=9pt]WINCE [/size][/font][font=宋体][size=9pt]提供的驱动([/size][/font][font=Arial][size=9pt]FAT[/size][/font][font=宋体][size=9pt]文件系统和[/size][/font][font=Arial][size=9pt]MSFLASH[/size][/font][font=宋体][size=9pt]驱动)来举例说明。如果采用默认[/size][/font][font=Arial][size=9pt]common.reg[/size][/font][font=宋体][size=9pt]中的注册表设置,那么[/size][/font][font=Arial][size=9pt]MSFLASH[/size][/font][font=宋体][size=9pt]驱动默认把整个[/size][/font][font=Arial][size=9pt] flash[/size][/font][font=宋体][size=9pt]作为存储区域来读写,这不符合问题的要求,所以必须告诉[/size][/font][font=Arial][size=9pt]MSFLASH[/size][/font][font=宋体][size=9pt]驱动程序可供读写的区域的起始地址和长度。以下是一个注册表例子:[/size][/font][font=Arial][size=9pt]  
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\FASLD]  
    "Dll"="fasld.dll"        ///[/size][/font][font=宋体][size=9pt]实际[/size][/font][font=Arial][size=9pt]Flash[/size][/font][font=宋体][size=9pt]存储器的驱动程序[/size][/font][font=Arial][size=9pt]  
    "Order"=dword:2       ///[/size][/font][font=宋体][size=9pt]该驱动程序相对于其它驱动程序的加载顺序[/size][/font][font=Arial][size=9pt]  
    "Prefix"="DSK"        ///[/size][/font][font=宋体][size=9pt]前缀[/size][/font][font=Arial][size=9pt]  
    "Ioctl"=dword:4        ///IOCTL[/size][/font][font=宋体][size=9pt]码,设备管理器加载驱动的时候调用[/size][/font][font=Arial][size=9pt]IOControl[/size][/font][font=宋体][size=9pt]函数,传递这个[/size][/font][font=Arial][size=9pt]IOCTL[/size][/font][font=宋体][size=9pt]码。[/size][/font][font=Arial][size=9pt]  
"Profile"="MSFlash"    ///Profile[/size][/font][font=宋体][size=9pt]名称,也就是[/size][/font][font=Arial][size=9pt][HLM\System\StorageManager\Profiles\MSFlash]  
///[/size][/font][font=宋体][size=9pt]当设备管理器加载此驱动程序的同时发送通知给系统,[/size][/font][font=Arial][size=9pt]IClass[/size][/font][font=宋体][size=9pt]([/size][/font][font=Arial][size=9pt]GUID[/size][/font][font=宋体][size=9pt])的值表明这是一个存储设备的驱动程序。[/size][/font][font=Arial][size=9pt]  
"IClass"="{A4E7EDDA-E575-4252-9D6B-4195D48BB865}"     
    "MemBase"=dword:00000000    ///Flash[/size][/font][font=宋体][size=9pt]中可供读写区域的起始物理地址,也就是[/size][/font][font=Arial][size=9pt]Flash[/size][/font][font=宋体][size=9pt]的首地址[/size][/font][font=Arial][size=9pt]+[/size][/font][font=宋体][size=9pt]偏移量[/size][/font][font=Arial][size=9pt]  
    "MemLen"=dword:00000000     ///Flash[/size][/font][font=宋体][size=9pt]中可供读写区域的长度[/size][/font][font=Arial][size=9pt]  
[HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\MSFlash]  
    "DefaultFileSystem"="FATFS"   ///MSFlash[/size][/font][font=宋体][size=9pt]驱动默认采用的文件系统[/size][/font][font=Arial][size=9pt]  
    "PartitionDriver"="mspart.dll"    ///[/size][/font][font=宋体][size=9pt]采用的分区驱动程序[/size][/font][font=Arial][size=9pt]  
    "MountAsRoot"=dword:1        ///[/size][/font][font=宋体][size=9pt]此目录作为文件系统的根目录[/size][/font][font=Arial][size=9pt]  
    "Folder"="NOR Flash"          ///[/size][/font][font=宋体][size=9pt]目录名称[/size][/font][font=Arial][size=9pt]  
    "Name"="FLASH Disk Block Device"   ///Flash[/size][/font][font=宋体][size=9pt]驱动名称[/size][/font][font=Arial][size=9pt]  
"PartitionDriverName"="MSPART" ///[/size][/font][font=宋体][size=9pt]分区驱动名称[/size][/font][font=Arial][size=9pt]  
"AutoMount"=dword:1         ///[/size][/font][font=宋体][size=9pt]自动装载检测到的分区[/size][/font][font=Arial][size=9pt]  
    "AutoPart"=dword:1            ///[/size][/font][font=宋体][size=9pt]自动分区[/size][/font][font=Arial][size=9pt]  
    "AutoFormat"=dword:1          ///[/size][/font][font=宋体][size=9pt]自动格式化分区[/size][/font][font=Arial][size=9pt]  
[HKEY_LOCAL_MACHINE\System\StorageManager\AutoLoad\MSFlash]  
    "DriverPath"="Drivers\\BuiltIn\\FASLD"    ///Flash[/size][/font][font=宋体][size=9pt]驱动在注册表中的位置[/size][/font][font=Arial][size=9pt]  
    "LoadFlags"=dword:1                 ///[/size][/font][font=宋体][size=9pt]这个值可以被设置为[/size][/font][font=Arial][size=9pt]0[/size][/font][font=宋体][size=9pt]、[/size][/font][font=Arial][size=9pt]1[/size][/font][font=宋体][size=9pt]、[/size][/font][font=Arial][size=9pt]2[/size][/font][font=宋体][size=9pt]。[/size][/font][font=Arial][size=9pt]1[/size][/font][font=宋体][size=9pt]表示同步加载,其它表示异步加载[/size][/font][font=Arial][size=9pt]  
    "Order"=dword:0  
[HKEY_LOCAL_MACHINE\System\StorageManager\FATFS]  
    "FriendlyName"="FAT FileSystem"    ///[/size][/font][font=宋体][size=9pt]文件系统名称[/size][/font][font=Arial][size=9pt]  
    "Dll"="fatfsd.dll"                   ///[/size][/font][font=宋体][size=9pt]文件系统驱动程序[/size][/font][font=Arial][size=9pt]  
    "Flags"=dword:00000064             ///[/size][/font][font=宋体][size=9pt]标志,详见帮助文档[/size][/font][font=Arial][size=9pt]  
    "Paging"=dword:1                   ///[/size][/font][font=宋体][size=9pt]是否分页[/size][/font][font=Arial][size=9pt]  
    "EnableCache"=dword:1              ///[/size][/font][font=宋体][size=9pt]是否允许缓存数据[/size][/font][font=Arial][size=9pt]  
    "CacheSize"=dword:0                ///[/size][/font][font=宋体][size=9pt]指定缓存大小,[/size][/font][font=Arial][size=9pt]0[/size][/font][font=宋体][size=9pt]表示默认[/size][/font]
[font=宋体][size=9pt]驱动程序如何发通知给应用程序?[/size][/font]
[font=宋体][size=9pt]这里介绍一下常见的两种办法。[/size][/font][font=Arial][size=9pt]  
1[/size][/font][font=宋体][size=9pt]、驱动程序调用[/size][/font][font=Arial][size=9pt]API SendNotifyMessage[/size][/font][font=宋体][size=9pt],发送特定的消息给应用程序,这就要求应用程序要有消息循环机制并且要事先做好消息的处理。参数[/size][/font][font=Arial][size=9pt] 1[/size][/font][font=宋体][size=9pt]为窗口句柄,可以设置[/size][/font][font=Arial][size=9pt]HWND_BROADCAST[/size][/font][font=宋体][size=9pt]表示广播消息。要注意的是不要在参数中传递指针(虚拟地址),因为执行驱动程序的线程和应用程序并不在同一个进程空间中。解决办法可以利用内存映射文件技术,比如在驱动程序中创建一个内存映射文件对象,申请一块物理内存,然后把对象名称和内存长度传递给应用程序,应用程序打开同名的内存映射文件对象,读取里面的数据。对象名称可以事先协定好,也可以通过注册表来传递,内存长度是[/size][/font][font=Arial][size=9pt]32[/size][/font][font=宋体][size=9pt]位值,通过消息参数就可以传递,也可以通过注册表来传递。另外一种解决办法是在定制内核时候预留一块物理内存,这样驱动程序和应用程序都可以通过[/size][/font][font=Arial][size=9pt]VirtualAlloc[/size][/font][font=宋体][size=9pt]和[/size][/font][font=Arial][size=9pt] VirtualCopy[/size][/font][font=宋体][size=9pt]来映射到同一块物理内存,其原理同内存映射文件技术一样,但是这块物理内存不具备通用性。最后一个办法是应用程序事先将一个缓冲区地址传递给驱动程序,驱动程序调用[/size][/font][font=Arial][size=9pt]MapPtrToProcess[/size][/font][font=宋体][size=9pt]映射应用程序传递过来的地址,当驱动程序调用[/size][/font][font=Arial][size=9pt]SendNotifyMessage[/size][/font][font=宋体][size=9pt]后应用程序可以直接到该地址中读取数据。[/size][/font]
[font=宋体][size=9pt]设备管理器就是调用此函数广播[/size][/font][font=Arial][size=9pt]WM_DEVICECHANGE[/size][/font][font=宋体][size=9pt]消息的。另外[/size][/font][font=Arial][size=9pt]WINCE[/size][/font][font=宋体][size=9pt]的一个例子程序[/size][/font][font=Arial][size=9pt]RNAApp[/size][/font][font=宋体][size=9pt]在拨号连接建立的时候也是调用这个函数广播[/size][/font][font=Arial][size=9pt]WM_NETCONNECT[/size][/font][font=宋体][size=9pt]消息的。[/size][/font][font=Arial][size=9pt]  
2[/size][/font][font=宋体][size=9pt]、驱动程序调用[/size][/font][font=Arial][size=9pt]API CeEventHasOccurred[/size][/font][font=宋体][size=9pt]指明一个事件[/size][/font][font=Arial][size=9pt]A[/size][/font][font=宋体][size=9pt]发生,在此之前应用程序调用[/size][/font][font=Arial][size=9pt]API CeRunAppAtEvent[/size][/font][font=宋体][size=9pt]将驱动程序指明的[/size][/font][font=Arial][size=9pt]A[/size][/font][font=宋体][size=9pt]事件和一个应用程序名称相关联,或者和一个事件[/size][/font][font=Arial][size=9pt]B[/size][/font][font=宋体][size=9pt]相关联。这样当[/size][/font][font=Arial][size=9pt]A[/size][/font][font=宋体][size=9pt]事件发生时,如果指明和一个应用程序名称关联,那这个应用程序就会被启动。如果指明了和一个事件[/size][/font][font=Arial][size=9pt]B[/size][/font][font=宋体][size=9pt]相关联,那么等待事件[/size][/font][font=Arial][size=9pt]B[/size][/font][font=宋体][size=9pt]的线程将被激活。如果想了解当前系统内部所有驱动程序支持哪些类似事件[/size][/font][font=Arial][size=9pt]A[/size][/font][font=宋体][size=9pt]的事件,调用[/size][/font][font=Arial][size=9pt] API CeNotifyPublic_FilterEvent[/size][/font][font=宋体][size=9pt],在该[/size][/font][font=Arial][size=9pt]API[/size][/font][font=宋体][size=9pt]的帮助文档里也列举了常见的事件,例如[/size][/font][font=Arial][size=9pt] NOTIFICATION_EVENT_NET_CONNECT[/size][/font][font=宋体][size=9pt]和[/size][/font][font=Arial][size=9pt] NOTIFICATION_EVENT_NET_DISCONNECT[/size][/font][font=宋体][size=9pt]。[/size][/font][font=Arial][size=9pt]  
  
EVC[/size][/font][font=宋体][size=9pt]创建的工程名称如果用中文就出错,该怎么办?[/size][/font]
[font=宋体][size=9pt]用[/size][/font][font=Arial][size=9pt]EVC[/size][/font][font=宋体][size=9pt]创建的工程名称如果为中文将导致资源文件打不开和编译出错,可以改资源文件名称为英文,再编辑[/size][/font][font=Arial][size=9pt].rc[/size][/font][font=宋体][size=9pt]文件中的资源文件名称。但建议尽量不要用中文为工程名称。[/size][/font]
[font=宋体][size=9pt]作为习惯,应该在[/size][/font][font=Arial][size=9pt]EVC[/size][/font][font=宋体][size=9pt]创建一个工程后,立刻在[/size][/font][font=Arial][size=9pt]“project”—“settings”[/size][/font][font=宋体][size=9pt]中设置资源的语言属性,然后在[/size][/font][font=Arial][size=9pt]“resource view”[/size][/font][font=宋体][size=9pt]中设置每个资源的语言属性,这些工作做完后再修改资源就没有问题了。有人询问对话框的标题为乱码,其原因就是在没有修改语言属性的情况下设置标题为中文。[/size][/font][font=Arial][size=9pt]  
  
WinCE[/size][/font][font=宋体][size=9pt]下如何读写几百兆的大文件呢[/size][/font][font=Arial][size=9pt]? [/size][/font][font=宋体][size=9pt]使用内存映射文件吗[/size][/font][font=Arial][size=9pt]?   
[/size][/font][font=宋体][size=9pt]一般[url=http://www.chinaeda.cn/edu/jiuye_1.html][color=#800080]嵌入式[/color][/url]设备配备[/size][/font][font=Arial][size=9pt]128MB[/size][/font][font=宋体][size=9pt]物理内存就算顶级的了,所以要读写几百[/size][/font][font=Arial][size=9pt]MB[/size][/font][font=宋体][size=9pt]的文件用内存映射文件技术是最好的选择了。映射文件之后读数据是非常容易的,要注意的是写数据,内存映射方面的[/size][/font][font=Arial][size=9pt]API[/size][/font][font=宋体][size=9pt]没有提供改变文件长度的功能,所以要在关闭映射文件对象后用文件[/size][/font][font=Arial][size=9pt]API[/size][/font][font=宋体][size=9pt]改变文件长度。[/size][/font]
[font=宋体][size=9pt]请问如何改系统调度的默认时间片值?[/size][/font]
[font=宋体][size=9pt]更改[/size][/font][font=Arial][size=9pt]schedule.c[/size][/font][font=宋体][size=9pt]文件中的[/size][/font][font=Arial][size=9pt]dwDefaultThreadQuantum [/size][/font][font=宋体][size=9pt]变量,然后重新编译该文件并[/size][/font][font=Arial][size=9pt]SYSGEN[/size][/font][font=宋体][size=9pt]。调用[/size][/font][font=Arial][size=9pt]API CeGetThreadQuantum[/size][/font][font=宋体][size=9pt]就知道更改是否生效。[/size][/font]
[font=宋体][size=9pt]如何让系统加载自己写的驱动程序?[/size][/font]
[font=宋体][size=9pt]两种办法:[/size][/font][font=Arial][size=9pt]  
1[/size][/font][font=宋体][size=9pt]、在[/size][/font][font=Arial][size=9pt][HKEY_LOCAL_MACHINE\Drivers\BuiltIn][/size][/font][font=宋体][size=9pt]下添加注册键。[/size][/font][font=Arial][size=9pt]  
2[/size][/font][font=宋体][size=9pt]、在应用程序中调用[/size][/font][font=Arial][size=9pt]ActivateDeviceEx[/size][/font][font=宋体][size=9pt]。[/size][/font]
[font=宋体][size=9pt]在一些文件中用分号来表示注释,例如下面的内容[/size][/font][font=Arial][size=9pt]   
; @CESYSGEN IF SERVERS_MODULES_HTTPD  
; @CESYSGEN ENDIF  
[/size][/font][font=宋体][size=9pt]在[/size][/font][font=Arial][size=9pt]“CESYSGEN...”[/size][/font][font=宋体][size=9pt]前加了[/size][/font][font=Arial][size=9pt]“@”[/size][/font][font=宋体][size=9pt],有没有什么特别的含义?[/size][/font]
[font=宋体][size=9pt]在[/size][/font][font=Arial][size=9pt]WINCE[/size][/font][font=宋体][size=9pt]的一些文件中,用[/size][/font][font=Arial][size=9pt]“;”[/size][/font][font=宋体][size=9pt]作为注释并在注释文字中用[/size][/font][font=Arial][size=9pt]@CESYSGEN[/size][/font][font=宋体][size=9pt]作为标记,后面接条件语句。[/size][/font][font=Arial][size=9pt]Cefilter.exe[/size][/font][font=宋体][size=9pt]工具负责按照条件来筛选文件内容,所以不要轻易地删除包含[/size][/font][font=Arial][size=9pt]@CESYSGEN[/size][/font][font=宋体][size=9pt]的注释语句。[/size][/font]
[font=宋体][size=9pt]通过串口建立[/size][/font][font=Arial][size=9pt]ActiveSync[/size][/font][font=宋体][size=9pt]联接[/size][/font][font=Arial][size=9pt],[/size][/font][font=宋体][size=9pt]串口线用三线的可以吗[/size][/font][font=Arial][size=9pt]?   
[/size][/font][font=宋体][size=9pt]不可以,因为用串口同步时要用到其余口的状态。[/size][/font][font=Arial][size=9pt]  

   
     WINCE[/size][/font][font=宋体][size=9pt]是否支持[/size][/font][font=Arial][size=9pt]MAPI[/size][/font][font=宋体][size=9pt]?[/size][/font]
[font=宋体][size=9pt]不支持。[/size][/font][font=Arial][size=9pt]WINCE[/size][/font][font=宋体][size=9pt]自带的[/size][/font][font=Arial][size=9pt]pmail.exe[/size][/font][font=宋体][size=9pt]软件也不是很好用。建议自开发邮件收发软件。如果需要购买[/size][/font][font=Arial][size=9pt]WINCE[/size][/font][font=宋体][size=9pt]下邮件收发软件可以联系我。[/size][/font]
[font=宋体][size=9pt]如何旋转屏幕显示的内容?[/size][/font]
[font=宋体][size=9pt]例子代码如下(前提是显示驱动程序支持旋转):[/size][/font][font=Arial][size=9pt]  
DEVMODE  devmode = {0};  
devmode.dmSize = sizeof(DEVMODE);  
devmode.dmDisplayOrientation = DMDO_90;       ///[/size][/font][font=宋体][size=9pt]垂直模式[/size][/font][font=Arial][size=9pt]  
devmode.dmFields = DM_DISPLAYORIENTATION;  
ChangeDisplaySettingsEx(NULL, &devmode, NULL, 0, NULL);  ///[/size][/font][font=宋体][size=9pt]改变显示的设置[/size][/font][font=Arial][size=9pt]  
CRect  rcWorkArea(0, 0, 320, 240);    ///[/size][/font][font=宋体][size=9pt]整个屏幕尺寸[/size][/font][font=Arial][size=9pt]  
///[/size][/font][font=宋体][size=9pt]设置客户区大小并广播消息,这样所有软件也就随之更改显示[/size][/font][font=Arial][size=9pt]  
SystemParametersInfo(SPI_SETWORKAREA, 0, (void*)&rcWorkArea, SPIF_SENDCHANGE);   
  
[/size][/font][font=宋体][size=9pt]请问如何修改字形缓存的容量?[/size][/font][font=Arial][size=9pt]  
[HKEY_LOCAL_MACHINE\System\GDI\GLYPHCACHE]  
"limit"=dword:0400  
  
[/size][/font][font=宋体][size=9pt]如何得到从[/size][/font][font=Arial][size=9pt]WINCE[/size][/font][font=宋体][size=9pt]启动开始到现在的时间?[/size][/font]
[font=宋体][size=9pt]调用[/size][/font][font=Arial][size=9pt]API GetTickCount[/size][/font][font=宋体][size=9pt],得到的值为[/size][/font][font=Arial][size=9pt]32[/size][/font][font=宋体][size=9pt]位整数,单位为毫秒。[/size][/font]
页: [1]
查看完整版本: WinCE驱动开发问题精华集锦二