当前位置: 首页 > news >正文

操作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操作的流驱动了。

 

相关文章:

  • 阿里云容器宣布开放支持Kubernetes托管服务
  • admuser让squid账户管理更轻松
  • 【c++】构造函数初始化列表中成员初始化的次序性
  • 如何做好Code Review:思考、方法和实践
  • 人工智能将如何变革视频监控行业?
  • .net实现客户区延伸至至非客户区
  • Windows年底再现图片漏洞攻击!
  • Flash视频播放器flowplayer的使用
  • 彻底卸载Virtual Camera虚拟摄像头
  • 解决 PHPExcel 长数字串显示为科学计数
  • 【HIHOCODER 1403】后缀数组一·重复旋律(后缀数组)
  • C#中如何将DataTable中的数据写入Excel
  • 打印机的一些高级设置
  • Qt4--FormLayout
  • 通用服务器桩-Receiver使用说明文档
  • python3.6+scrapy+mysql 爬虫实战
  • 实现windows 窗体的自己画,网上摘抄的,学习了
  • Asm.js的简单介绍
  • axios请求、和返回数据拦截,统一请求报错提示_012
  • Flex布局到底解决了什么问题
  • JavaScript标准库系列——Math对象和Date对象(二)
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • Kibana配置logstash,报表一体化
  • node 版本过低
  • Rancher-k8s加速安装文档
  • session共享问题解决方案
  • spring boot下thymeleaf全局静态变量配置
  • Vim Clutch | 面向脚踏板编程……
  • Vue实战(四)登录/注册页的实现
  • 从0实现一个tiny react(三)生命周期
  • 从PHP迁移至Golang - 基础篇
  • 手机app有了短信验证码还有没必要有图片验证码?
  • 通过git安装npm私有模块
  • 写代码的正确姿势
  • 一份游戏开发学习路线
  • 正则表达式小结
  • media数据库操作,可以进行增删改查,实现回收站,隐私照片功能 SharedPreferences存储地址:
  • ​​快速排序(四)——挖坑法,前后指针法与非递归
  • ​草莓熊python turtle绘图代码(玫瑰花版)附源代码
  • ​插件化DPI在商用WIFI中的价值
  • #if #elif #endif
  • #Linux(权限管理)
  • #我与Java虚拟机的故事#连载16:打开Java世界大门的钥匙
  • ${factoryList }后面有空格不影响
  • (31)对象的克隆
  • (4)STL算法之比较
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (Forward) Music Player: From UI Proposal to Code
  • (poj1.3.2)1791(构造法模拟)
  • (二)Eureka服务搭建,服务注册,服务发现
  • (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致
  • (算法)前K大的和
  • (译) 函数式 JS #1:简介
  • (转)ObjectiveC 深浅拷贝学习
  • (轉貼)《OOD启思录》:61条面向对象设计的经验原则 (OO)