查看: 2519|回复: 1

[Wince技术] Win CE中断处理实例

[复制链接]
  • TA的每日心情

    2014-4-10 13:56
  • 签到天数: 5 天

    连续签到: 1 天

    [LV.2]偶尔看看I

    发表于 2014-1-21 10:32:35 | 显示全部楼层 |阅读模式
    分享到:
    本帖最后由 forlinx2013 于 2014-1-24 09:43 编辑

    欢迎大家来到飞凌爱板网专区,对嵌入式技术感兴趣的朋友不妨多多关注一下,我们提供了公司所有开发板的所有资料,也会更新大量技术文章,欢迎大家一块学习提高!!!

    Win CE中断处理实例
    网上有很多wince中断处理的过程讲解,内容虽然充实,但是不免有些枯燥。本文将以实例的方式讲解wince6.0的中断处理过程。让初学者像学51中断一样简单明了。
    本文以飞凌ok6410开发板为开发工具,软件为wince6.0的bsp(飞凌提供),首先我们要先了解下wince的中断处理过程,虽然枯燥,但是不得不看,因为我们要大致了解下wince中断的流程,网上资料很多,在这里我就不多做说明,给大家一个介绍wince中断链接方便大家查阅http://blog.163.com/amao831@126/blog/static/915253322010315105954546/。这里面介绍的很详细,希望大家好好看。
    看完wince中断的过程我们有了一个大致的了解,从结构上看,可分为4层硬件层、内核层、OAL层、IST处理层。
    ① 硬件层就是我们GPIO引脚设计
    ② 内核层就内核处理层
    ③  OAL层其实就是一个中转层
    ④ IST层是实际我们去处理中断事件的层
    从程序上分可以分为如下几部:
    1.   初始化GPIO口
    2、  创建事件
    3、  获取IRQ的系统中断号
    4、  创建挂起的中断服务线程IST
    5、  调用InterruptInitialize以创建IRQ与事件之间的关联。(创建未挂起的中断服务线程有可能导致InterruptInitialize函数调用失败,因为该事件已经处于等待状态)
    6、  调用CeSetThreadPriority函数设置IST的优先级
    7、  启动IST线程
    在这里我就不再创建一个新的驱动了,因为前面也应有过创建新驱动的步骤。我将以led的驱动为前提进行修改,最后可以用一个按键控制一盏灯的亮灭.
    首先我们打开飞凌提供的bsp,打开led.cpp。
    1.在头文件与驱动入口函数之间加上如下代码:
    HANDLEKeyThread[6];//声明按键线程可以声明6
    HANDLEKeyEvent[6];      //声明的按键事件,为6
    UINT32g_KeySysIntr[6];    //按键逻辑中断号
    UCHARflag_led = 0;        //led亮灭标志位
    // GPIO virtual address
    staticvolatileS3C6410_GPIO_REG  *v_pIOPregs  ;
    staticvolatileS3C6410_VIC_REG *g_pVIC0Reg;

    2.写初始化gpio的代码:
    BOOLKeyGpioInit()   
    {   
            RETAILMSG(1,(TEXT("Key_Gpio_Setting----\r\n")));   
            v_pIOPregs->GPNPUD&= ~(0x0fff);            //设置按键的各个gpio为中断
            v_pIOPregs->GPNCON&= ~(0x0fff);
            v_pIOPregs->GPNCON |= 0xaaa;

            v_pIOPregs->EINT0CON0&= ~(0x0fff);
            v_pIOPregs->EINT0CON0 |= ~(0x0222);                //使能按键中断位
            v_pIOPregs->EINT0MASK&= ~(0x3f);



            return 1;
    }
    根据6410数据手册,给下列各个寄存器赋值,如果初学者不能很好的掌握寄存器的控制,可以用RETAILMSG(1,(TEXT("******* v_pIOPregs->GPNCON = %x\r\n"),v_pIOPregs->GPNCON ));这个函数可与打印出该寄存器的值。


    3.物理中断映射成系统中断号,创建中断事件及中断处理线程:

    在led—init函数中加上如下代码:
    DWORDthreadID[6];

    g_pVIC0Reg=(volatileS3C6410_VIC_REG*)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_VIC0,sizeof(S3C6410_VIC_REG),FALSE);

            KeyGpioInit() ;

            //创建IST线程  
            KeyThread[0] = CreateThread(NULL,   
                    0,   
                    (LPTHREAD_START_ROUTINE)FLKProcessThread0,   
                    0,   
                    0,   
                    &threadID[0]);   

            if (NULL == KeyThread[0] ) {   
                    RETAILMSG(1,(TEXT("ERROR: failed to Create Key Thread!\r\n")));   
                    returnFALSE;   
            }   
    创建总线程:总线程名称必须和上面创建线程的名称一致,下面各个函数用户可以上网查看,特别是各个参数的意思。

    DWORDFLKProcessThread0(void)   
    {
            UINT32IRQ;   

            //创建事件,后面与中断关联  
            KeyEvent[0] = CreateEvent(NULL, FALSE, FALSE, NULL);      
            if (!KeyEvent[0])    {   
                    RETAILMSG(1, (TEXT("ERROR: FLK: Failed to create event.\r\n")));   
                    returnFALSE;   
            }   
            //动态申请外部中断
            IRQ = IRQ_EINT0;  //物理中断号
            if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &IRQ, sizeof(UINT32), &g_KeySysIntr[0], sizeof(UINT32), NULL))    {   
                    RETAILMSG(1, (TEXT("ERROR: kEYBD: Failed to request sysintr value.\r\n")));   
                    returnFALSE;   
            }   

            //初始化中断,关联逻辑中断号与事件  
            if (!InterruptInitialize(g_KeySysIntr[0], KeyEvent[0], NULL, 0))     {   
                    RETAILMSG(1,(TEXT("Fail to initialize userkey interrupt event\r\n")));   
                    returnFALSE;   
            }
            while(1)   
            {   //等待事件发生  
                    WaitForSingleObject(KeyEvent[0], INFINITE);           
                    //处理外部中断         
                    if (flag_led == 0)
                    {
                            v_pIOPregs->GPMCON&=(~(0x0f<<4));
                            v_pIOPregs->GPMCON|=0x1<<4;
                            v_pIOPregs->GPMDAT|=(0x01<<1);
                            OutputDebugString(L"Led1 Open- LED IO Control\n");
                    }
                    else
                    {
                            v_pIOPregs->GPMCON&=(~(0x0f<<4));
                            v_pIOPregs->GPMCON|=0x1<<4;
                            v_pIOPregs->GPMDAT&=~(0x01<<1);
                            OutputDebugString(L"Led1 Close- LED IO Control\n");
                    }

                    flag_led = !flag_led;

                    InterruptDone(g_KeySysIntr[0]);//完成中断
            }
    }
    4.保存led.cpp,然后右击led工程文件选择 rebuild,从新烧写,成功后,就可以看到,当按下按键后,led灯亮了。剩下的几个按键用户可以自己去试着做!

    回复

    使用道具 举报

    该用户从未签到

    发表于 2014-1-21 20:14:46 | 显示全部楼层
    杀个发                              
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-5-31 20:31 , Processed in 0.110441 second(s), 17 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.