为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

天极论坛精选

2011-07-03 17页 pdf 249KB 49阅读

用户头像

is_259191

暂无简介

举报
天极论坛精选 作者:付林林 windowsce@tom.com 天极论坛嵌入式开发版 http://378.bbs.yesky.com 1 声 明 — 本文档中所有问题均选自天极论坛嵌入式开发版,本文档作者为版主。 — 对于原来问题不正确的解答在此已经更正,由于作者经验有限如还有错误敬请谅解。 — 筛选问题的原则是有代表性,提问的人较多,另外没有选择和硬件有关的问题。 — 有些问题的原因是因WINCE的版本不同或者BUG造成,所以没有被选入。建议读者及时更新WINCE的补丁。下载地址: http://msdn.mi...
天极论坛精选
作者:付林林 windowsce@tom.com 天极论坛嵌入式开发版 http://378.bbs.yesky.com 1 声 明 — 本文档中所有问题均选自天极论坛嵌入式开发版,本文档作者为版主。 — 对于原来问题不正确的解答在此已经更正,由于作者经验有限如还有错误敬请谅解。 — 筛选问题的原则是有代性,提问的人较多,另外没有选择和硬件有关的问题。 — 有些问题的原因是因WINCE的版本不同或者BUG造成,所以没有被选入。建议读者及时更新WINCE的补丁。下载地址: http://msdn.microsoft.com/embedded/downloads/ce/wince/default.aspx — 本文件可任意传播和下载,如转载其中内容必须注明作者信息,作者信息如下: 作者:付林林 MSN / E-MAIL:windowsce@tom.com 作者:付林林 windowsce@tom.com 天极论坛嵌入式开发版 http://378.bbs.yesky.com 2 WINCE 常见问题解答 v0.1 z 在 mediaplayer 全屏播放的时候,我可以用键盘上的某一个键调节声音大小,现在我想在屏幕上显示调节的结果就跟 我们看电视一样能出来一些标记。当声音变大在屏幕上就增多,当声音变小的时候就减少 得到播放窗口的 DC,然后在上面显示一个不同颜色的矩形或者其它形状。 z 在 ce 自制平台中如何添加自己的驱动?cec 文件和 reg,bib 文件有何区别?看混了,不知道如何才能让驱动注册到平 台中。另外,reg 和 bib 是我在编写驱动必须要自己写的么 CE 的驱动分为本机驱动和流驱动,本机驱动你可以修改源码(在%_WINCEROOT%\PUBLIC\COMMON\OAK\DRIVERS),然后 build 驱动源 码,之后用 PB 编译内核。流驱动是以 DLL 的形式被系统程序加载的。加载流驱动要在注册表中添加信息,这和 cec 文件没关。如果你想把 此驱动 DLL 和注册信息作为一个整体给别人使用,那么就要做一个 cec 文件,PB 能够读取 cec 文件内容并加载到内核工程中。cec 文件相 当于安装程序。 z 我安装的是 evc4.0,我开发的系统要显示中文比如姓名什么的。在编辑的时候是中文显示,但是到了输出时,显示的 都是乱码。不知道应该怎么去解决 EVC的模拟器不支持中文。所以显示出来的都是乱码。1、你可以只显示英文,调试结束后在改界面为中文。2、安装PB,PB的模拟器支持中 文。 z CStatic 及其控件的文字无法垂直居中显示,虽然在 evc 的资源编辑器中可设置,但是一旦运行,却无法垂直居中显示 这种情况正常,而且除此之外还不能右对齐。 z 获取设备 ID 的种类有哪些 除了手机模块外,还有 CF 卡有序列号、硬盘有 ID 号、网卡有 MAC 号等。这几种方法数获取手机模块 ID 最简单。 z 在应用程序中,如何向修改本机的 ip 地址等网络参数,并使之立即生效? 网络设置保存在注册表中,位置[HKEY_LOCAL_MACHINE\Comm\网卡名称\Parms\TcpIp],例如常见的 CS8900 网卡设置: [HKEY_LOCAL_MACHINE\Comm\CS89001\Parms\TcpIp] "EnableDHCP"=dword:0 "DefaultGateway"="192.168.0.1" "DNS"="111.111.111.111" "UseZeroBroadcast"=dword:0 "IpAddress"="192.168.0.2" "Subnetmask"="255.255.255.0" 设置之后要生效有两种办法:一种热启动,调用 KernelIoControl(IOCTL_HAL_REBOOT, NULL, 0, NULL, 0, NULL),热启动时间很短暂;另 外一种调用 DevieceIoControl API,传递 IOCTL=IOCTL_NDIS_REBIND_ADAPTER。 z 如何向控制面板中那样,修改系统声音的音量 调用 API waveOutSetVolume(HWAVEOUT, dwVolume ),一般参数 1 为 0。在[HKEY_CURRENT_USER\ControlPanel\Volume]下是系统声音 的注册表设置。 z 在应用程序中如何实现 jpg、gif 图片的显示 有几种办法: 1、在 MSDN 中搜索标题为“Windows CE .NET Technical Frequently Asked Questions”的文档,其中有一个问题“How can I display JPEG, GIF, and other graphics files?”,下面就是。 2、如果安装了 Windows CE 5.0,一个例子源码位于 WINCE500\PUBLIC\GDIEX\SDK\SAMPLES\SIMPLE。 3、用 IWebBrowser 组件实现。 作者:付林林 windowsce@tom.com 天极论坛嵌入式开发版 http://378.bbs.yesky.com 3 z 在应用程序中如何实现系统待机 void GwesPowerOffSystem(void); z 在 WINCE 下如何实现键盘钩子 我 写 了 一 个 简 单 的 例 子 , 把 其 中 主 要 部 分 截 取 出 来 放 到 了 我 的 FTP 里 。 用 户 名 以 及 密 码 均 为 winceuser , 地 址 是 ftp://211.95.73.26/fllsoft@sina.com/SourceCode/用钩子禁止系统键.rar。 z 在 WINCE 中如何得到网卡 MAC 地址 事实证明,获得物理网卡的 MAC 地址并没有被统一成一个 API 或者 IOCTL,如果网卡驱动程序没有提供接口的话只能直接访问寄存器获得。 读者可以参考目录 WINCE500\PUBLIC\COMMON\OAK\DRIVERS\NETCARD 里的一些驱动源码。 z Windows XP Embedded 和 Windows CE 有何区别 简单地说 Windows XP Embedded 采用 Windows XP 内核,只能运行在 x86 处理器上,优点是能够运行 PC 上现有的应用软件,缺点是授权 费太高,标价¥900 元;Windows CE 采用 Windows CE 内核,能够运行在多种处理器上,如 x86、ARM、SHX、MIPS 等,优点是授权费低, 最低 Core 版标价¥30 元。缺点是需要单独开发应用软件、定制内核,甚至开发 BSP、Driver。 z wince 下只是把调制解调器的驱动挂接在了 com1,如何将器驱动挂接在 com2 上? 1、在 HLM\drivers\buildin\com2\unimodem 下复制和 com1 一样的数据 2、在 HLM\ExtModems\HayesCompat 下改写 Port 为 COM2:,再改写 FriendlyName 为"Hayes Compatible 在 COM2:"。 z 如何定制自己的外壳 1、先开发一个外壳软件,假设名称为 MyShell.exe 2、删除注册表[HKEY_LOCAL_MACHINE\init]下如下一行: "Launch50"="explorer.exe" 3、在注册表[HKEY_LOCAL_MACHINE\init]下添加如下一行: "Launch50"="MyShell.exe" 上述的“LaunchXX”中的 XX 为序列数,内核依据这个序列数按由小到大的顺序来分别执行所有子键列出的应用程序,具体数值应该为多少 请参考帮助文档的。 如果原来的内核中添加了外壳(standard shell)组件,或者添加了其它组件而这些组件需要依赖标准外壳,那么在 PB 中是无法删除标 准外壳组件的,解决办法一是保留 explorer.exe 在内核中,二是删除依赖标准外壳的组件。 z 我原来的工程是 x86 版本的,编译选项只有 x86,我如何能够编译 ARM 版本的 两种办法: 1、用 EVC 新建一个工程的时候,建议复选“CPUs”列表,这样发生了这种事情也能够轻易通过选择“WCE Configuration”工具栏中的 CPU 列表来编译不同 CPU 版本的软件 2、如果打开工程后 CPU 列表中只有 x86,而此时已经安装了 ARM 版本的 SDK,那么单击 EVC 菜单“build”-“configurations”,然后单 击“add”按钮来添加 CPU。 z 通常情况下 WINCE 采用串口 1 作为调试时输出信息用途,要正式出产品前如何去掉串口 1 的调试功能 正常情况下串口 1 只有在编译 debug 版本的内核时才在 BootLoader 中初始化串口 1 用于输出信息,而编译 release 版本会跳过此代码。而 有些 BSP 设计成没有宏定义,也就是说无论什么版本都会在 BootLoader 中初始化串口 1,这样造成 WINCE 启动后串口 1 无法被应用程序 使用。对于这种情况只能在 BootLoader 源码中删除初始化代码,如 OEMInitDebugSerial。 z 基于 wince 的应用程序能建成 console project 么? 不能 z ARM 系统外扩一片 512K RAM,驱动程序经过映射可以使用这一段 RAM。1、应用系统如何使用这一段 RAM?要加 作者:付林林 windowsce@tom.com 天极论坛嵌入式开发版 http://378.bbs.yesky.com 4 一层驱动吗?2、如果要将这一段 RAM 当作 RAM 盘存储系统,该如何作呢?应该要加文件系统吧,如何加呢? 解答这个问题前,先要说一下 WINCE 的地址映射机制。对于包含 MMU(存储器管理单元)的处理器来说,如 ARM 和 x86,WINCE 要求 OEM 在定制内核的时候填写一个虚拟地址与物理地址映射关系的表,称为 OEMAddressTable,在这个表中定义了所有物理设备的起始物理 地址,对应的起始虚拟地址,地址空间大小,RAM 就包括在其中(如果是 x86 平台还要求 RAM 起始虚拟地址从 0x80000000 开始)。如果 有多片 RAM,应该在 OEMAddressTable 中将它们定义在一起,使之地址连续。对于非 OEM 的开发者来说,他们拿到的是定制好的内核,不 能做任何修改,如果在产品中外扩一片 RAM,只能通过 API 函数通知操作系统增加一条虚拟地址与物理地址映射关系表项。相关 API 函数 有两个,分别是 CreateStaticMapping 和 VirtualCopy。它们的相同之处是都用于建立物理地址和虚拟地址的映射关系。它们的不同之处是 CreateStaticMapping 映射的虚拟地址范围在 0xC400 0000 到 0xE000 0000 之间,这个范围只能由内核访问,一般用于 ISR 访问,因为 ISR 只能访问静态映射的虚拟地址空间,不能用 VirtualCopy。VirtualCopy 通常和 VirtualAlloc 配合使用,映射的虚拟地址空间在 0x8000 0000 以下,一般用于驱动程序和应用程序访问。 1、应用程序要访问这片 RAM,和驱动程序访问方法一样,调用 VirtualAlloc 和 VirtualCopy。 2、可以做一个流驱动程序专门用于读写这片 RAM,这样所有应用程序就可以通过调用流驱动接口函数来访问,非要加文件系统也是可行的, 通过修改注册表就可以做到,但是麻烦一些。 z 我怎么能在 PB 左边的定制平台加进我的驱动呢? 两种办法: 1、在 platform.bib 或者 project.bib 的 MODULES 部分添加一条语句,例如: MyDriver.dll C:\Driver\MyDriver.dll NK SH 这样编译内核的时候就会把你的驱动 DLL 文件添加到内核中,如果有注册表需要设置,在 platform.reg 或者 project.reg 中添加注册表内容。 2、通过制作.cec 文件来添加驱动,制作.cec 文件的优点是只需制作一次,以后就可以通过将.cec 文件导入到 PB 的 Catalog 中,象 PB 自带的 feature 一样通过菜单“Add to OS Design”添加到左边的内核工程中。 z WINCE 有没有相对路径概念?如果没有如何得到当前模块的路径? 1、WINCE 没有相对路径概念,只有绝对路径,所以凡是涉及到路径均为绝对路径。 2、调用 API GetModuleFileName,传递一个模块的实例句柄就能够得到模块的绝对路径。 z 怎样让 POCKET WORD 打开*.dat 格式(里面都是数据)的文件? 两种办法: 1、调用 API ShellExecuteEx,在结构体 SHELLEXECUTEINFO 中添加.dat 文件的路径。 2、调用 API CreateProcess,在第二个参数中设置.dat 文件的路径。 z x86 Rom Boot Loader 真的可以实现吗?它确实能代替 BIOS 启动计算机? Rom Boot 被设计存放在 Flash/EEPROM 中,也就是原来 BIOS 的位置,这样当上电后 CPU 到固定地址执行代码,也就是执行了 Rom Boot 的代码,它对整个硬件系统进行初始化和检测,并且支持通过网卡从远程机器上下载 nk.bin 或者从本地 IDE/ATA 硬盘的活动分区中寻找 nk.bin 文件加载。Rom Boot 的优点就是引导并且加载速度快,而且它自身完成了所有的操作,这样就不用 BIOS、MSDOS,更不用 Loadcepc 了。 z 对于 x86 Rom Boot Loader,如何 Build 得到 Romboot.rom? 1、在 PB 中打开一个内核工程(x86 的) 2、单击 PB 菜单“Build”-“Open Build Release Directory” 3、用 cd 命令进入 %_WINCEROOT%\Platform\Geode\Romboot 4、build z 如何设置、更改显示分辨率 能否设置、更改显示分辨率由显示驱动程序决定,而没有统一的标准。例如 CEPC,在启动的时候可以通过设置 loadcepc.exe 的参数 /L 来 决定 WINCE 启动后的显示分辨率,这是由于显示驱动“VGA Linear Framebuffer”支持,而 Geode 可以通过在定制内核时修改注册表项来 决定 WINCE 启动后的显示分辨率。 作者:付林林 windowsce@tom.com 天极论坛嵌入式开发版 http://378.bbs.yesky.com 5 z 几个硬件使用同一个 IRQ,那么发生中断的时候系统怎么判断到底是哪一个硬件发生的中断呢?ISR 里面又应该怎么 控制呢? Windows CE 支持多个设备中断共享一个 IRQ,当一个共享 IRQ 发生时,CE 内核的异常处理程序检测设备特定的寄存器,因为大多数设备 都有一个单独的寄存器用于表示设备的活动状态,所以通过遍历共享这个 IRQ 的所有设备的寄存器就可以判断哪个设备发生中断。nk.exe 加载一个 giisr.dll,这个.dll 是微软提供的,它其实是第一个可安装 ISR。默认 CE 内核就是调用这个 dll 来检测寄存器状态的,当然 OEM 可 以编写自己的.dll。 CE 内部有一个 ISR 链,也就是可安装 ISR。因为 CE 允许 OEM 添加自己的 ISR 处理程序,所以 ISR 被设计成一个链表。排在前面的 ISR 比 后面的 ISR 优先处理中断,如果当前 ISR 能够处理当前中断,那就返回中断 ID 由 IST 处理或者返回 SYSINTR_NOP,如果当前 ISR 不能够 处理当前中断,那就返回 SYSINTR_CHAIN 让下一个 ISR 处理。 z 请问在 wince 中如何在内核中增加一个与\windows 同级的目录? 在 platform.dat 或者 project.dat 中添加语句。例如要创建根目录下子目录 Program Files,语句如下: root:-Directory("Program Files") z 文件格式如下所示,我想把每行的 4 个值读到 4 个变量中,用 EVC 如何编程? 第一行: 460.000, 3384672.357342, 521268.972763 第二行: 475.117, 3384663.772419, 521281.415271 伪代码如下: FILE *stream; stream = _wfopen(L"\\a.txt", L"r+"); if( stream == NULL ) return; fseek(stream, 0L, SEEK_SET ); while( !feof( stream ) ) { fwscanf(stream, L"%s", WCHAR1); fwscanf(stream, L"%f", float1); fwscanf(stream, L"%f", float2); fwscanf(stream, L"%f", float3); } fclose( stream ); z GWES 组件的功能有哪些? GWES 不仅负责 GDI、窗口、消息,还负责管理本机设备驱动程序,负责加载显示、键盘鼠标、触摸屏驱动程序,而且 GWES 本身包含电 源、LED 驱动程序。 z 如何在 PB 中预先设定好存储内存和程序内存的大小,我想多划分一些空间给程序内存? 两种办法: 1、在定制内核时在 config.bib 文件中设置 FSRAMPERCENT = number,具体 number 可参考标题为“FSRAMPERCENT ”的帮助文档。这种 办法是修改内核的设置,所有一直有效。 2、在应用程序中调用 API SetSystemMemoryDivision,如果函数返回 SYSMEM_CHANGED 表示成功,如果返回 SYSMEM_MUSTREBOOT 表示需要热启动才能有效。这种办法需要每次启动后调用 API 才有效。 z 如何取消鼠标光标? 通过取消 SYS 变量来实现此目的,在 PB 命令行下键入“set SYSGEN_CURSOR=”,然后回车确认。 z EVC 下调用 TextOut 如何编译会出错? 类似这样的问题很多,这是因为 EVC 的帮助文档内容有错误。可能 EVC 的帮助文档内容是从桌面 Windows 帮助文档复制过来的,所以很 作者:付林林 windowsce@tom.com 天极论坛嵌入式开发版 http://378.bbs.yesky.com 6 多 API 函数还有例子代码都有错误,例如帮助文档中包含一个 API 函数的说明,但是实际编译的时候提示没有这个 API,有的例子代码采用 ANSI 字符串,而 WINCE 的 API 都是宽字符版本,造成直接复制过来编译失败。 因为 MFC for WINCE 的 CDC 类中没有 TextOut 成员函数,所以编译会出错,可以用其它类成员函数 ExtTextOut 或者 DrawText 替换。 z 我如何将我的 dll 软件让现有的 ce 系统认可?尽管我也知道应该使用 signfile.exe 程序进行签名,但是我并不知道那 个 ce 系统认可的签名应该是啥 如果你说的 WINCE 系统内核已经加入了签名认证机制,那么没有私钥对你的 DLL 文件签名肯定是无法运行在此内核中的,一般签名密钥 的密钥长度都是 1024 位,很难破解。 z 如果查看 WINCE 注册表中的内容? 两种办法: 1、建立同步后,用 EVC 自带的工具“Remote Registry Editor”打开查看。 2、从网上下载注册表查看工具,放到 WINCE 设备中。 z 调用 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 或者其它组件。 z 在 PB 的 config.bib 文件中,“IMGFLASH”表示什么意思呢? 表示能够刷 NK 到 ROM 中,具体请查看标题为“IMG Environment Variables”的帮助文档。 z 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 下驱动开发基础》。 z 修改了 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”。 作者:付林林 windowsce@tom.com 天极论坛嵌入式开发版 http://378.bbs.yesky.com 7 2、如果想完全自己开发驱动程序,建议直接采用 EVC 或者 PB 来编写编译。 z 开发 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 的结果。 z 编译器报错:error C2065: 'CFileFind' : undeclared identifier,如何解决? MFC for WINCE 版本没有 CFileFind 类,所以要查找文件只能调用 API FindFirstFile 和 FindNextFile。 z 如何设置 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。 z 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。 z 在不采用硬件计时器的情况下如何创建更精确的计时器?最精确周期能否达到 1 毫秒? 对于精确值的要求不同,所采用的办法不同。以下阐述几种办法。 1、在单线程中循环调用 API Sleep 函数,Sleep 函数精确程度为如果 Sleep(N),那么实际睡眠时间在 N 到 N+1 毫秒之间。而且还要注意调用 Sleep 的线程优先级的问题。如果任务过多并且此线程优先级低,那误差就更大些。 2、调用 API QueryPerformanceCounter 函数,举例如下: LARGE_INTEGER liFrequency; if (QueryPerformanceFrequency(&liFrequency)) // 查询系统时钟的频率,这里将返回 1000 { 作者:付林林 windowsce@tom.com 天极论坛嵌入式开发版 http://378.bbs.yesky.com 8 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 里处理任务了。 z 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 驱动在注册表中的位置 作者:付林林 windowsce@tom.com 天极论坛嵌入式开发版 http://378.bbs.yesky.com 9 "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 表示默认 z 驱动程序如何发通知给应用程序? 这里介绍一下常见的两种办法。 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。 z EVC 创建的工程名称如果用中文就出错,该怎么办? 用 EVC 创建的工程名称如果为中文将导致资源文件打不开和编译出错,可以改资源文件名称为英文,再编辑.rc 文件中的资源文件名称。但 建议尽量不要用中文为工程名称。 作为习惯,应该在 EVC 创建一个工程后,立刻在“project”—“settings”中设置资源的语言属性,然后在“resource view”中设置每个资源 的语言属性,这些工作做完后再修改资源就没有问题了。有人询问对话框的标题为乱码,其原因就是在没有修改语言属性的情况下设置标题 为中文。 z WinCE 下如何读写几百兆的大文件呢? 使用内存映射文件吗? 一般嵌入式设备配备 128MB 物理内存就算顶级的了,所以要读写几百 MB 的文件用内存映射文件技术是最好的选择了。映射文件之后读数 据是非常容易的,要注意的是写数据,内存映射方面的 API 没有提供改变文件长度的功能,所以要在关闭映射文件对象后用文件 API 改变 文件长度。 z 请问如何改系统调度的默认时间片值? 更改 schedule.c 文件中的 dwDefaultThreadQuantum 变量,然后重新编译该文件并 SYSGEN。调用 API CeGetThreadQuantum 就知道更改是否 生效。 z 如何让系统加载自己写的驱动程序? 两种办法: 1、在[HKEY_LOCAL_MACHINE\Drivers\BuiltIn]下添加注册键。 2、在应用程序中调用 ActivateDeviceEx。 作者:付林林 windowsce@tom.com 天极论坛嵌入式开发版 http://378.bbs.yesky.com 10 z 在一些文件中用分号来表示注释,例如下面的内容 ; @CESYSGEN IF SERVERS_MODULES_HTTPD ; @CESYSGEN ENDIF 在“CESYSGEN...”前加了“@”,有没有什么特别的含义? 在 WINCE 的一些文件中,用“;”作为注释并在注释文字中用@CESYSGEN 作为标记,后面接条件语句。Cefilter.exe 工具负责按照条件来 筛选文件内容,所以不要轻易地删除包含@CESYSGEN 的注释语句。 z 通过串口建立 ActiveSync 联接,串口线用三线的可以吗? 不可以,因为用串口同步时要用到其余口的状态。 z WINCE 是否支持 MAPI? 不支持。WINCE 自带的 pmail.exe 软件也不是很好用。建议自开发邮件收发软件。如果需要购买 WINCE 下邮件收发软件可以联系我。 z 如何旋转屏幕显示的内容? 例子代码如下(前提是显示驱动程序支持旋转): 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); z 请问如何修改字形缓存的容量? [HKEY_LOCAL_MACHINE\System\GDI\GLYPHCACHE] "limit"=dword:0400 z 如何得到从 WINCE 启动开始到现在的时间? 调用 API GetTickCount,得到的值为 32 位整数,单位为毫秒。 z 如何调用 WINCE 的软键盘? 调用 API SipShowIM(SIPF_ON),前提是内核加入了软键盘组件。 z 基于 HIVE 的注册表,如何在系统关闭前保存注册表的数据到文件 system.hv? 调用 API RegFlushKey 函数。 z 使用 VirtualAlloc 和 VirtualCopy 的时候需要注意哪些事项? 1、VirtualAlloc 的作用是申请虚拟地址空间,这肯定不是最终的目的,最终目的可能是申请物理内存、映射寄存器、提交文件等。没有一个 目的会在意虚拟地址空间的位置,所以尽量传递参数 1 为 0,也就是让 WINCE 自动分配虚拟地址空间。VirtualAlloc 分配地址空间实际上是 以 64KB 为单位,所以要指定申请的虚拟空间的首地址的话,参数 1 应该为 64KB 的整数倍,申请的长度也应该为 64KB 的整数倍,即使你 不需要那么大。 2、VirtualCopy 的主要作用是映射物理地址空间,如果参数 2 为物理地址,那么最后一个参数要添加 PAGE_PHYSICAL,参数 2 必须是 256 的整数倍。如果参数 2 为虚拟地址(0x80000000 以上),那么最后一个参数就不要添加 PAGE_PHYSICAL,WINCE 内核会根据这个虚拟地 址找到对应的物理地址。 z 驱动程序和应用程序之间传递数据时何时调用 MapPtrToProcess? 作者:付林林 windowsce@tom.com 天极论坛嵌入式开发版 http://378.bbs.yesky.com 11 因为设备管理器负责加载驱动程序 DLL,这意味着当应用程序调用驱动程序接口函数的时候,WINCE 内核会将调用驱动程序接口函数的线 程转移到设备管理器的进程空间然后执行具体的驱动程序代码,应用程序和设备管理器处于两个进程空间,这就造成设备管理器无法访问应 用程序传递的指针(虚拟地址),所以当我们在应用程序中传递指针给流驱动程序接口函数时,WINCE 内核从中作了一个地址映射,例如 ReadFile、WriteFile、DeviceIoControl 函数的参数凡是指针都经过了映射才传递给驱动程序,所以很多驱动程序开发者并不了解其中的奥秘 就可以编程了。但是如果参数是一个指向一个结构体的指针,而结构体里包括一个或多个指针,那么 WINCE 内核并不负责映射,所以就需 要开发者在驱动程序接口函数中调用 API 函数 MapPtrToProcess 来映射地址。例如:pPointer_retval = MapPtrToProcess(pPointer, GetCallerProcess()); z 如何判断可插拔的设备是否存在? 1、通过查找注册表的值。凡是由 API ActivateDeviceEx 加载的驱动程序都在
/
本文档为【天极论坛精选】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索