WinCE下GPIO(LED可参考)的流驱动开发(附源码,供下载参考)

4 篇文章 0 订阅
2 篇文章 0 订阅

 WinCE下GPIO(LED可参考)的流驱动开发(附源码,供下载参考)

 

笔者接到导师任务,在WinCE系统下加载一个I/O口的流驱动来控制一个继电器开关,说白了就是来控制GPIO口的输入输出状态和端口电平的高低。现在手上的板子是友善公司的Tiny6410增强版。

首先,来上一张图来理一下做的思路。

 

在带有操作系统的基础上对芯片进行操作,是需要在驱动层中BSP中对GPIO文件进行编写及一系列流程的操作达到预期效果。(PS:在这块我想说一下和对单片机操作的不同,单片机的编程是直接对芯片进行操作,也就是相当于WinCE下GPIO的流驱动开发直接驱动层的操作,单片机的编程对管脚的给0给1是写死的,然而驱动的开发不能对管脚的电平写死,不然的话对于调用驱动的应用层就没意义了。)供应用层的开发来控制底层的目的。

 

接下来,废话少说,转入正题:

在用VS2005编译软件打开BSP包,整个操作只在 

C:\WINCE600\PLATFORM\SMDK6410\SRC\DRIVERS下操作,复制一个LEDDriver的驱动,重命名为XXX(如GPIO)。除了(.h 文件| .cpp 文件|.c文件|.def文件|makefile文件|sources文件)括号中的这几个文件外全部删掉。然后在.h和.cpp文件中进行对驱动的编写。在dirs文件中添加/GPIO(这里仿照已经添加驱动的格式,添加自己驱动的名字,最后一个驱动的名字后面可以不加/)。

从原理图可以知道如果我们要控制GPIOxxx , 只需要 GPMx 输出高电平, 如果要降低 GPIOxxx, 只需要 GPMx 输出低电平即可。
 
I.  由于在 WINCE 中使用都是虚拟的地址, 所以需要将实际的物理地址转换为虚拟地址来使用。 在系统提供的 BSP 中提供了一个函数来实现从物理地址到虚拟地址的映射。

1. void *DrvLib_MapIoSpace (UINT32 PhysicalAddress , UINT32 NumberOfBytes ,BOOL CacheEnable )
2.  把物理地址转换为虚拟地址。(其实它就是在地址映射表中查找相应的物理地址,然后返回对应的虚拟地址加上它的偏移。)

3.  UINT32 PhysicalAddress :要实现映射的物理地址的起始地址。

4.  UINT32 NumberOfBytes : 要映射物理地址的长度。

5.  BOOL CacheEnable :该物理地址是否使用了CACHE.( 具体参照地址映射表) 。

II.  GPIOXXX 上下文结构体的定义

1.  定义了一个 GPIOXXX 驱动的上下文, 用来保存 GPIOXXX 驱动的信息。 但是只是简单的 GPIOXXX 驱动, 没有包含多的数据。

typedef struct
{
    volatile S3C6410_GPIO_REG   *pGPIOReg ;
}GPIOXXX_PUBLIC_CONTEXT , *PGPIOXXX_PUBLIC_CONTEXT ;
2 .S3C6410_GPIO_REG 是BSP 预先定义的一个GPIO 使用的数据结构。

III. GPIO 寄存器的使用。 GPIO 寄存器的地址都映射到了虚拟的地址上。

BSP 提供了一个结构体方便 GPIO 寄存器的使用,在gpio.h文件。

 

1.   typedef struct
{          ……………..

             UINT32 GPMCON;           // 820           

UINT32GPMDAT;            // 824          

 UINT32 GPMPUD;           // 828      

    ………………..

} S3C6410_GPIO_REG,*PS3C6410_GPIO_REG;

 

2. 在使用这个结构全的时候把 GPIO 的虚拟地址的基地址映射到此结构的开始即可以操作此结构体的数据来操作实际的寄存器.。

 

3. 进行GPIO 物理地址到虚拟地址的映射: pGPIOXXXContext->pGPIOReg = (volatile S3C6410_GPIO_REG *)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_GPIO , sizeof (S3C6410_GPIO_REG ), FALSE ) ;

 

 IV.   实现 GPIOXXX 灯状态的操作。
1. 获得了 GPIO 的虚拟地址就可以像实际的物理地址那样实现寄存器的操作。

2.        

a) // 使能上拉
b) pGPIOXXXContext ->pGPIOReg ->GPMPUD |= 0x0ff;
c)   // 设置为输出

d) pGPIOXXXContext ->pGPIOReg ->GPMCON = 0x111111;
e)    // 关闭所有的
GPIOXXX
f) GPIOXXX_ALL_OFF (pGPIOXXXContext ->pGPIOReg ->GPMDAT );
3. 为了方便进行操作,定义了一组宏。


// 打开或关闭GPIOXXX0
#define GPIOXXX0_ON (x )   (x |= 0x00000001)
#define GPIOXXX0_OFF (x )  (x &= 0xfffffffe)
// 打开或关闭
GPIOXXX1
#define GPIOXXX1_ON (x )   (x |= 0x00000002)
#define GPIOXXX1_OFF (x )  (x &= 0xfffffffd)
// 打开或关闭
GPIOXXX2
#define GPIOXXX2_ON (x )   (x |= 0x00000004)
#define GPIOXXX2_OFF (x )  (x &= 0xfffffffb)
// 打开或关闭
GPIOXXX3
#define GPIOXXX3_ON (x )   (x |= 0x00000008)
#define GPIOXXX3_OFF (x )  (x &= 0xfffffff7)
// 打开或关闭所有的
GPIOXXX
#define GPIOXXX_ALL_ON (x )    (x |= 0x0000000f)
#define GPIOXXX_ALL_OFF (x )   (x &= 0xfffffff0)
 V. 添加与硬件打交道的函数

XXX_Init、XXX_Deinit、XXX_Open、XXX_Close、XXX_Read、XXX_Write、XXX_PowerUp、
  XXX_PowerDown、XXX_Seek、XXX_IOControl,这些函数与硬件打交道。

其中最重要的是XXX_Init初始化,和XXX_IOControl完成驱动的功能。

驱动完成后,应用层利用函数:CreateFileDeviceIoControl ReadFile WriteFile来调用驱动文件,在WinCE中,驱动是以文件的形式进行处理的。这些函数方便用户使用驱动程序。

基本思路: 1实现动态库(里面实现硬件连接,端口控制  语言 C/C++   其实就是功能函数。人员知识要求:所开驱动芯片引脚,时序,功能  CPU控制端口的确认,如果CPU不支持,开发人员需要模拟时序控制芯片)          

  2将刚才编好的DALL文件提交系统
 3设置注册表项            

 4设备管理器在系统启动后会调用你这个DALL
接下来就是你看到上面的几个函数

 VI.  有关函数介绍
  1DLLENTRY(HINSTAN  DLLINSTANCE  Dllinstance  ,INT  Reason,LPVOID  Resered)  这个函数是DLL入口函数设备管理器会调用这个函数加载或者卸载动态库函数

  参数说明:DALL 句柄,初始化DALL  卸载DALL

   接下来从这些函数开始

XXX_Init  这个函数调用次序经次于上面那个而且可以多次调用。这个函数调用后,用户就可以在用户态调用Creatfile()  函数打开设备XXX(注意这时候,你的驱动就是一个设备,明白吗)设备管理器就会调用

XXX_Open()这就是原理,仔细想想原来就是这么回事,不过我说的这样明白,有些人会说,太抽象。

用户调用Creatfile()   就是判断这个动态库是否打开,如果失败,就提示加载失败,也就是说系统打开失败

XXX_Deinit、这个函数是设备管理器卸载你的设备时调用的(你的设备就是你的DALL),他要干什么,难道你不明白吗。

XXX_Open、上面讲了里面有三个参数,设备信息,打开方式

XXX_Close、这个就是关闭,用户调用CLOSEHANDLE关闭时,设备管理器就调用这个函数
XXX_Read  

XXX_Write  

XXX_PowerUp、这个里面什么都不要干,否则后果自负  不干就RETRUN

XXX_PowerDown、什么都不要干。

XXX_Seek、这个函数是上电。

XXX_IOControl,驱动所有功能要在这个里面实现,里面有8个参数

到这里重点来了,我来附一段.cpp的驱动源代码。(这个示例文件比较简单,没有.h文件),仅供参考。

#include <windows.h>

#include <ceddk.h>

#include <nkintr.h>

#include <pm.h>

#include <DrvLib.h>

#include <s3c6410_gpio.h>

#include <s3c6410_base_regs.h>

#include "pmplatform.h"

#include "Pkfuncs.h"

#include "ioctl_cfg.h"

 

#define IO_CTL_GPH_1_ON 0x01

#define IO_CTL_GPH_2_ON 0x02

#define IO_CTL_GPH_3_ON 0x03

#define IO_CTL_GPH_4_ON 0x04

#define IO_CTL_GPH_ALL_ON 0x05

#define IO_CTL_GPH_1_OFF 0x06

#define IO_CTL_GPH_2_OFF 0x07

#define IO_CTL_GPH_3_OFF 0x08

#define IO_CTL_GPH_4_OFF 0x09

#define IO_CTL_GPH_ALL_OFF 0x0a

 

 

static volatile S3C6410_GPIO_REG * g_pGPIOReg = NULL;

 

static void Virtual_Alloc()

{

 

    // GPIO Virtual alloc

    g_pGPIOReg =(S3C6410_GPIO_REG *)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_GPIO,sizeof(S3C6410_GPIO_REG), FALSE);

    if (g_pGPIOReg == NULL) {

              RETAILMSG(1,(TEXT("Fors2440IOP: VirtualAlloc faiGPH!\r\n")));

    }

      

}

 

 

BOOL WINAPI 

DllEntry(HANDLE       hinstDLL,

                     DWORDdwReason,

                     LPVOID /*lpvReserved */)

{

       switch(dwReason)

       {

       case DLL_PROCESS_ATTACH:

              DEBUGREGISTER((HINSTANCE)hinstDLL);

              return TRUE;

       case DLL_THREAD_ATTACH:

              break;

       case DLL_THREAD_DETACH:

              break;

       case DLL_PROCESS_DETACH:

              break;

#ifdef UNDER_CE

       case DLL_PROCESS_EXITING:

              break;

       case DLL_SYSTEM_STARTED:

              break;

#endif

       }

 

       return TRUE;

}

 

 

BOOL GPH_Deinit(DWORD hDeviceContext)

{

       BOOL bRet = TRUE;

      

       RETAILMSG(1,(TEXT("USERGPH:GPH_Deinit\r\n")));

 

       return TRUE;

}

 

 

static BOOL GPHGpioInit()

{

       RETAILMSG(1,(TEXT("GPH_Gpio_Setting----\r\n")));

       g_pGPIOReg->GPKCON0 =(g_pGPIOReg->GPKCON0 & 0xFFFFU) | 0x11110000U;

       g_pGPIOReg->GPKDAT |=0xF0U;

       return TRUE;

}

 

static BOOL GPHSet(int number, int value)

{

       if (number >= 0&& number < 4) {

              if (value) {

                     g_pGPIOReg->GPKDAT&= ~( 1<< (4+number));

              } else {

                     g_pGPIOReg->GPKDAT|= ( 1<< (4+number));

              }

              return TRUE;

       } else {

              return FALSE;

       }

}

 

 

 

DWORD GPH_Init(DWORD dwContext)

{

      

       RETAILMSG(1,(TEXT("GPH_Init----\r\n")));

 

       Virtual_Alloc();

      

       GPHGpioInit();

       return TRUE;

}

 

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

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

BOOL GPH_IOControl(DWORD hOpenContext,

                               DWORD dwCode,

                               PBYTE pBufIn,

                               DWORD dwLenIn,

                               PBYTE pBufOut,

                               DWORD dwLenOut,

                               PDWORD pdwActualOut)

{

       switch(dwCode)

       {

       case IO_CTL_GPH_1_ON:

              GPHSet(0, 1);

              break;

       case IO_CTL_GPH_2_ON:

              GPHSet(1, 1);

              break;

       case IO_CTL_GPH_3_ON:

              GPHSet(2, 1);

              break;

       case IO_CTL_GPH_4_ON:

              GPHSet(3, 1);

              break;

       case IO_CTL_GPH_ALL_ON:

              GPHSet(0, 1);

              GPHSet(1, 1);

              GPHSet(2, 1);

              GPHSet(3, 1);

              break;

       case IO_CTL_GPH_1_OFF:

              GPHSet(0, 0);

              break;

       case IO_CTL_GPH_2_OFF:

              GPHSet(1, 0);

              break;

       case IO_CTL_GPH_3_OFF:

              GPHSet(2, 0);

              break;

       case IO_CTL_GPH_4_OFF:

              GPHSet(3, 0);

              break;

       case IO_CTL_GPH_ALL_OFF:

              GPHSet(0, 0);

              GPHSet(1, 0);

              GPHSet(2, 0);

              GPHSet(3, 0);

              break;

       default:

              break;          

       }

   

       RETAILMSG(1,(TEXT("GPH:Ioctlcode = 0x%x\r\n"), dwCode));

       return TRUE;

}

 

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

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

DWORD GPH_Open(DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode)

{

       RETAILMSG(1,(TEXT("USERGPH:GPH_Open\r\n")));

       return TRUE;

}

 

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

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

BOOL GPH_Close(DWORD hOpenContext)

{

       RETAILMSG(1,(TEXT("USERGPH:GPH_Close\r\n")));

       GPHSet(0, 0);

       GPHSet(1, 0);

       GPHSet(2, 0);

       GPHSet(3, 0);

       return TRUE;

}

 

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

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

void GPH_PowerDown(DWORD hDeviceContext)

{

       RETAILMSG(1,(TEXT("USERGPH:GPH_PowerDown\r\n")));

}

 

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

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

void GPH_PowerUp(DWORD hDeviceContext)

{

       RETAILMSG(1,(TEXT("USERGPH:GPH_PowerUp\r\n")));

 

}

 

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

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

DWORD GPH_Read(DWORD hOpenContext, LPVOID pBuffer, DWORD Count)

{

       RETAILMSG(1,(TEXT("USERGPH:GPH_Read\r\n")));

       return TRUE;

}

 

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

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

DWORD GPH_Seek(DWORD hOpenContext, long Amount, DWORD Type)

{

       RETAILMSG(1,(TEXT("USERGPH:GPH_Seek\r\n")));

       return 0;

}

 

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

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

DWORD GPH_Write(DWORD hOpenContext, LPCVOID pSourceBytes, DWORD NumberOfBytes)

{

       RETAILMSG(1,(TEXT("USERGPH:GPH_Write\r\n")));

       return 0;

}

VII.后续流程

1.新建.def文件。添加配置(目录没有这个文件的新建,有这个文件的进行修改就可以了)

;

; Windows CE GPH Driver. Written by capbily

 

LIBRARY userGPH

EXPORTS

         GPH_Close

         GPH_Deinit

         GPH_Init

         GPH_IOControl

         GPH_Open

         GPH_PowerDown

         GPH_PowerUp

         GPH_Read

         GPH_Seek

         GPH_Write

2.新建makefile文件(目录没有这个文件的新建,有这个文件的没有必要修改就可以用了)

!if 0

Copyright (c) Microsoft Corporation.  All rights reserved.

!endif

!if 0

Use of this sample source code is subjectto the terms of the Microsoft license agreement under which you licensed thissample source code. If you did not accept the terms of the license agreement,you are not authorized to use this sample source code. For the terms of thelicense, please see the license agreement between you and Microsoft or, ifapplicable, see the LICENSE.RTF on your install media or the root of your toolsinstallation. THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NOWARRANTIES. !endif

#

# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a newsource

# file to this component.  This file merely indirects to the real makefile

# that is shared by all the components ofWindows CE

#

!INCLUDE $(_MAKEENVROOT)\makefile.def

3.新建sources文件

SYNCHRONIZE_DRAIN=1

RELEASETYPE=PLATFORM

TARGETNAME=GPH

TARGETTYPE=DYNLINK

SOURCES= GPH.cpp

TARGETLIBS= \

   $(_COMMONSDKROOT)\lib\$(_CPUINDPATH)\coredll.lib    \

   $(_TARGETPLATROOT)\lib\$(_CPUINDPATH)\DriverLib.lib

INCLUDES_PATH=$(_TARGETPLATROOT)\src\drivers\GPH          

FILE_VIEW_ROOT_FOLDER= \

做完这一步之后,打开vs2005环境打开BSP,在PLATFORM\SMDK6410\SRC\DRIVERS\GPIO进行编译此驱动。

4.进行添加platform.bib文件 和platform.reg注册文件。(这一步直接在c盘目录打开进行添加,这两个文件在一起C:\WINCE600\PLATFORM\SMDK6410\FILES下)

在platform.bib文件中添加:

GPIO.dll             $(_FLATRELEASEDIR)\GPIO.dll               NK      SHK 

在platform.reg文件中添加:

;==================================GPIO   1-4=================

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\GPIO]

   "Prefix"="GPI"

   "Dll"="GPIO.dll"

   "Order"=dword:8

   "Index"=dword:1

5.然后再vs2005中编译bsp,(Build 选项卡中选择Advanced Build Commands中的倒数第二项编译即可。)

6.编译通过

后在C:\WINCE600\OSDesigns\mini6410\mini6410\RelDir\Samsung_SMDK6410_Release中找到NK.nb0和NK.bin文件烧写到Tiny6410 中,初步在板子的注册表文件中查看要添加的驱动是否添加。应用层的调用示例请查看后续博文。。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值