关闭

WinCE6.0 DEVICEEMULATOR BSP在GEC2410开发板上的移植(3)-PwrButton驱动移植及分析

标签: wincenullbuttonoutputmanagerallocation
1872人阅读 评论(0) 收藏 举报
分类:

PwrButton驱动实现了按键关机(PowerOff)和重启(Reset)的功能.我们这里定义开发板上的K1为PowerOff,K3为Reset,对应与CPU的EINT0和EINT2中断.
DEVICEEMULATOR BSP中已经基本实现了该驱动,在GEC2410.bat中使能PwrButton,即设置BSP_NOPWRBTN不为1:
set BSP_NOPWRBTN=
编译后通过KITL可以看到pwrbtn2410.dll已经被加载了,但是按任何按钮都没有反应.这是由于PwrButton驱动中的IO设置与我们实际板子上还不完全匹配.
在GEC2410开发板上,按键的原理图是:

在PwrButton驱动中,使用EINT0和EINT2来检测按键的输入,没有按键输入时,EINT0,EINT2被上拉为1,当K1按下时要使EINT0产生下降沿中断,KSCAN0必须为输出0,为了使K2,K9,K10按下时不产生中断,KSCAN1-3需要输出1.这样只有当K1按下时才产生EINT0的下降沿中断.
同理对K3.
我们需要的工作就是配置相应的GPIO,使KSCAN0输出0,KSCAN1-3输出1,EINT0和EINT2设置为外部中断,下降沿触发.然后在驱动中设置该中断,当中断发生时读取EINT0或EINT2对应引脚的值就可以判断K1或者K3是否按下了.
如果要读取所有键盘的值,只需要通过KSCAN0-KSCAN3分别置0扫描并读取相应的EINT管脚就能确定是哪个按键按下了.
接下来我们来看看该驱动详细的代码以及需要添加或修改的地方.
1.流驱动接口
PwrButton驱动也是个标准的流接口驱动,但是只实现了PBT_Init一个函数,其他的如PBT_Open,PBT_Read,PBT_Write都没有实现,仅仅返回0.
PBT_Init 主要工作是:
(1)从coredll.dll获得系统函数SetSystemPowerState,
(2)调用InitializeAddresses获取寄存器地址
(3)调用SetScanOutput()来设置KSCAN0-3的输出值.
(4)创建检测PowerButton(K1)和ResetButton(K3)的线程:PowerButtonIntrThread和ResetButtonIntrThread.
其中SetScanOutput()是我添加的函数,用来初始化KSCAN0-3的输出(KSCAN0为0,其余为1)
代码如下:

InitializeAddresses:
InitializeAddresses通过调用VirtualAlloc和VirtualCopy获得了GPIO寄存器和中断寄存器的虚拟地址,并转换为S3C2410X_IOPORT_REG和S3C2410X_INTR_REG结构的指针。
 
SetScanOutput:
设置KSCAN0为0,KSCAN1-3为1

2.PowerButtonIntrThread和ResetButtonIntrThread
PowerButtonIntrThread:
(1).调用EnablePowerButtonInterrupt()来初始化IO和使能中断EINT0.
(2).创建中断事件PwrButtonIntrEvent,调用KernelIoControl向系统申请IRQ_EINT0对应的逻辑中断号PwrButtonSysIntr.
(3).调用InterruptInitialize将PwrButtonSysIntr关联PwrButtonIntrEvent事件并初始化中断.
(4).等待中断事件发生
(5).中断发生后,调用PowerButtonIsPushed来检测按钮是否按下,延时200ms并再次判断是否按键释放,如果释放了确定按键有效.
(6).pfnSetSystemPowerState存在时,调用其来设置系统状态为POWER_STATE_SUSPEND
pfnSetSystemPowerState(NULL, POWER_STATE_SUSPEND, POWER_FORCE);
否则调用PowerOffSystem()关闭系统.
(7).最后InterruptDone(PwrButtonSysIntr);来通知系统中断完成.
以下是PowerButtonIntrThread代码:

ResetButtonIntrThread:
(1).调用EnableResetButtonInterrupt()来初始化IO和使能中断EINT2.
(2).创建中断事件ResetButtonIntrEvent,调用KernelIoControl向系统申请IRQ_EINT2对应的逻辑中断号ResetButtonSysIntr.
(3).调用InterruptInitialize将ResetButtonSysIntr关联ResetButtonIntrEvent事件并初始化中断.
(4).等待中断事件发生
(5).中断发生后,首先屏蔽EINT11中断(原来的EINT11是连接存储设备的,而我们的板子连接的是键盘,这句代码可以不用)
(6)调用PowerButtonIsPushed来检测按钮是否按下,延时200ms并再次判断是否按键释放,如果释放了确定按键有效.
(7).pfnSetSystemPowerState存在时,调用其来设置系统状态为POWER_STATE_RESET
pfnSetSystemPowerState(NULL, POWER_STATE_RESET, POWER_FORCE);
否则调用KernelIoControl(IOCTL_HAL_REBOOT,NULL,0,NULL,0,NULL)来重启系统.
(8).最后InterruptDone(ResetButtonSysIntr);来通知系统中断完成.
以下是ResetButtonIntrThread代码:

3.EnablePowerButtonInterrupt,EnableResetButtonInterrupt,PowerButtonIsPushed,ResetButtonIsPushed
EnablePowerButtonInterrupt和EnableResetButtonInterrupt初始化EINT0和EINT2的功能管脚和中断设置(下降沿触发)

PowerButtonIsPushed和ResetButtonIsPushed读取GPF0和GPF2的状态来确定按钮是否按下.

4.增加OAL中的GPIO初始化
KSCAN0-3的GPIO寄存器配置在OAL中的OEMInit()函数中完成,调用以下的InitGPIO来进行初始化:
具体的引脚及其功能见如下代码及注释:

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:161991次
    • 积分:2416
    • 等级:
    • 排名:第15854名
    • 原创:67篇
    • 转载:2篇
    • 译文:7篇
    • 评论:34条
    文章分类
    最新评论