WinCE的中断处理流程 && 光感应sensor举例

       关于WinCE的中断处理,OAL中主要是实现了ISR部分,一般IST会在设备驱动中实现。

                           
      这张图想必很多人都见过,主要这张图太经典了,所以还是贴出来唠叨几句,硬件中断产生以后,会导致内核ISR的运行,然后由OAL中的ISR来处理相应的中断,最后导致相对应的IST运行完成真正的中断处理。所以在WinCE中,中断处理由ISR和IST共同完成。ISR主要完成中断源的确定,屏蔽该中断并返回给内核相对应的系统中断号,ISR应该尽量短小。IST则是完成真正的中断处理,比如数据的传输和解析等。当然不是所有的中断处理都需要ISR和IST,看需要,比如WinCE的系统Timer中断就只需要ISR完成。

      运行流程图:

                        

(1)如果一个驱动程序要处理一个中断,那么驱动程序需要首先建立一个事件,可以使用CreateEvent函数,然后调用InterruptInitialize将该事件与中断号绑定,这一步就会使能该中断,OAL中的OEMInerrupteEnable就会被调用,如果该函数不返回true的话,InterruptInitialize就会失败。然后驱动程序中的IST就可以使用WaitForSingleObject函数来等待中断的发生。
(2)当一个硬件中断发生之后,操作系统陷入异常,中断向量指示进入CE的异常处理程序,该异常处理程序然后调用OAL的OEMInterruptHandler函数,该函数检测硬件之后,将硬件中断转换为软件的中断号,返回给系统。该中断号就是上面提到的InterruptInitialize中使用的那个中断号。系统得到该中断号之后,就会找到该中断号对应的事件,并唤醒等待相应事件的线程(IST),然后IST就可以在用户态进行中断处理。

(3)处理完成之后,IST需要调用InterruptDone来告诉操作系统中断处理结束,操作系统再次调用OAL中的OEMInterruptDone函数,最后完成中断的处理。

(4)光感应芯片应用实例:

static DWORD  g_als_irq_id;  //物理中断号

HANDLE g_ps_intr_event;     //中断事件

#define XLLP_GPIO_ALS_INT                           89   //光感应芯片的GPIO

DWORD ALS_Init(    LPCTSTR pContext,    LPCVOID lpvBusContext)

{

       HANDLE AlsThread;

       DWORD m_dwSysIntr;  //内部中断号

       g_als_irq_id = IRQ_GPIO_SHARE(XLLP_GPIO_ALS_INT);    //物理中断号

       if(!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &g_als_irq_id, sizeof(DWORD), &(m_dwSysIntr), sizeof(DWORD), NULL))   //从物理中断号获得内部中断号
       {
              m_dwSysIntr = SYSINTR_UNDEFINED;
              return ERROR_INVALID_DATA;
       }

 

       g_ps_intr_event = CreateEvent(NULL, FALSE, FALSE, NULL);

       if(NULL == g_ps_intr_event)
       {
              RETAILMSG(1, (TEXT("CreateEvent g_ps_intr_event_ error XXXXX/r/n")));
       }

       if(!InterruptInitialize(m_dwSysIntr, g_ps_intr_event, NULL, 0))   //把中断号跟中断事件绑定
       {
              RETAILMSG(1, (TEXT(" InterruptInitialize_ error XXXXX by cheehwa/r/n")));
       }

 

       AlsThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ps_intr_thread, 0, 0, NULL);
}

void ps_intr_thread()
{

       while(1)
       {
             if(WaitForSingleObject(g_ps_intr_event, INFINITE) == WAIT_OBJECT_0)
             {

                    ............

                    InterruptDone(acc_sys_intr);  //中断处理完上报

             }

       }

}

(5)利用线程实现轮询操作(打开,关闭,工作共三种状态)

HANDLE g_control_als_ps_event_open;  //设备打开事件
HANDLE g_control_als_ps_event_close;  //设备关闭事件

enum
{
       OPEN_EVENT,    //设备打开事件标号
       CLOSE_EVENT,   //设备关闭事件标号
       ALSPS_NUM_EVENTS
};

DWORD ALS_Init(    LPCTSTR pContext,    LPCVOID lpvBusContext)

{

       HANDLE hPollingThread;

       g_control_als_ps_event_open = CreateEvent(NULL, FALSE, FALSE, NULL);

       if(NULL == g_control_als_ps_event_open)
       {
              RETAILMSG(1, (TEXT("CreateEvent g_control_als_ps_event_open_ error XXXXX/r/n")));
       }

       g_control_als_ps_event_close = CreateEvent(NULL, FALSE, FALSE, NULL);

       if(NULL == g_control_als_ps_event_close)
       {
              RETAILMSG(1, (TEXT("CreateEvent g_control_als_ps_event_close_ error XXXXX/r/n")));
       }

       hPollingThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)als_detec_intr_thread, NULL, 0, NULL);

}

void als_detec_intr_thread()
{

       DWORD dwResult, time_out = INFINITE;

       HANDLE  WaitEvents[ALSPS_NUM_EVENTS];
       WaitEvents[OPEN_EVENT] = g_control_als_ps_event_open;
       WaitEvents[CLOSE_EVENT] = g_control_als_ps_event_close;

       while(1)
       {
              dwResult = WaitForMultipleObjects(ALSPS_NUM_EVENTS, &WaitEvents[0], FALSE, time_out);

              switch(dwResult)
              {
                     case(WAIT_OBJECT_0 + OPEN_EVENT):
                     {
                             time_out = 3000;  //如果设备打开了,变为3S工作查询一次
                     }
                     break;
                     case(WAIT_OBJECT_0 + CLOSE_EVENT):
                     {
                             time_out = INFINITE;    //如果设备关闭,时间变更为等待下次打开
                     }
                     break;
                     case(WAIT_TIMEOUT):
                     {
                             .......................   //要得到的感应器数据
                     }
                     break;
                     default:
                     break;
             }
       }

}

而那两个事件的更改则在外部函数控制

DWORD ALS_Open(DWORD dwClientContext, DWORD dwAccess, DWORD dwShareMode)
{
      alsps_enable();
      SetEvent(g_control_als_ps_event_open);
      return dwClientContext;
}

BOOL ALS_Close(DWORD dwOpenContext)
{
      alsps_disable();
      SetEvent(g_control_als_ps_event_close);
      return (dwOpenContext != 0);
}

(5)关于光感应sensor的补充说明

        目前平台上所用的CM3623就是一款典型的光感应sensor,根据光线强度和距离感应来扩展手机的应用,比如通话时关掉背光,关闭通话后重启背光,达到省电。如图:

                          

根据CM3652上的红外LED来向外发射光线,再通过CM3623检测反射光强度,来做出相应的处理。这里有个功耗问题:LED不断以一定的周期向外发送红外线,也会消耗一定的能量,单就这个应用,我们如何做到更省电?那就是在不通话的时候关掉LED发射。

       其逻辑大致是:
if(calling && gsensor侧立 )
{
       enable(proximity);
       if(proximity范围内)
       {
              closebacklight();
       }
       else
       {
              openbacklight();
       }
}
else
{
       disable(proximity);
}
这样就实现更低的功耗。


参考原文:http://blog.mcuol.com/User/armwince/Article/14707_1.htm
参考原文:http://www.cnblogs.com/nesta/archive/2008/04/04/1136977.html
参考原文:http://www.cnblogs.com/we-hjb/archive/2009/05/26/1490461.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值