WinCE--中断处理程序ISR 详…

    首先来解释一下, OAL实际上就是一个硬件的抽象层,WinCE的内核通过OAL来和硬件进行通信,应该说它并不包含硬件外设的驱动,而只是对基于处理器本身的硬件模块的控制。

 ISR (Interrupt service routine),  中断处理程序。 WinCE实际上使用 ISR来处理中断,即默认的中断入口函数

    ISR是OEM实现的一段这段处理代码,它属于OAL层的一部分。在ARM平台下,ISR是由OEMInterruptHandle和OEMInterruptHandleFIQ两个函数实现。ISR的主要作用就是将物理IRQ映射为逻辑中断号。

    细节:

      这个流程就是OEMInterruptHandle和OEMInterruptHandleFIQ两个函数的实现流程。[转载]WinCE--中断处理程序ISR <wbr>详解

 

    返回上述三种值中一个后ISR就完成了它的使命,将操作权交给内核。

    由于在进入ISR处理前比当前优先级低的中断都给屏蔽掉了,所以ISR处理必须快速、简洁、高效!尽快将操作权交给内核,尽快回复中断,以防中断丢失!!!

关于SYSINTR的解释: 
在 WinCE中,SYSINTR 就是 system interrupt,就是一个操作系统的逻辑中断。

一般对于中断的处理方式都是将一个IRQ映射为一个或者多个(中断共享)SYSINTR,而后,在实际的ISR中根据IRQ返回一个对应的SYSINTR用来告诉操作系统需要服务的逻辑对象。

   使用逻辑中断的好处当然就是可以实现虚拟的中断(一个 SYSINTR 就被 OS 认为是一个独立中断)和中断共享(单 IRQ对应多 SYSINTR)。
    逻辑中断是WinCE需要处理的实际对象,至于这个对象是一个共享的IRQ,还是一个虚拟的中断,还是独立的物理中断,系统并不过问,从而隔离了硬件与逻辑,我们的 ISR 需要做的也正是这种物理中断到逻辑中断的映射。

 

ISR的延伸话题:
 下面我们来谈谈
可安装的 ISR 
一、为什么要使用可安装ISR (以下简称 IISR) 
    需要 ISR 的目的有两种:
I. 动态的安装中断程序
     在系统运行的过程中注册中断,这种中断一般是不可预知设备的中断,常用在总线设备中,比如PCI设备

II. 中断共享
       当多个中断源使用同一个中断号(IRQ)时,就需要使用可安装的ISR来实现了,
当然如果是需要动态安装的共享中断就最适合了。 ??????

    因为我们的IST模型中,中断服务程序就是驱动中的IST,IRQ与 IST是一对一的关系。而如果ISR固定了的话,所以在需要动态添加一个中断服务程序的时候就没有办法处理了。
    同样由于IRQ与IST的一一对应关系对于一个IRQ对应多个需要服务的IST就同样没有办法处理。 ???????(知道SYSINTR_XXX不是就可以了么就可以找到IST么???)
 基于上面的情况才会有可安装的ISR的出现,可安装的ISR 从本质上是在ISR 中提供了一个接口,当ISR 调用 NKCallIntChain时,以此IRQ为参数,在链表中依次查找是哪一个服务程序来
服务这次 IRQ,然后返回相应的 SYSINTR,此后的动作与 IST 模型就基本一样,通过SYSINTR 来激活Event,从而启动相应的 IST。
  所以可安装的ISR的实现就是动态的向某一个IRQ服务程序链表添加结点的过程。

 

二、 可安装ISR的实现
下面我们来看看可安装ISR 的具体实现步骤:
  首先我们需要了解可安装的ISR 服务中断的实现原理,如上面描述的,根据IRQ,来顺序调用链表中的中断处理程序。所以我们可以有两个选择,一个就是类似 ISR 模型,直接在链表
中的中断处理程序中判断是不是自己的中断,并且做处理。还有一种方式就是类似 IST 模
型,如果判断是自己的中断,则返回一个SYSINTR,以此SYSINTR 来激活IST 。???
 
  无论哪种方法,关于注册中断和查询中断的方式是一样的,下面我们来看下如何将中断程序添加到链表,又如何在中断来的时候去搜索链表。
  Microsoft提供了一个通用的IISR的处理模型,叫做 GIISR,这是一个 IST模型处理 IISR 的模块,源程序可以在WINCE500PUBLICCOMMONOAKDRIVERSGIISR找到。熟悉了 GIISR,想实现自己的 IISR 处理程序或者基于 ISR 模型的处理,都比较简单了。
  下面我们就分析这种比较通用的处理 IISR 的模型
a)  首先我们[转载]WinCE--中断处理程序ISR <wbr>详解需要以 IRQ 来申请 SYSINTR,并且将 SYSINTR 与 Event 绑定这些步骤与IST模型中介绍的一样,这里就不重复叙述了IISR 在这里与 IST模型并没有任何的不同。其与 IST 模型的唯一不同点就是如何根据 IRQ 来判断相应的
SYSINTR
在 IST 模型中是 OEM写死的一个判断程序,而 IISR 可以动态来注册一个判断程序给系统调用,这是唯一的实现区别。
b)  下面我们[转载]WinCE--中断处理程序ISR <wbr>详解需要注册可安装中断程序的 dll,和 dll中的中断处理函数,并且将他们与某一个特定的IRQ相关联 这个过程是通过调用LoadIntChainHandler函数来实先现
    这里我们的中断服务dll叫做”giisr.dll”,处理函数名叫做”ISRHandler”,对应IRQ
为0x20,则函数调用形式如下:
    HANDLE  hIsrHandler  LoadIntChainHandler(TEXT(“giisr.dll”),
    TEXT(“ISRHandler”), 0x20);

 

c)  上一步在GIISR中通过CreateInstance把这个新的中断处理程序加入GIISR自己的管理。GIISR 的主要作用就是判断当中断来的时候,是不是其内部数组中的某个成员需要服务中断。所以需要更多的信息用来判断中断是否匹配当前的中断服务程序,所以我们需要把信息传递进去,这里就是调用KernelLibIoControl。
具体的方法为:
KernelLibIoControl(hIsrHandler,IOCTL_GIISR_INFO,&giisr_info, 

                                sizeof(GIISR_INFO), NULL, 0, NULL);

这里就是把 giisr_info 的内容传递给刚才注册的中断,giisr_info 是一个
GIISR_INFO的结构体,其内容如下:
typedef struct _GIISR_INFO {
       DWORD SysIntr;  // SYSINTR for ISR handler to return

                      //( if associated device is asserting IRQ)
       BOOL CheckPort   // If true, check port to see if device is asserting IRQ
       BOOL PortIsIO;         // Port is IO port (possibly true only for x86)
       BOOL UseMaskReg;       // If  true,  read  from MaskAddr  to obtain mask
       DWORD PortAddr;                          // Port Address
       DWORD PortSize;                          // Port data width in bytes 
      DWORD Mask;//Mask to use on data port to determine if device is asserting IRQ
       DWORD MaskAddr;            //  Address  of  register  to  use  as mask
} GIISR_INFO, *PGIISR_INFO;

这些成员都是需要设置的,具体含义如下 :
    SysIntr:这个中断所对应的系统中断号,即第一步申请到的 SYSINTR,系统在确定是当前的

             设备出发的 IRQ 之后会返回这个 SysIntr
    CheckPort:一般为 TRUE,如果为 FALSE 则直接返回 SysIntr,而不是判断是不是当前设备

               触发的中断
    PortIsIO:是不是IO端口,这个可能只是在 x86 下使用,我们置为 FALSE
    UseMaskReg:是否使用地址来获得 Mask,如果为TRUE,则Mask 字段无意义
    PortAddr:实际上是可以判断中断是哪个设备出发的那个寄存器的地址
    PortSize:PortAddr的位宽,标志PortAddr是1字节(BYTE),2 字节(WORD),还是 4字节

              (DWORD)的寄存器,其他不支持
    Mask:一个掩码位,在UseMaskReg为FALSE 的情况下与PortAddr的值进行位或运算,

           如果不为0,则确定为当前设备触发的中断
    MaskAddr:当 UseMaskReg为 TRUE 的时候,使用这个地址来获得掩码的值,给动态的判断中

              断提供了接口 仔细看了上面各个成员的介绍,大家就应该可以了解 GIISR 是如何

              判断中断是不是当前设备产生的。
所有的判断依据就是这个结构体。一般我们会将 CheckPort 置为 TRUE,然后让
系统去读取PortAddr地址处的值,这个值可以标志是否为当前设备触发的中断
获得这个值以后,与一个 mask 值进行或运算(&),如果值不为 0,则认为是当前
设备触发的中断
。这个 mask 值在 UseMaskReg 为 FALSE 时是成员 Mask,反之是从 MaskAddr 地址处获得。

 

d) 下面就是启动IST,等待Event,这里和IST模型没有任何区别。 到这里全部的初始化就完成了,可以看出,和IST模型相比就是多了两步 b)和 c),这两步决定了中断判断的方式,这也是 IISR的根本所在。

   
三、中断的判断
下面详细介绍下可安装中断在 ISR 中被判断的过程。
      同 样 , 中 断 到 来 时 进 入 的 函 数 是 OEMInterruptHandler , 在
OEMInterruptHandler中会调用NKCallIntChain来遍历该IRQ对应注册的IISR。这是一个链表结构,所以对中断判断程序是一个顺序调用的过程,即先注册的设备先判断,如果判断到正确的结果,则返回合法的 SYSINTR,OEMInterruptHandler也同样返回这个值。所以即使后面的设备也符合条件,也不会被执行。如果整个链表中都没找到正确的设备,则返回 SYSINTR_CHAIN。OEMInterruptHandler 在判断到返回结果为SYSINTR_CHAIN 时,即表示请求中断的设备不在链表中。

 

四、  自定义的 IISR
  我们可以不使用GIISR,而自己实现IISR功能,只要知道了IISR 的原理。

     当以某一个寄存器或者地址的值,不足以判断到底是系统中哪个设备触发的中断的时候,GIISR 就不是这么好用了??????。比如多个不同的外设,使用同一个GPIO 来触发中断。外设需要读取多个寄存器或者需要一个复杂些的计算(不只是简单的一个&操作)才能判定中断是否是其产生的。这时候我们需要使用自己的一套 IISR的处理方式。
     当然我们不希望去改动整个微软对于 IISR 的处理结构,所以我们就要区分开来上面介绍的 GIISR 的模型里,哪些是微软的架构,哪些是GIISR 自己的实现。

      [转载]WinCE--中断处理程序ISR <wbr>详解微软的 IISR 架构:
a)  首先需要使用 LoadIntChainHandler 去注册这个 IISR 的处理判断程序的dll,在这个 dll中除了需要一个判断处理程序(也就是通过LoadIntChainHandler传递进去的那个参数),还需要一个CreateInstance的函数,这个是必须的。在你不改动微软内核的情况下,名字也是固定的,详细地函数定义,可以参考 GIISR 的 CreateInstance。至于 IOControl,最好也参考 GIISR 的定义一个,如果不需要去调用KernelLibIoControl 的话,应该是可以不实现的。

b)  在OEMInterruptHandler 中调用NKCallIntChain去遍历链表,在调用处理函数时将CreateInstance 的返回值作为参数传递进去,如果处理函数在判断到不是自己触发的中断,应该返回 SYSINTR_CHAIN,否则返回一个有意义的 SYSINTR 值

c)  在需要注销这个IISR 的时候,调用 FreeIntChainHandler,需要在dll中实现 DestroyInstance 这个函数,被系统调用,这个是可选的。

      [转载]WinCE--中断处理程序ISR <wbr>详解[转载]WinCE--中断处理程序ISR <wbr>详解GIISR 自己的实现:
     使用同一套代码管理这些中断处理程序,每个中断处理程序在内部的数组中占用一项,这些项目记录着中断处理程序激活使用的SYSINTR 以及判定其触发中断的标准。这个标准就是读取某个寄存器或地址来用掩码来判断。同时这个数组项目对应的结构体数据就是通过KernelLibIoControl 传递进去的。

  所以对于需要使用自己的特殊方式判断中断触发的程序,可以使用自己的中断判别程序。
  我们可以为每一个中断外设都实现自己的处理dll。在调用LoadIntChainHandler时传递进自定义的一个 dll 与处理函数,CreateInstance 一定要实现,不过返回值可以忽略。
  在处理函数中,我们直接根据自己的外设来判断中断条件,然后返回相应的SYSINTR。

  其实使用 CreateInstance 的含义就是想把同一判断类型的设备使用一套统一的
处理函数来判断。CreateInstance 的返回值就是区别不同设备的这个 Index。

五、 IISR资源的释放
当我们需要注销这个 IISR 的时候,需要调用 FreeIntChainHandler,来将该中
断服务从链表中删除。

FreeIntChainHandler(hIsrHandler);
hIsrHandler 就是LoadIntChainHandler 的返回值。
 

六、 使用 IISR的注意事项
由于 IISR 是动态的被加载的,也就是说注册的 dll 会被加载到内核空间。所以不能调用任何非内核的函数。
  并且,如果将 IISR的 dll放在 bib文件的MODULES section里面,需要设置”K”属性,如
giisr.dll               $(_FLATRELEASEDIR)giisr.dll       NK   SHK

如果放在 FILES section 里面,需要保证没有 fixup类型的变量。 
    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值