您的位置:首页 > 其它

wince问题集锦二

2018-02-23 17:08 197 查看
如果查看WINCE注册表中的内容?  

两种办法:  

1、建立同步后,用EVC自带的工具“Remote Registry
Editor”打开查看。  

2、从网上下载注册表查看工具,放到WINCE设备中。  

  

调用directshow出现链接错误,如何解决? 
 

player.obj : error LNK2001: unresolved external symbol
_IID_IVideoWindow  

player.obj : error LNK2001: unresolved external symbol
_IID_IMediaControl  

这是因为链接器没有找到合适的.lib文件。两种办法:  

1、在EVC菜单Tools—options—directories 里把library
files的路径重新调整一下。如果你只安装了EVC自带的Standard
SDK而没有其它SDK,可以指定WINCE目录中的.lib文件路径,例如D:\WINCE500\PUBLIC\DIRECTX\OAK\LIB\X86\RETAIL。注意CPU的类型。  

2、安装SDK,前提是导出SDK的PB内核工程必须包括DirectShow或者其它组件。  

   

 
   在PB的config.bib文件中,“IMGFLASH”表示什么意思呢?  

表示能够刷NK到ROM中,具体请查看标题为“IMG Environment
Variables”的帮助文档。  

  

x86平台如何映射各种地址空间?如何编写中断服务例程?  

如果是x86平台,可以调用HalTranslateBusAddress转换物理总线地址到物理系统地址,调用HalTranslateSystemAddress转换物理系统地址到逻辑总线地址,也可以不调用这两个函数,因为x86平台除32位物理地址外还有16位的IO地址空间,对于16位的IO地址空间,可以直接调用WRITE_PORT_UCHAR或者READ_PORT_UCHAR等函数直接读写端口。对于32位物理地址可以调用VirtualAlloc和VirtualCopy来映射。这样做思路清晰,简单明了。  

在x86平台要实现ISR,有如下几个步骤(以Geode
BSP为例):  

1、用SETUP_INTERRUPT_MAP宏关联SYSINTR和IRQ。以“SYSINTR_”为前缀的常量由内核使用,用于唯一标识发生中断的硬件,又称为中断ID。在Nkintr.h文件中预定义了一些SYSINTR,OEM可以在Oalintr.h文件中自定义SYSINTR。  

2、用HookInterrupt函数关联硬件中断号和ISR。这里提到的硬件中断号为物理中断号,IRQ为逻辑中断号。在InitPICs函数的最后调用了HookInterrupt函数,如下:  

for (i = 64; i < 80;
i++)  

HookInterrupt(i, (void
*)PeRPISR);  ///用ISR关联16个中断号 
 

3、调用InterruptInitialize函数关联SYSINTR和IST创建的事件对象,也是IST等待的事件对象。详细内容请参考Geode
BSP源码。  

在x86平台要实现可安装ISR,先调用LoadIntChainHandler函数注册在注册表中指定的ISR
DLL,然后填充GIISR_INFO结构体并调用KernelLibIoControl函数将此结构体传递给可安装ISR。详细内容请参考WINCE帮助文档或者我著的《Windows
CE下驱动开发基础》。  

  

修改了WINCE自带的驱动程序后如何编译?如果是自己开发的驱动程序如何编译?  

1、分为IDE方式和命令行方式。  

IDE方式的编译很简单,以PB5.0为例,打开定制内核的工程,在左边的“workspace”—“FileView”中找到你已经修改了的目录,然后单击右键弹出菜单,在菜单中选择“Build
and Sysgen Current
Project”,这样PB就会编译指定的目录中的项目源码文件,然后执行sysgen命令根据source文件中的内容生成目标文件并复制到当前内核工程目录下。  

命令行方式的编译需要打开“Build OS”—“Open Release
Directory”,以cd命令进入你已经修改的驱动程序目录中,然后键入“build –cfs”,然后键入“sysgen –p
项目名称”,一般项目名称为source文件中的“TARGETNAME”。  

2、如果想完全自己开发驱动程序,建议直接采用EVC或者PB来编写编译。  

  

开发PCI设备驱动时,InterruptInitialize函数的第一参数是否是PCI卡配置空间信息中的InterruptLine
参数?是否需要在HKLM\Drivers\BuiltIn\PCI\Template 加一個自己的
subkey,并填写相应内容?如何填?  

1、InterruptInitialize的第一参数是IRQ,也就是逻辑中断号,而不是物理中断号,InterruptLine是指物理中断号  

2、需要在template下加自己的PCI设备的信息,例如:  

 
 [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"  

而这些信息就来自于你执行pcienum.exe的结果。 
 

  

编译器报错:error C2065: 'CFileFind' : undeclared
identifier,如何解决?  

MFC for WINCE版本没有CFileFind类,所以要查找文件只能调用API FindFirstFile
和FindNextFile。  

  

如何设置WINCE系统字体、字号?如何设置自己开发的软件的字体、字号?  

1、系统字体通过注册表设置。如下:  

[HKEY_LOCAL_MACHINE\System\GDI\SysFnt] 
 ///系统字体  

Wt=420  

Ht=18  

Nm=Arial  

[HKEY_LOCAL_MACHINE\System\GWE\Menu\BarFnt] 
 ///菜单栏字体  

[HKEY_LOCAL_MACHINE\System\GWE\Menu\PopFnt] 
 ///弹出窗口字体  

[HKEY_LOCAL_MACHINE\System\GWE\Menu] 
  
  
 ///菜单字体  

HKEY_LOCAL_MACHINE\System\GWE\Button 
  
    
///按钮字体  

2、创建字体时把字体高度参数设置大点就可以了。如CFont::CreateFont(nHeight,...),也可以在LOGFONT结构中设置字体高度或者字体种类。如果是控件,调用控件的SetFont成员函数。如果是直接画,在OnPaint响应函数中调用SelectObject选字体到DC。  

  

nk.bin和nk.nb0有什么区别?  

这里提到的bin是一种二进制镜像格式,以片断(section)为单位组织数据,每个片断都包括一个头,头里指定了起始地址,长度,校验值。Platform
Builder调用工具将WINCE内核所有文件以bin格式合并成一个文件,默认文件名为nk.bin。BootLoader又以同样的格式将nk.bin分解成多个文件放到RAM中。可以在命令行中键入“viewbin
nk.bin”来查看bin文件中具体包括了哪些内容。键入Cvrtbin命令转换.bin格式文件为.sre格式或者.abx格式。  

nb0格式是原始的二进制镜像,它不包括头,一般情况下将内核下载到设备的RAM中运行都采用nb0格式。要生成nbx格式的文件,需要在相关.bib文件中确定如下值:ROMSTART、ROMWIDTH、ROMSIZE。  

  

在不采用硬件计时器的情况下如何创建更精确的计时器?最精确周期能否达到1毫秒?  

对于精确值的要求不同,所采用的办法不同。以下阐述几种办法。  

1、在单线程中循环调用API
Sleep函数,Sleep函数精确程度为如果Sleep(N),那么实际睡眠时间在N到N+1毫秒之间。而且还要注意调用Sleep的线程优先级的问题。如果任务过多并且此线程优先级低,那误差就更大些。  

2、调用API
QueryPerformanceCounter函数,举例如下:  

LARGE_INTEGER  liFrequency;  

if
(QueryPerformanceFrequency(&liFrequency))  //
查询系统时钟的频率,这里将返回1000  

{  

   liFrequency.QuadPart /=
1000; 
   

 
 LARGE_INTEGER  liTimeOut; 
   

   if
(QueryPerformanceCounter(&liTimeOut)) 
 //得到截至到当前累计发生的系统时钟中断次数  

 
 {  

    
 liTimeOut.QuadPart +=
liFrequency.QuadPart; 
 ///计算下一秒到来时总的中断次数是多少  

    
 LARGE_INTEGER  liCurrent;  

    
 do  

    
 { 
  
  
   

    
  
 QueryPerformanceCounter(&liCurrent); 
  //
循环查询累计的的中断次数  

    
 } while (liCurrent.QuadPart <
liTimeOut.QuadPart);
///到达下一秒  

 
 }  

}  

调用QueryPerformanceCounter同调用Sleep在本质上都是一样的,都是在单线程中无限循环等到周期一到执行任务,相比较QueryPerformanceCounter要比Sleep更精确些,越精确就越要求线程的优先级,保障线程能够正常得到处理器。  

3、以上办法难以保证周期精确到1毫秒并且WINCE系统稳定地运行,所以要从中断入手。以x86平台为例,先在Timer.c中将默认的SetTimer0(TIMER_COUNT)中的TIMER_COUNT
/=2,SetTimer0函数负责设置系统时钟的频率,默认1毫秒发生一次中断,如果除以2就是0.5毫秒发生一次中断。然后在fwpc.c文件中修改ISR函数PeRPISR,因为原来默认是1毫秒发生一次中断,在处理INTR_TIMER0时系统负责累计计数、管理线程的调度,返回相应的SYSINTR值,而我们没有办法再添加代码返回自己定义的SYSINTR值,所以现在要修改原来的处理代码,例如设置一个BOOL型变量,TRUE就执行原来默认的代码,而FALSE就返回我们自己定义的SYSINTR值,这样即不影响原来的ISR处理,又加入了我们的中断响应代码。ISR返回我们定义的SYSINTR后WINCE内核激活相对应的EVENT事件,我们就可以在我们编写的IST里处理任务了。  

  

flash中存放了BootLoader和内核镜像,如何把剩余flash部分划分为一个存储区域供应用程序读写?  

以WINCE提供的驱动(FAT文件系统和MSFLASH驱动)来举例说明。如果采用默认common.reg中的注册表设置,那么MSFLASH驱动默认把整个flash作为存储区域来读写,这不符合问题的要求,所以必须告诉MSFLASH驱动程序可供读写的区域的起始地址和长度。以下是一个注册表例子:  

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\FASLD]  

   
"Dll"="fasld.dll" 
  
   ///实际Flash存储器的驱动程序  

   
"Order"=dword:2 
    
///该驱动程序相对于其它驱动程序的加载顺序  

   
"Prefix"="DSK" 
  
   ///前缀  

   
"Ioctl"=dword:4 
  
   ///IOCTL码,设备管理器加载驱动的时候调用IOControl函数,传递这个IOCTL码。  

"Profile"="MSFlash"   
///Profile名称,也就是[HLM\System\StorageManager\Profiles\MSFlash]  

///当设备管理器加载此驱动程序的同时发送通知给系统,IClass(GUID)的值表明这是一个存储设备的驱动程序。  

"IClass"="{A4E7EDDA-E575-4252-9D6B-4195D48BB865}" 
   

   
"MemBase"=dword:00000000   
///Flash中可供读写区域的起始物理地址,也就是Flash的首地址+偏移量  

   
"MemLen"=dword:00000000 
   ///Flash中可供读写区域的长度  

[HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\MSFlash]  

   
"DefaultFileSystem"="FATFS" 
 ///MSFlash驱动默认采用的文件系统  

   
"PartitionDriver"="mspart.dll"   
///采用的分区驱动程序  

   
"MountAsRoot"=dword:1 
  
   ///此目录作为文件系统的根目录  

    "Folder"="NOR
Flash"    
    
///目录名称  

    "Name"="FLASH Disk Block
Device" 
 ///Flash驱动名称  

"PartitionDriverName"="MSPART"
///分区驱动名称  

"AutoMount"=dword:1 
  
  
 ///自动装载检测到的分区  

   
"AutoPart"=dword:1 
  
  
  
 ///自动分区  

   
"AutoFormat"=dword:1 
  
    
///自动格式化分区  

[HKEY_LOCAL_MACHINE\System\StorageManager\AutoLoad\MSFlash]  

   
"DriverPath"="Drivers\\BuiltIn\\FASLD" 
 
///Flash驱动在注册表中的位置  

   
"LoadFlags"=dword:1 
  
  
  
  
   ///这个值可以被设置为0、1、2。1表示同步加载,其它表示异步加载  

   
"Order"=dword:0  

[HKEY_LOCAL_MACHINE\System\StorageManager\FATFS]  

    "FriendlyName"="FAT
FileSystem"   
///文件系统名称  

   
"Dll"="fatfsd.dll" 
  
  
  
  
    
///文件系统驱动程序  

   
"Flags"=dword:00000064 
  
  
    
///标志,详见帮助文档  

   
"Paging"=dword:1 
  
  
  
  
    
///是否分页  

   
"EnableCache"=dword:1 
  
  
  
   ///是否允许缓存数据  

   
"CacheSize"=dword:0 
  
  
  
    
///指定缓存大小,0表示默认  

 

     驱动程序如何发通知给应用程序?  

这里介绍一下常见的两种办法。  

1、驱动程序调用API
SendNotifyMessage,发送特定的消息给应用程序,这就要求应用程序要有消息循环机制并且要事先做好消息的处理。参数1为窗口句柄,可以设置HWND_BROADCAST表示广播消息。要注意的是不要在参数中传递指针(虚拟地址),因为执行驱动程序的线程和应用程序并不在同一个进程空间中。解决办法可以利用内存映射文件技术,比如在驱动程序中创建一个内存映射文件对象,申请一块物理内存,然后把对象名称和内存长度传递给应用程序,应用程序打开同名的内存映射文件对象,读取里面的数据。对象名称可以事先协定好,也可以通过注册表来传递,内存长度是32位值,通过消息参数就可以传递,也可以通过注册表来传递。另外一种解决办法是在定制内核时候预留一块物理内存,这样驱动程序和应用程序都可以通过VirtualAlloc和VirtualCopy来映射到同一块物理内存,其原理同内存映射文件技术一样,但是这块物理内存不具备通用性。最后一个办法是应用程序事先将一个缓冲区地址传递给驱动程序,驱动程序调用MapPtrToProcess映射应用程序传递过来的地址,当驱动程序调用SendNotifyMessage后应用程序可以直接到该地址中读取数据。  

设备管理器就是调用此函数广播WM_DEVICECHANGE消息的。另外WINCE的一个例子程序RNAApp在拨号连接建立的时候也是调用这个函数广播WM_NETCONNECT消息的。  

2、驱动程序调用API CeEventHasOccurred指明一个事件A发生,在此之前应用程序调用API
CeRunAppAtEvent将驱动程序指明的A事件和一个应用程序名称相关联,或者和一个事件B相关联。这样当A事件发生时,如果指明和一个应用程序名称关联,那这个应用程序就会被启动。如果指明了和一个事件B相关联,那么等待事件B的线程将被激活。如果想了解当前系统内部所有驱动程序支持哪些类似事件A的事件,调用API
CeNotifyPublic_FilterEvent,在该API的帮助文档里也列举了常见的事件,例如NOTIFICATION_EVENT_NET_CONNECT和
NOTIFICATION_EVENT_NET_DISCONNECT。  

3、使用同名事件

  

EVC创建的工程名称如果用中文就出错,该怎么办? 
 

用EVC创建的工程名称如果为中文将导致资源文件打不开和编译出错,可以改资源文件名称为英文,再编辑.rc文件中的资源文件名称。但建议尽量不要用中文为工程名称。  

作为习惯,应该在EVC创建一个工程后,立刻在“project”—“settings”中设置资源的语言属性,然后在“resource
view”中设置每个资源的语言属性,这些工作做完后再修改资源就没有问题了。有人询问对话框的标题为乱码,其原因就是在没有修改语言属性的情况下设置标题为中文。  

  

WinCE下如何读写几百兆的大文件呢? 使用内存映射文件吗? 
 

一般嵌入式设备配备128MB物理内存就算顶级的了,所以要读写几百MB的文件用内存映射文件技术是最好的选择了。映射文件之后读数据是非常容易的,要注意的是写数据,内存映射方面的API没有提供改变文件长度的功能,所以要在关闭映射文件对象后用文件API改变文件长度。  

  

请问如何改系统调度的默认时间片值?  

更改schedule.c文件中的dwDefaultThreadQuantum 变量,然后重新编译该文件并SYSGEN。调用API
CeGetThreadQuantum就知道更改是否生效。  

  

如何让系统加载自己写的驱动程序? 
 

两种办法:  

1、在[HKEY_LOCAL_MACHINE\Drivers\BuiltIn]下添加注册键。  

2、在应用程序中调用ActivateDeviceEx。  

  

在一些文件中用分号来表示注释,例如下面的内容 
 

; @CESYSGEN IF
SERVERS_MODULES_HTTPD  

; @CESYSGEN
ENDIF  

在“CESYSGEN...”前加了“@”,有没有什么特别的含义?  

在WINCE的一些文件中,用“;”作为注释并在注释文字中用@CESYSGEN作为标记,后面接条件语句。Cefilter.exe工具负责按照条件来筛选文件内容,所以不要轻易地删除包含@CESYSGEN的注释语句。  

  

通过串口建立ActiveSync联接,串口线用三线的可以吗? 
 

不可以,因为用串口同步时要用到其余口的状态。  

   

 
   WINCE是否支持MAPI?  

不支持。WINCE自带的pmail.exe软件也不是很好用。建议自开发邮件收发软件。如果需要购买WINCE下邮件收发软件可以联系我。  

  

如何旋转屏幕显示的内容?  

例子代码如下(前提是显示驱动程序支持旋转):  

DEVMODE  devmode =
{0};  

devmode.dmSize =
sizeof(DEVMODE);  

devmode.dmDisplayOrientation = DMDO_90; 
    
///垂直模式  

devmode.dmFields =
DM_DISPLAYORIENTATION;  

ChangeDisplaySettingsEx(NULL, &devmode, NULL, 0,
NULL);  ///改变显示的设置  

CRect  rcWorkArea(0, 0, 320,
240);   
///整个屏幕尺寸  

///设置客户区大小并广播消息,这样所有软件也就随之更改显示  

SystemParametersInfo(SPI_SETWORKAREA, 0, (void*)&rcWorkArea,
SPIF_SENDCHANGE); 
 

  

请问如何修改字形缓存的容量?  

[HKEY_LOCAL_MACHINE\System\GDI\GLYPHCACHE]  

"limit"=dword:0400  

  

如何得到从WINCE启动开始到现在的时间?  

调用API
GetTickCount,得到的值为32位整数,单位为毫秒。  

  

如何调用WINCE的软键盘?  

调用API
SipShowIM(SIPF_ON),前提是内核加入了软键盘组件。  

  

基于HIVE的注册表,如何在系统关闭前保存注册表的数据到文件system.hv?  

调用API
RegFlushKey函数。  

  

使用VirtualAlloc和VirtualCopy的时候需要注意哪些事项?  

1、VirtualAlloc的作用是申请虚拟地址空间,这肯定不是最终的目的,最终目的可能是申请物理内存、映射寄存器、提交文件等。没有一个目的会在意虚拟地址空间的位置,所以尽量传递参数1为0,也就是让WINCE自动分配虚拟地址空间。VirtualAlloc分配地址空间实际上是以64KB为单位,所以要指定申请的虚拟空间的首地址的话,参数1应该为64KB的整数倍,申请的长度也应该为64KB的整数倍,即使你不需要那么大。  

2、VirtualCopy的主要作用是映射物理地址空间,如果参数2为物理地址,那么最后一个参数要添加PAGE_PHYSICAL,参数2必须是256的整数倍。如果参数2为虚拟地址(0x80000000以上),那么最后一个参数就不要添加PAGE_PHYSICAL,WINCE内核会根据这个虚拟地址找到对应的物理地址。  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: