操作GPIO流驱动生成(W83627为例)

涉及版权,欲用于商业用途,务必与作者联系; 

  QQ26764135

 伊妹儿/麦思恩:liam7953@yahoo.com.cn 

 

在WINCE6中,应用程序无法直接访问GPIO,而必须通过一个驱动程序,在此,我们用一个通用的流驱动来实现。

一个简单的流驱动包含如下几个部分:

XXX.CPP    \\实现文件

XXX.def     \\符号导出文件

makefile     \\编译文件

sources     \\

GPI.reg      \\注册表文件,假如需要做进包里,需要增加进入工程注册表,假如动态加载,需要用程序将其写到系统中

 

//如下部分为源程序部分

// GPI.cpp : Defines the entry point for the DLL application.
//
#include "GPI.h"
#include <windows.h>
#include <memory.h>
#include <nkintr.h>
#include <ceddk.h>
#include <winioctl.h> 


#pragma comment(lib,"ceddk.lib")
 
#define GIO_VENDOR  CTL_CODE(FILE_DEVICE_SERIAL_PORT, 2090, METHOD_BUFFERED, FILE_ANY_ACCESS)    

static UCHAR * virGpioMemBase = NULL;

/**************************************************************************
 *                            基础函数定义                                *
 **************************************************************************/
/************************************************************
* OutPortByte
*
* 向特定GPIO地址输出字节
*/
static void OutPortByte(WORD wAddr,byte bValue)
{
 if(NULL != virGpioMemBase)
 {
  if( W83627_EFER == wAddr)
  {
   WRITE_PORT_UCHAR(virGpioMemBase,bValue);
  }
  else
  {
   WRITE_PORT_UCHAR(virGpioMemBase+1,bValue);  
  }
 }
 else
 {
  RETAILMSG(TRUE, (TEXT(">>YOU NAME-OutPortByte return for virGpioMemBase NULL\r\n")));    
 }

    RETAILMSG(TRUE, (TEXT(">>YOU NAME-OutPortByte: Add:0x%x, Val:0x%x\r\n"),wAddr,bValue));   
}

/************************************************************
* InPortByte
*
* 从特定GPIO地址读取字节
*/
static byte InPortByte(WORD wAddr)
{
 byte tmpRtnVal = 0xFF;

 if(NULL != virGpioMemBase)
 {
  if( W83627_EFER == wAddr)
  {
   tmpRtnVal = READ_PORT_UCHAR(virGpioMemBase);
  }
  else
  {
   tmpRtnVal = READ_PORT_UCHAR(virGpioMemBase+1);  
  }
 }
 else
 {
  RETAILMSG(TRUE, (TEXT(">>YOU NAME-InPortByte return for virGpioMemBase NULL\r\n")));    
 }
 
  RETAILMSG(TRUE, (TEXT(">>--YOU NAME-InPortByte, Add:0x%x Val:0x%x!\r\n"),wAddr,tmpRtnVal));
   
    return tmpRtnVal;
}

/************************************************************
* W83627Set
*
* 设定W8362 PIO A 值
*/
static void W83627Set(byte ucParaVal)
{
    RETAILMSG(TRUE, (TEXT(">>++YOU NAME-W83627Set Val:0x%x!\r\n"),ucParaVal));  
    //enter the extended function mode,two successive writes of 0x87 must be applied to
    //Extended Function Enable Registers(EFERs,i.e. 2Eh)
    OutPortByte(W83627_EFER,0x87);
    OutPortByte(W83627_EFER,0x87);
 
    //CRF1(GP10-GP17 data register Default 0x00)
    //if a port is programmed to be an output port,then its respective bit can be read/write
    //if a port is programmed to be an input port,then its respective bit can only be read
    OutPortByte(W83627_EFIR,0x07);
    OutPortByte(W83627_EFDR,0x08);
 
    //实际写值到对应的寄存器
    OutPortByte(W83627_EFIR ,0xF1);
    OutPortByte(W83627_EFDR ,ucParaVal);   
 
    //exit extended function mode
    OutPortByte(W83627_EFER,0xAA);
 
    Sleep(1);
}

/************************************************************
* W83627Set
*
* 读取W8362 PIO A 值
*/
static byte W83627Get()
{
    byte    tmpVal = 0;
   
    //enter the extended function mode,two successive writes of 0x87 must be applied to
    //Extended Function Enable Registers(EFERs,i.e. 2Eh)
    OutPortByte(W83627_EFER,0x87);
    OutPortByte(W83627_EFER,0x87);
    //Configurate the configuration registers
     
    //configure logical device 7(gp10-gp17),configuration register CRF0,CRF1,CRF2
    //select logical device 7
    OutPortByte(W83627_EFIR,0x07);
    OutPortByte(W83627_EFDR,0x08);
     
    //CRF1(GP10-GP17 data register Default 0x00)
    //if a port is programmed to be an output port,then its respective bit can be read/write
    //if a port is programmed to be an input port,then its respective bit can only be read
    OutPortByte(W83627_EFIR,0xF1); 
    tmpVal = InPortByte(W83627_EFDR);
 
    //exit extended function mode
    OutPortByte(W83627_EFER,0xAA);

    Sleep(1);
    RETAILMSG(TRUE, (TEXT(">>++YOU NAME-W83627Get4 Val:0x%x!\r\n"),tmpVal)); 

    return (byte)(tmpVal);
}

/************************************************************
* W83627VendorIdGet
*
* 读取W8362 部分厂家编号
*/
static byte W83627VendorIdGet()
{
    byte    tmpVal = 0;
      
    //enter the extended function mode,two successive writes of 0x87 must be applied to
    //Extended Function Enable Registers(EFERs,i.e. 2Eh)
    OutPortByte(W83627_EFER,0x87);
    OutPortByte(W83627_EFER,0x87);
 
    //Configurate the configuration registers
    OutPortByte(W83627_EFER,0x20);
    tmpVal = InPortByte(W83627_EFDR);

    //exit extended function mode
    OutPortByte(W83627_EFER,0xAA);

    Sleep(1);
 RETAILMSG(TRUE, (TEXT(">>++YOU NAME-W83627VendorIdGet:0x%x\r\n"),tmpVal));  
 
    return (byte)(tmpVal);
}

/************************************************************
* W83627GPIInit
*
* 初始化W83627GPI A 相关的寄存器
*/
static void W83627GPIInit()
{
    //enter the extended function mode,two successive writes of 0x87 must be applied to
    //Extended Function Enable Registers(EFERs,i.e. 2Eh)
    OutPortByte(W83627_EFER,0x87);
    OutPortByte(W83627_EFER,0x87);

    //Configurate the configuration registers
    OutPortByte(W83627_EFIR ,0x2a); //EFIR write control register index to EFIR
    OutPortByte(W83627_EFDR ,0x01); //GPIO20 119S

    //Configurate the configuration registers
    OutPortByte(W83627_EFIR ,0x2b); //EFIR write control register index to EFIR
    OutPortByte(W83627_EFDR ,0xff); //GPIO21~GPIO27
   
    //configure logical device 7(gp10-gp17),configuration register CRF0,CRF1,CRF2
    //select logical device 7
    OutPortByte(W83627_EFIR,0x07);
    OutPortByte(W83627_EFDR,0x08);

    OutPortByte(W83627_EFIR,0x30);
    OutPortByte(W83627_EFDR,0x01);

    //CRF0(GP10-GP17 I/O selection register   Default 0xff)
    //when set to a ’1’, respective GPIO port is programmed as an input port
    //when set to a ’0’, respective GPIO port is programmed as an output port
    OutPortByte(W83627_EFIR,0xF0);
    OutPortByte(W83627_EFDR,0x00);
    //GPIO10,11,12,13输入,14,15,16,17,输出
    //CRF2(GP10-GP17 inversion register Default 0x00)
    //when set to a ’1’,the imcoming/outgoing port value is inverted
    //when set to a ’0’,the imcoming/outgoing port value is the same as in data register
    OutPortByte(W83627_EFIR,0xF2);
    OutPortByte(W83627_EFDR,0x00);
     
    //CRF1(GP10-GP17 data register Default 0x00)
    //if a port is programmed to be an output port,then its respective bit can be read/write
    //if a port is programmed to be an input port,then its respective bit can only be read
    OutPortByte(W83627_EFIR,0xF1);
    OutPortByte(W83627_EFDR,0x00);

    //exit extended function mode
    OutPortByte(W83627_EFER,0xAA);
    Sleep(10);
   
    RETAILMSG(TRUE, (TEXT(">>++YOU NAME-W83627GPIInit\r\n"))); 
}

BOOL APIENTRY DllMain(
                       HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{   
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
           
        default:
            break;
    }
       
    return TRUE;
}

GPI_API DWORD GPI_Init(LPCTSTR pContext,DWORD dwBusContext)
{
    PHYSICAL_ADDRESS IoAddress;
    IoAddress.LowPart  = W83627_EFER;//硬件地址
    IoAddress.HighPart = 0;

    virGpioMemBase = ( UCHAR *)MmMapIoSpace( IoAddress , 2 , FALSE );
    if(NULL != virGpioMemBase)
    {
     RETAILMSG(TRUE, (TEXT(">>YOU NAME-OutPortByte:MmMapIoSpace return:0x%x\r\n"),virGpioMemBase));       
    }
    else
    {
     RETAILMSG(TRUE, (TEXT(">>YOU NAME-OutPortByte,MmMapIoSpace return NULL\r\n")));
  return (FALSE);
    }

    if(W83627_VENDOR != W83627VendorIdGet())
    {  
        RETAILMSG(TRUE, (_T(">>++YOU NAME-ERROR::W83627VendorIdGet Check failed\r\n")));  

        return (FALSE);          
    } 
    W83627GPIInit();

    RETAILMSG(TRUE, (TEXT(">>--YOU NAME-GPI_Init\r\n")));

    return(TRUE);      
}

GPI_API BOOL  GPI_Deinit(DWORD hDeviceContext)
{
 if(NULL != virGpioMemBase)
 {
  MmUnmapIoSpace( (PVOID)virGpioMemBase , 2);
  virGpioMemBase = NULL;
 }

    RETAILMSG(TRUE, (TEXT(">>++YOU NAME-GPI_Deinit\r\n")));

    return (TRUE);
}

GPI_API DWORD GPI_Open (DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode)

    RETAILMSG(TRUE, (TEXT(">>++YOU NAME-GPI_Open\r\n"))); 

    return(TRUE); 
}

GPI_API BOOL  GPI_Close(DWORD hOpenContext)
{
    RETAILMSG(TRUE, (TEXT(">>++YOU NAME-GPI_Close\r\n"))); 

    return TRUE;  
}

GPI_API DWORD GPI_Read(DWORD hOpenContext,  LPVOID pBuffer, DWORD Count)
{
    BYTE * pdatabuf = NULL;
   
    pdatabuf = (BYTE * )pBuffer;
    *pdatabuf = W83627Get();

 RETAILMSG(TRUE, (TEXT(">>--YOU NAME-GPI_Read Val:0x%x\r\n"),*pdatabuf)); 
       
    return (TRUE);       
}

GPI_API DWORD GPI_Write(DWORD hOpenContext,LPCVOID pBuffer,DWORD Count)
{
    BYTE* pdatabuf = NULL;
       
    pdatabuf = (BYTE*)pBuffer;
    W83627Set(*pdatabuf);   
   
 RETAILMSG(TRUE, (TEXT(">>--YOU NAME-GPI_Write Val:0x%x\r\n"),*pdatabuf));
   
    return (TRUE);
}

//======================================================================
// ANY_Seek - Called when SetFilePtr called
//
GPI_API DWORD GPI_Seek (DWORD hOpenContext, long Amount, WORD Type)
{
    RETAILMSG(TRUE, (TEXT(">>--YOU NAME-GPI_Seek\r\n")));
     
    return (TRUE);
}

//======================================================================
// ANY_IOControl - Called when DeviceIocontrol called
//
GPI_API BOOL GPI_IOControl(DWORD hOpenContext,DWORD dwCode,PBYTE pBufIn,
      DWORD dwLenIn,PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut)
{
    BOOL bError = FALSE;  
    switch(dwCode)  
    {  
        case GIO_VENDOR:  
   *(BYTE*)pBufOut = W83627VendorIdGet();
   RETAILMSG(TRUE, (TEXT(">>--YOU NAME-GPI_IOControl-Vendor Read, Val:0x%x\r\n"),*(BYTE*)pBufOut));
            break;  

  default:
   break;
    }  
    RETAILMSG(TRUE, (TEXT(">>--YOU NAME-GPI_IOControl\r\n"))); 

    return bError;  
}

//======================================================================
// ANY_PowerDown - Called when system suspends
//
GPI_API void GPI_PowerDown (DWORD hDeviceContext)
{
    RETAILMSG(TRUE, (TEXT(">>++YOU NAME-GPI_PowerDown\r\n"))); 
 
    return;
}
//======================================================================
// ANY_PowerUp - Called when resumes
//
GPI_API void GPI_PowerUp (DWORD hDeviceContext)
{
    RETAILMSG(TRUE, (TEXT(">>++YOU NAME-GPI_PowerUp\r\n")));
     
    return;
}

 

//如下部分为函数导出部分

LIBRARY         GPI

EXPORTS        
    GPI_Init
    GPI_Deinit
    GPI_Open
    GPI_Close  
    GPI_Read   
    GPI_Write
    GPI_Seek
    GPI_IOControl
    GPI_PowerDown
    GPI_PowerUp

 

//MAKE file的实现比较简单,和其他的内容是一样的

!INCLUDE $(_MAKEENVROOT)\makefile.def

 

//source文件实现

RELEASETYPE=PLATFORM
TARGETDEFNAME=GPI
DEFFILE=$(TARGETDEFNAME).def   ##指定DLL文件导出接口函数

TARGETNAME=GPI
TARGETTYPE=DYNLINK
DLLENTRY=DllMain       ##DLL入口地址


SOURCES= \
    XXX.cpp \

CDEFINES=$(CDEFINES) -DGPI_EXPORTS

TARGETLIBS= \
    $(_PROJECTROOT)\cesysgen\sdk\lib\$(_CPUINDPATH)\coredll.lib \
 $(_SYSGENOAKROOT)\lib\$(_CPUINDPATH)\ceddk.lib

 

将如上几个文件放置到WINCE的源代码目录下面,然后编译,就可以实现GPIO操作的流驱动了。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值