2440/2416/6410/S5PV210之wince+android系统驱动开发者

等待新发生的事情

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

ZLG7290(wince下)驱动之不停执行同一动作的解决办法(作者:wogoyixikexie@gliet)

//-----------------------------------------------------------------------------------------------------------

// 日期:2009年3月23日 8:31:19

// 作者:wogoyixikexie@gliet

// 版权:桂林电子科技大学一系科协wogoyixikexie@gliet

// 平台:wince5.0 2440 5.0 BSP

// 最后修改:2009年3月23日 8:31:30

//-----------------------------------------------------------------------------------------------------------

     今天,把原来4.2BSP的ZLG7290驱动搬到2440 5.0BSP下,只是简单修改一下中断的获得方式就成功了,哈哈,看到按键控制菜单真是爽呆了。可是出现了非常郁闷的事情,那就是按一下就会不停的执行按下的相应动作。这明显是中断不停的产生了,真是不知道如何搞的。现在的机子是成品不给拆卸,示波器用不上了,真是奇了,刚才我认为是是BSP没有处理好中断。OEMInterruptHandler函数有禁止中断的功能,在处理完相应的线程以后,我们必须调用InterruptDone函数来重新使能中断,我看了一下代码,发现这个OEMInterruptHandler并没有问题,并且即使没有禁止,也只会在按下的时候多次中断发生,而不会没有按的时候不停的中断。我觉得还是这个ZLG7290的问题,极有可能他不停的产生了中断信号,明天使用示波器之后就会知道了。

     现在不妨看看这个键盘驱动是怎么回事。在命令行窗口输入 dumpbin  /exports  键盘驱动DLL

      --明天继续吧,下班打篮球了。

      继续.........

     先来看看这个DLL到处了什么函数。

 

LIBRARY         LAYOUTMANAGER——哈哈,这个名字可以改动的吗?以前没有注意这个问题。

 EXPORTS

 KeybdDriverInitializeEx
 KeybdDriverPowerHandler
 KeybdDriverGetInfo
 KeybdDriverSetMode
 KeybdDriverInitStates
 KeybdDriverVKeyToUnicode
 KeybdDriverMapVirtualKey

 LayoutMgrGetKeyboardType
 LayoutMgrGetKeyboardLayout
 LayoutMgrGetKeyboardLayoutName
 LayoutMgrGetKeyboardLayoutList
 LayoutMgrLoadKeyboardLayout
 LayoutMgrActivateKeyboardLayout

 IL_00000409
 Matrix
 PS2_AT_00000409

     从这些函数找突破口很容易找到问题所在。

     根据现象,我觉得产生这种原因有两种可能:一个是中断不停的产生,一个是没有检测按键弹起出了问题。我设置接ZLG7290的中断引脚的EINT11为双边沿触发的?难道上升沿触发无效(即检测按键弹起)?好用sunrain_hjb的工具修改一下中断方式看看到底是怎么回事。

      

       

 

     0x22224242是把EINT11设置成上升沿触发(检测键盘弹起中断),这样之后按键按下弹起不会做任何动作了,难道真的是没有检测到上升沿中断?我把把EINT11设置成下降沿触发(检测键盘按下中断),按键又能工作了,效果和双边触发一样。上面的猜测不一定成功,要把键盘的IST移到BSP中加入打印信息就知道是否产生了上升沿触发中断了。

     郁闷,当设置成上升沿触发的时候果然什么反映都没有啊,怎么搞的?难道上升沿是什么事情都不做?

     我在keyboard IST里面加了打印信息,来看看按一次是否能产生两次中断。

 

BOOL
KeybdIstLoop(
    PKEYBD_IST pKeybdIst
    )
{
    SETFNAME(_T("KeybdIstLoop"));

    UINT32  rguiScanCode[16];
    BOOL    rgfKeyUp[16];
    UINT    cEvents;
 // add by wogo at 2009-03-12
 RETAILMSG(1, (TEXT("In KeybdIstLoop Funtion:\r\n")));
    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)
    {
  // add by wogo at 2009-03-12
  RETAILMSG(1, (TEXT("Deal with hevInterrupt@@@!!! :\r\n")));
        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);
  // add by wogo at 2009-03-12
  RETAILMSG(1, (TEXT("InterruptDone(pKeybdIst->dwSysIntr_Keybd)@@@!!! :\r\n")));
    }

    goto wait_for_keybd_interrupt;

    ERRORMSG(1, (TEXT("KeybdIstLoop: Keyboard driver thread terminating.\r\n")));
 RETAILMSG(1, (TEXT("KeybdIstLoop: Keyboard driver thread terminating!!! :\r\n")));
    return TRUE;
}

 

     找到问题了,果然按下一次按键只打印了如下信息

Deal with hevInterrupt@@@!!! :
InterruptDone(pKeybdIst->dwSysIntr_Keybd)@@@!!! :
     按照常理,使用双边触发,按一次应该打印如下。

Deal with hevInterrupt@@@!!! :
InterruptDone(pKeybdIst->dwSysIntr_Keybd)@@@!!! :
Deal with hevInterrupt@@@!!! :
InterruptDone(pKeybdIst->dwSysIntr_Keybd)@@@!!! :

     现在难搞了,使用应用程序去读中断寄存器的设置,读出是0x22226242,这个和要求完全吻合,怎么就不产生双边沿触发呢?难道是干扰?我的天啊,真是越来越神奇了。神啊,救救我吧!

     后来我根据CSDN的shuiyan牛人的建议做了如下事情:

     一、在按下之后禁止下降沿中断,使能上升沿中断——》结果:当按下键盘太久的时候,可以产生弹起中断,快点只能产生按下中断;配置成双边触发却不行,这个说明双边触发的反映速度比单片触发要慢。

     二、把中断线程里面的代码全部删除——》结果:可以产生按下、弹起中断。这个足以证明是中断处理线程调用的ZLG7290的键盘扫描函数花掉了大量时间,后来我把里面的for循环延时全部删除,但是还是无济于事,后来逼急了想了个绝招——在按下之后设置一个标志告诉系统,已经按下,这样系统就不会不停的做同一件事情啊。结果成功解决问题。

     现在把结果公布,造福后人——把微软的键盘IST移植到BSP下添加的。

键盘功能通过偏方实现了功能,但是不能扑捉到键盘弹起中断的问题依然没有解决。

我在按下线程里面加了一个键盘弹起的标志,告诉系统,就这样,这个键盘就搞定了。哈哈
哎,就是加了两行东西。
wait_for_keybd_interrupt:
    if (WaitForSingleObject(pKeybdIst->hevInterrupt, INFINITE) == WAIT_OBJECT_0)
    {
// add by wogo at 2009-03-12
//RETAILMSG(1, (TEXT("Deal with hevInterrupt@@@!!! :\r\n")));
//#if 0
        cEvents = (*pKeybdIst->pfnGetKeybdEvent)
            (pKeybdIst->uiPddId, rguiScanCode, rgfKeyUp);
        //
        //RETAILMSG(1, (TEXT("cEvents=%d\r\n"), cEvents));
        for (UINT iEvent = 0; iEvent < cEvents; ++iEvent) {
        //UINT iEvent = 0
        (*pKeybdIst->pfnKeybdEvent)(pKeybdIst->uiPddId, rguiScanCode[iEvent], rgfKeyUp[iEvent]);
rgfKeyUp[iEvent]=TRUE;——我原来太执着于本身了,不过键盘功能是实现了,但是本质没有解决。
(*pKeybdIst->pfnKeybdEvent)(pKeybdIst->uiPddId, rguiScanCode[iEvent], rgfKeyUp[iEvent]);

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

        InterruptDone(pKeybdIst->dwSysIntr_Keybd);
// add by wogo at 2009-03-12
//RETAILMSG(1, (TEXT("InterruptDone.Keybd)\r\n")));
    } 

     感谢各位关照,尤其是shuiyan前辈,他自己忙着加班,还要回我的问题。

     现在来对键盘驱动做个总结吧。

     MDD太复杂了,这里就不谈了,现在就来谈PDD和IST

     C:\WINCE500\PLATFORM\SMDK2440A\Src\Drivers\Keybd\Kbdcommon里面的东西构成了PDD

     初始化(中断,IO等)——》申请中断——》调用键盘IST——》等待中断(MDD IST)

     下面代码相当重要,用来绑定IST,使MDD和PDD紧密结合起来。

 KEYBD_IST keybdIst;
 keybdIst.hevInterrupt = m_hevInterrupt;
 keybdIst.dwSysIntr_Keybd = dwSysIntr_Keybd;
 keybdIst.uiPddId = v_uiPddId;
 keybdIst.pfnGetKeybdEvent = KeybdPdd_GetEventEx2;
 keybdIst.pfnKeybdEvent = v_pfnKeybdEvent;
  
 KeybdIstLoop(&keybdIst);

      论坛同步帖子http://topic.csdn.net/u/20090312/14/51c097e2-11a8-49eb-b5f0-38bf15d84107.html

posted on 2010-11-05 10:58  gooogleman  阅读(252)  评论(0编辑  收藏  举报