WinCE 5.0边练边学(5)(6)

出处:互联网    发布于:2011-09-03 08:14:47

 
   工欲善其事,必先利其器
 
 对于实时系统,如何调试是一个很难解决的问题,包括对系统内核的调试,对驱动程序的调试,对应用程序的调试等。对于应用程序,通常各集成开发环境都提供了常规的单步跟踪等调试手段。而对于另两个的调试,Platform Builder除了为我们提供了常规的断点跟踪等手段以外,还和系统的源程序配合使用了一种新的调试手段——Debug Zones调试区。
 
  通常,我们都是利用OutpubDebugString函数来实现调试信息的输出的,但是由于系统底层的调试信息非常繁多,如果这样大量的调试信息用于实时输出的话一定会影响到系统的性能和实时性,也就影响到了系统的运行。如果有一种方式能允许开发人员自己选择输出哪些调试信息,不输出哪些调试信息的话,那么就可以让开发人员只看到关心的调试信息,而把诸如键盘按键、鼠标移动等无用的调试信息隐去,则可以更好的提高开发效率,迅速找到问题所在。
 

  在程序中使用调试区之前必须先定义它们,一个程序的16个调试区编号分别为0-15。代码样例如下所示:

  #ifdef DEBUG

  //

  // For debug builds, use the real zones.

  //

  #define ZONE_TEST DEBUGZONE(0)

  #define ZONE_PARAMS DEBUGZONE(1)

  #define ZONE_VERBOSE DEBUGZONE(2)

  ……

  #define ZONE_WARN DEBUGZONE(14)

  #define ZONE_ERROR DEBUGZONE(15)

  #else

  //

  // For retail builds, use forced messages based on the zones turned on below.

  //

  #define ZONE_TEST 0

  #define ZONE_PARAMS 0

  #define ZONE_VERBOSE 0

  ……

  #define ZONE_WARN 0

  #define ZONE_ERROR 0

  #endif

  这样,就可以程序的DEBUG版本中使用调试区了,而在RELEASE版本中则将其全部定义为0,调试信息即不再输出。

  在程序中,除了以上的定义以外,还要声明几个专用的调试信息输出函数,这些函数与OutputDebugString函数的区别就在于在调用时需要指定对应的调试区,这些函数以及以上用到的DEBUGZONE宏的定义都在DbgApi.h头文件中,因此只要在源程序中包含此头文件即可。除此以外,还需要一个全局的DEBPARAM类型的变量命名为dpCurSettings,以供集成开发环境和调试信息输出函数使用。其代码样例如下:

  #ifdef DEBUG

  DBGPARAM dpCurSettings = {

  TEXT("WaveDriver"), {

  TEXT("Test") // 0

  ,TEXT("Params") // 1

  ,TEXT("Verbose") // 2

  ,TEXT("Interrupt") // 3

  ,TEXT("WODM") // 4

  ,TEXT("WIDM") // 5

  ,TEXT("PDD") // 6

  ,TEXT("MDD") // 7

  ,TEXT("Regs") // 8

  ,TEXT("Misc") // 9

  ,TEXT("Init") // 10

  ,TEXT("IOcontrol") // 11

  ,TEXT("Alloc") // 12

  ,TEXT("Function") // 13

  ,TEXT("Warning") // 14

  ,TEXT("Error") // 15

  }

  ,

  (1 《 15) // Errors

  | (1 《 14) // Warnings

  };

  #endif

  此例中还把ERROR和WARN调试区作为默认被开发人员选中的调试区。

  要想使用调试区,还需要做的一件准备的事情就是在程序中进行注册,也就是在程序启动时通知集成开发环境本程序中要使用调试区,这个注册很简单,只要在程序的入口处使用DEBUGREGISTER宏即可,样例如下:

  DllEntry (

  HANDLE hinstDLL,

  DWORD Op,

  LPVOID lpvReserved

  )

  {

  switch (Op) {

  case DLL_PROCESS_ATTACH :

  DEBUGREGISTER((HINSTANCE)hinstDLL);

  break;

  ……

  至于调试区的使用,完全是几个宏的使用而已,我想做程序的人都会用的,常用的宏如下:

  DEBUGMSG(),DEBUGLED(),RETAILMSG(),RETAILLED(),ERRORMSG(),DEBUGCHK()

  好了,调试区就概要的说了这么多,如此复杂的机制在自己的程序中写起来是烦琐了点,不过如果你需要的话,可以从CE现有的例程序中复制过来,这样就省了很多麻烦事,也不会出错。下图是在PB中使用调试区的截图,当选中某一个调试区后,如果该调试区有调试信息则会在DEBUG窗口输出的。


 

  Windows CE的 中断响应时间是针对锁存在内存上的线程 (当内存响应不存在时)。这使得计算差事件响应成为可能——中断服务程序(ISR) 开始和中断服务线程(IST)开始D的总时间,直到中断处理的总时间能够通ISR 和 IST 中所需时间计算决定。

  中断测试应用软件Intrtime.exe,在Windows CE标准版本收集中断分时延迟信息,应用软件在测试中控制系统时间。因此,当系统需要时间控制器时,是不合适使用的。例如,此应用程序不能与内核 instrumented版本一起使用,因为它也需要时间控制。

   
   

 

    我们分布来解释上图中的流程:


  1、硬件设备向Kernel发送中断异常的代码,如果检测到这个中断异常,就会被Kernel层的异常处理所截获;

  2、中断服务调度程序会调用OAL例程中的OEMInterruptDisable函数,这个函数会通知硬件在处理完这一中断前关闭特殊的中断,但其他的中断仍然处于开放状态;

  3、中断服务例程ISR被调用以决定如何来处理这一中断;

  4、Kernel接收到ISR的返回值以得知如何处理这一中断。它的响应结果之一是忽略掉这一中断不作处理(SYSINTR_NOP),另一结果是准备执行IST。

  5、Kernel引发中断服务调度程序来唤醒中断服务线程去工作。IST是常规的Win32线程,一旦启动后,它会创建必要的EVENT然后等待该EVENT被激发。中断服务调度通过调用PulseEvent函数来激发EVENT,从而唤醒IST线程运行;

  6、当唤醒以后,IST会对中断进行必要的处理如将数据移动到缓冲区或其他有意义的事;

  7、如果需要的话,IST会借助于I/O支持例程访问硬件设备;

  8、当IST处理完成后,它会调用InterruptDone函数通知Kernel;

  9、Kernel调用OEMInterruptDone函数完成此次中断的处理过程,OAL例程通知硬件设备重新启用中断。

  以上就是中断在CE中简要的处理过程。这其中还涉及到几个函数的使用,包括:

  1、供OAL调用的ISR函数

  HookInterrupt函数在OEMInit函数中被调用以关联IRQ和ISR;

  UnhookInterrupt函数用来终止IRQ和ISR的关联。

  2、供驱动程序调用的IST函数

  InterruptInitialize函数用来将EVENT对象和逻辑中断号关联并允许中断;

  InterruptDone函数用来通知中断处理的结束;

  InterruptDisable函数被驱动程序调用以关闭中断同时取消被InterruptInitialize初始化的EVENT对象。

  下面我们再分别来看一下重要的两部分,ISR和IST。

  ISR属于OAL层,通常是用汇编语言编写的,它可以将CPU寄存器中的数据移动到内存缓冲区中,但是它不能做更多的工作,其中一个原因就是它不能访问到用户态的存储区,它要把这些工作交给IST来完成。它做的另一项工作是进行物理中断号和逻辑中断号的映射。一个物理设备比如键盘在一种平台上可能产生4号中断,在另一种平台上可能产生15号中断,经过ISR以后,它就会把这一物理中断转换成CE中标准的SYSINTR_KEYBOARD逻辑中断。Kernel就会根据这个逻辑中断值找到对应的EVENT从而唤醒IST。

  ISR 响应通用公式定义如下:   ISR开始时间 = value1 + dISR_Current + sum(dISR_Higher)   value1=由内核处理过程获得响应值    dISR_Current=中断到达时程序中 ISR 持续时间。这个值范围由0到系统中长的 ISR 持续时间    sum(dISR_Higher)=所有在 ISR 开始前的较ISRS 持续时间总和,即在时间 vahe1+dISR-cumeneu间到达的中断   例如,考虑一个拥有关键优先权 ISR 的嵌入式系统,因为 ISR 被设成,这有样 ISRS dISR-Higher 值为0。当没有其它 ISRS 响应,在程序中,即为value1 响应即为value1加系统中长 ISR 周期,当中断到达时,正是系统中长的 ISR 开始执行。   IST 响应周期定义如下:   IST开始时间 = value2 + sum(dIST) + sum(dISR)    value2=由内核处理的响应值   sum(dIST)=所有的出现在 ISR 和 IST ,开始的优先级 ISTS 和线程上下文转换时间总和。   sum(dISR)=在中断(?) ISR 和它的 IST 之间运行的其它 ISRS 持续时间总和。

  ISR有两种,一种是单ISR模式, 即全局只有一个ISR,它适用于不支持多中断的CPU,在这种情况下,OAL会提供一个OEMInterruptHandler的命令ISR。另一种是多ISR模式,即CPU有多个硬件中断的情况,OAL通过HookInterrupt函数为每一个中断调用ISR。

  IST是驱动程序中的用户态线程,它来执行中断的处理工作。在启动后它会空闲等待EVENT的激发状态,激发后处理真正的中断处理过程,调用InterruptDone函数标识中断处理完成。它通常通过CeSetThreadPriority函数设置在较高的优先级状态。

  以上是对中断的简要了解,在WINCE5的驱动程序中,很大的变化就是把很多过程化的东西变成了面向对象的方式,即进行了以类为基础的封装,这样代码变得非常层次化,如果你想了解以上这些中断在具体驱动程序中的实现,建议还是先来看看CE4中的代码,似乎更明显一些。

  KeybdIstLoop(

  PKEYBD_IST pKeybdIst

  )

  {

  SETFNAME(_T("KeybdIstLoop"));

  UINT32 rguiScanCode[16];

  BOOL rgfKeyUp[16];

  UINT cEvents;

  DEBUGCHK(pKeybdIst->hevInterrupt != NULL);

  DEBUGCHK(pKeybdIst->pfnGetKeybdEvent != NULL);

  DEBUGCHK(pKeybdIst->pfnKeybdEvent != NULL);

  SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);

  wait_for_keybd_interrupt:

  if (WaitForSingleObject(pKeybdIst->hevInterrupt, INFINITE) == WAIT_OBJECT_0)

  {

  cEvents = (*pKeybdIst->pfnGetKeybdEvent)

  (pKeybdIst->uiPddId, rguiScanCode, rgfKeyUp);

  for (UINT iEvent = 0; iEvent < cEvents; iEvent) {

  (*pKeybdIst->pfnKeybdEvent)(pKeybdIst->uiPddId,

  rguiScanCode[iEvent], rgfKeyUp[iEvent]);

  }

  // cEvents could be 0 if this was a partial scan code, like 0xE0

  InterruptDone(pKeybdIst->dwSysIntr_Keybd);

  }

  goto wait_for_keybd_interrupt;

  ERRORMSG(1, (TEXT("KeybdIstLoop: Keyboard driver thread terminating.\r\n")));

  return TRUE;

  }

    这次我们了解到了内置的设备驱动程序的架构,因为各种不同类别的内置驱动程序要实现不同的接口,因此在实现起来就非常有针对性,也不利于演示。

    关于WinCE 5.0

  Windows CE为微软针对个人电脑以外的电脑产品所研发的嵌入式操作系统,而CE缩写的来源则有Customer Embedded,Compact Edition, Consumer Electronics等等。  目前的Windows CE为Windows CE 5.0,为微软的。NET家族成员,除100%兼容于Windows CE外,并强化许多功能;在开发环境上,微软提供兼容于。NET Framework的开发元件:。NET Compact Framework,让正在学习。NET或已拥有。NET程序开发技术的开发人员能迅速而顺利的在搭载Windows CE .NET系统的装置上开发应用程序。  用于掌上电脑Pocket PC上的Windows CE系统称为Windows Mobile,目前的版本为Windows Mobile 5.0,代号为Magneto。简单地说,Windows CE就是基于掌上型电脑类的电子设备操作系统。其中CE中的C代表袖珍(Compact)、消费(Consumer)、通讯能力(Connectivity)和伴侣(Companion);E代表电子产品(Electronics),好了,已经写了不少了,唉,写这东西真是费时啊,不说了,希望我们能一起获得更多的知识。


  

版权与免责声明

凡本网注明“出处:维库电子市场网”的所有作品,版权均属于维库电子市场网,转载请必须注明维库电子市场网,https://www.dzsc.com,违反者本网将追究相关法律责任。

本网转载并注明自其它出处的作品,目的在于传递更多信息,并不代表本网赞同其观点或证实其内容的真实性,不承担此类作品侵权行为的直接责任及连带责任。其他媒体、网站或个人从本网转载时,必须保留本网注明的作品出处,并自负版权等法律责任。

如涉及作品内容、版权等问题,请在作品发表之日起一周内与本网联系,否则视为放弃相关权利。

广告
上传BOM文件: BOM文件
*公司名:
*联系人:
*手机号码:
QQ:
应用领域:

有效期:
OEM清单文件: OEM清单文件
*公司名:
*联系人:
*手机号码:
QQ:
有效期:

扫码下载APP,
一键连接广大的电子世界。

在线人工客服

买家服务:
卖家服务:

0571-85317607

客服在线时间周一至周五
9:00-17:30

关注官方微信号,
第一时间获取资讯。

建议反馈

联系人:

联系方式:

按住滑块,拖拽到最右边
>>
感谢您向阿库提出的宝贵意见,您的参与是维库提升服务的动力!意见一经采纳,将有感恩红包奉上哦!