控制单个GPIO端口的驱动

 

控制单个GPIO端口的驱动

 

 

// GpioDriver.cpp : Defines the entry point for the DLL application.

//

 

#include <ceddk.h>

#include "GpioDriver.h"

#include "stdafx.h"

 

typedef struct _GPIO{

    volatile unsigned int   PORTCFG0;               // 0x000 R/W Port Configuration Register 0

    volatile unsigned int   PORTCFG1;               // 0x004 R/W Port Configuration Register 1

    volatile unsigned int   PORTCFG2;               // 0x008 R/W Port Configuration Register 2

    volatile unsigned int   PORTCFG3;               // 0x00C R/W Port Configuration Register 3

    volatile unsigned int   PORTCFG4;               // 0x010 R/W Port Configuration Register 4

    volatile unsigned int   PORTCFG5;               // 0x014 R/W Port Configuration Register 5

    volatile unsigned int   PORTCFG6;               // 0x018 R/W Port Configuration Register 6

    volatile unsigned int   PORTCFG7;               // 0x01C R/W Port Configuration Register 7

    volatile unsigned int   PORTCFG8;               // 0x020 R/W Port Configuration Register 8

    volatile unsigned int   PORTCFG9;               // 0x024 R/W Port Configuration Register 9

    volatile unsigned int   PORTCFG10;              // 0x028 R/W Port Configuration Register 10

    volatile unsigned int   PORTCFG11;              // 0x02C R/W Port Configuration Register 11

    volatile unsigned int   PORTCFG12;              // 0x030 R/W Port Configuration Register 12

    volatile unsigned int   PORTCFG13;              // 0x034 R/W Port Configuration Register 13

    volatile unsigned int   NOTDEFINE0;             // 0x038 -

    volatile unsigned int   NOTDEFINE1;             // 0x03C -

    volatile unsigned int   GPADAT;                 // 0x040 R/W 0x00000000 GPA Data Register

    volatile unsigned int   GPAEN;                  // 0x044 R/W 0x00000000 GPA Output Enable Register

    volatile unsigned int   GPASET;                 // 0x048 W - OR function on GPA Output Data

    volatile unsigned int   GPACLR;                 // 0x04C W - BIC function on GPA Output Data

    volatile unsigned int   GPAXOR;                 // 0x050 W - XOR function on GPA Output Data

    volatile unsigned int   NOTDEFINE2;             // 0x054

    volatile unsigned int   NOTDEFINE3;             // 0x058

    volatile unsigned int   NOTDEFINE4;             // 0x05C

    volatile unsigned int   GPBDAT;                 // 0x060 R/W 0x00000000 GPB Data Register

    volatile unsigned int   GPBEN;                  // 0x064 R/W 0x00000000 GPB Output Enable Register

    volatile unsigned int   GPBSET;                 // 0x068 W - OR function on GPB Output Data

    volatile unsigned int   GPBCLR;                 // 0x06C W - BIC function on GPB Output Data

    volatile unsigned int   GPBXOR;                 // 0x070 W - XOR function on GPB Output Data

    volatile unsigned int   NOTDEFINE5;             // 0x074

    volatile unsigned int   NOTDEFINE6;             // 0x078

    volatile unsigned int   NOTDEFINE7;             // 0x07C

    volatile unsigned int   GPCDAT;                 // 0x080 R/W 0x00000000 GPC Data Register

    volatile unsigned int   GPCEN;                  // 0x084 R/W 0x00000000 GPC Output Enable Register

    volatile unsigned int   GPCSET;                 // 0x088 W - OR function on GPC Output Data

    volatile unsigned int   GPCCLR;                 // 0x08C W - BIC function on GPC Output Data

    volatile unsigned int   GPCXOR;                 // 0x090 W - XOR function on GPC Output Data

    volatile unsigned int   NOTDEFINE8;             // 0x094

    volatile unsigned int   NOTDEFINE9;             // 0x098

    volatile unsigned int   NOTDEFINE10;            // 0x09C

    volatile unsigned int   GPDDAT;                 // 0x0A0 R/W 0x00000000 GPD Data Register

    volatile unsigned int   GPDEN;                  // 0x0A4 R/W 0x00000000 GPD Output Enable Register

    volatile unsigned int   GPDSET;                 // 0x0A8 W - OR function on GPD Output Data

    volatile unsigned int   GPDCLR;                 // 0x0AC W - BIC function on GPD Output Data

    volatile unsigned int   GPDXOR;                 // 0x0B0 W - XOR function on GPD Output Data

    volatile unsigned int   NOTDEFINE11;            // 0x0B4

    volatile unsigned int   NOTDEFINE12;            // 0x0B8

    volatile unsigned int   NOTDEFINE13;            // 0x0BC

    volatile unsigned int   GPEDAT;                 // 0x0C0 R/W 0x00000000 GPE Data Register

    volatile unsigned int   GPEEN;                  // 0x0C4 R/W 0x00000000 GPE Output Enable Register

    volatile unsigned int   GPESET;                 // 0x0C8 W - OR function on GPE Output Data

    volatile unsigned int   GPECLR;                 // 0x0CC W - BIC function on GPE Output Data

    volatile unsigned int   GPEXOR;                 // 0x0D0 W - XOR function on GPE Output Data

    volatile unsigned int   NOTDEFINE14[3]; //  0x0D4,0x0D8,0x0DC

    volatile unsigned int   GPFDAT;                 // 0x0E0 R/W 0x00000000 GPF Data Register

    volatile unsigned int   GPFEN;                  //0x0E4 R/W 0x00000000 GPF Output Enable Register

    volatile unsigned int   GPFSET;                 //0x0E8 W - OR function on GPF Output Data

    volatile unsigned int   GPFCLR;                 //0x0EC W - BIC function on GPF Output Data

    volatile unsigned int   GPFXOR;                 //0x0F0 W - XOR function on GPF Output Data

    volatile unsigned int   NOTDEFINE15[3]; //RESERVED 0x0F4 0x0F8 0x0FC

    volatile unsigned int   CPUD0 ;                 //0x100 R/W Pull-Up/Down Control Register 0

    volatile unsigned int   CPUD1;                  // 0x104 R/W Pull-Up/Down Control Register 1

    volatile unsigned int   CPUD2 ;                 //0x108 R/W Pull-Up/Down Control Register 2

    volatile unsigned int   CPUD3 ;                 //0x10C R/W Pull-Up/Down Control Register 3

    volatile unsigned int   CPUD4;                  // 0x110 R/W Pull-Up/Down Control Register 4

    volatile unsigned int   CPUD5;                  // 0x114 R/W Pull-Up/Down Control Register 5

    volatile unsigned int   CPUD6;                  // 0x118 R/W Pull-Up/Down Control Register 6

    volatile unsigned int   CPUD7;                  // 0x11C R/W Pull-Up/Down Control Register 7

    volatile unsigned int   CPUD8;                  // 0x120 R/W Pull-Up/Down Control Register 8

    volatile unsigned int   CPUD9 ;                 //0x124 R/W Pull-Up/Down Control Register 9

    volatile unsigned int   CPDRV0;                 // 0x128 R/W Driver strength Control Register 0

    volatile unsigned int   CPDRV1;                 // 0x12C R/W

    volatile unsigned int   AINCFG;                 // 0x130 R/W 0x00000000 Analog Input Pad Control Register

    volatile unsigned int   EINTSEL0;                   // 0x134 R/W 0x00000000 External Interrupt Select Register 0

    volatile unsigned int   EINTSEL1;                   // 0x138 R/W 0x00000000 External Interrupt Select Register 1

    volatile unsigned int   IRQSEL;                 // 0x13C R/W 0x00000000 Interrupt Select Register

}GPIO, *PGPIO;

 

#define IOCTL_GPIO_SET_PIN   0x0000050

#define IOCTL_GPIO_CLR_PIN   0x0000070

#define IOCTL_GPIO_DIS_PIN   0x0000090

 

//寄存器对应的结构体

static volatile GPIO * v_pIOPregs;

 

static int  g_OpenCount = 0;                      // 驱动打开计数器

 

#define  BASE_ADDRESS               0xF005A000

#define  ADDRESS_INTERVAL_GPIO      0x04

#define  GPx_GPA                0

 

/*******************************************************************************************

函数名称: PIO_InitializeAddresses

    述: 取得相关寄存器的虚拟地址

输入参数: 无

输出参数: 无

    回: > 0 分配到的虚拟地址;  FALSE: 失败

*******************************************************************************************/

static BOOL MyGPIO_InitAddresses(void)

{

    BOOL    RetValue = TRUE;

 

    //  IO Register Allocation

    v_pIOPregs = (volatile GPIO *)VirtualAlloc(0, sizeof(GPIO), MEM_RESERVE, PAGE_NOACCESS);

    if (v_pIOPregs == NULL)

    {

        RETAILMSG(1,(TEXT("For IOPregs : VirtualAlloc failed!/r/n")));

        RetValue = FALSE;

    }

    else

    {

        if (!VirtualCopy((PVOID)v_pIOPregs, (PVOID)(BASE_ADDRESS >> 8), sizeof(GPIO), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))

        {

            RETAILMSG(1,(TEXT("For IOPregs: VirtualCopy failed!/r/n")));

            RetValue = FALSE;

        }

    }

   

    if (!RetValue)

    {

        RETAILMSG (1, (TEXT("::: PIO_InitializeAddresses - Fail!!/r/n") ));

 

        if (v_pIOPregs)

        {

            VirtualFree((PVOID) v_pIOPregs, 0, MEM_RELEASE);

        }

 

        v_pIOPregs = NULL;

 

        RetValue = FALSE;

        return RetValue;

    }

 

    RETAILMSG(1,(TEXT("For IOPregs : VirtualAlloc SUCCESS!/r/n")));

 

    //配置寄存器选中GPIOE8

//  v_pIOPregs->PORTCFG10 &= ~(0x0f << 12);

//  v_pIOPregs->PORTCFG10 |= (0x01 << 12);

 

    //配置寄存器为输出模式

//  v_pIOPregs->GPEEN |= (0x01 << 8);

 

    return(RetValue);

}

 

 

/*******************************************************************************************

函数名称: PIO_Init

    述: 驱动程序初始化函数

输入参数: DWORD dwContext: 设备管理器传递给本驱动的参数, 通常为流接口驱动在注册表内的位置   

输出参数: 无

    回: 驱动程序句柄

*******************************************************************************************/

DWORD PIO_Init(DWORD dwContext)

{

    MyGPIO_InitAddresses();

    g_OpenCount = 0;

    RETAILMSG(1, (TEXT("PIO_Init!/r/n")));

    return (DWORD)1;

}

 

 

 

/*******************************************************************************************

函数名称: DllEntry

    述: 驱动程序动态库入口

输入参数:   

输出参数:

    回:

*******************************************************************************************/

BOOL DllEntry(HINSTANCE hinst_dll, DWORD reason, LPVOID reserved)

{

    switch (reason) {

    case DLL_PROCESS_ATTACH:

        RETAILMSG(1, (TEXT("[GPIO] Process Attach/r/n")));

        break;

    case DLL_PROCESS_DETACH:

        RETAILMSG(1, (TEXT("[GPIO] Process Detach/r/n")));

        break;

    }

   

    return TRUE;

}

 

/*******************************************************************************************

函数名称: PIO_Close

    述: 驱动程序关闭函数

输入参数: DWORD Handle:驱动程序引用事例句柄

输出参数: 无

    回: FALSE: 失败    TRUE: 成功

*******************************************************************************************/

BOOL PIO_Close(DWORD Handle)

{

    g_OpenCount = 0;

 

    return TRUE;

}

 

 

/*******************************************************************************************

函数名称: PIO_Deinit

    述: 驱动程序卸载函数

输入参数: DWORD dwContext: 驱动程序句柄

输出参数: 无

    回: FALSE: 失败    TRUE: 成功

*******************************************************************************************/

BOOL PIO_Deinit(DWORD dwContext)

{

    g_OpenCount = 0;

 

    if (v_pIOPregs)

        VirtualFree((PVOID) v_pIOPregs, 0, MEM_RELEASE);    /* 释放申请的虚拟空间 */

 

    return TRUE;

}

 

 

/*******************************************************************************************

函数名称: PIO_Open

    述: 打开驱动程序

输入参数: DWORD dwData     : 设备驱动程序句柄

          DWORD dwAccess   : 访问请求代码,是读和写的组合

          DWORD dwShareMode: 共享模式 

输出参数:

    回: 驱动程序引用事例句柄

*******************************************************************************************/

DWORD PIO_Open(DWORD dwData, DWORD dwAccess, DWORD dwShareMode)

{

    if (g_OpenCount > 0)

        return 0;

 

    g_OpenCount++;

 

    return g_OpenCount;                          /* 返回一个不为零的数 */

}

 

/*******************************************************************************************

函数名称: GPIO_SetPin

    述: 设置某个引脚输出高电平

输入参数: DWORD dwIoControlCode : I/O control code, 指出操作的GPIO组, 如GPA, GPB

          BYTE PinNum        : 引脚编号, 如 GPB1, 则值为 1

输出参数:

    回: TRUE: 操作成功    FALSE: 操作失败

*******************************************************************************************/

BOOL GPIO_SetPin(DWORD dwIoControlCode, BYTE PinNum)

{

 

   

    //配置寄存器选中GPIOE8

    v_pIOPregs->PORTCFG10 &= ~(0x0f << 12);

    v_pIOPregs->PORTCFG10 |= (0x01 << 12);

 

    //配置寄存器为输出模式

    v_pIOPregs->GPEEN |= (0x01 << 8);

 

    //设置数据寄存器为1

    v_pIOPregs->GPESET |=  (0x01 << 8);

 

    //使能上拉

//  v_pIOPregs->CPUD7 &= ~(0x03 << 30);

//  v_pIOPregs->CPUD7 |= (0x01 << 30);

    return TRUE;

}

 

/*******************************************************************************************

函数名称: GPIO_ClrPin

    述: 设置某个引脚输出低电平

输入参数: DWORD dwIoControlCode : I/O control code, 指出操作的GPIO组, 如GPA, GPB

          BYTE PinNum        : 引脚编号, 如 GPB1, 则值为 1

输出参数:

    回: TRUE: 操作成功    FALSE: 操作失败

*******************************************************************************************/

BOOL GPIO_ClrPin(DWORD dwIoControlCode, BYTE PinNum)

{

 

   

    //配置寄存器选中GPIOE8

    v_pIOPregs->PORTCFG10 &= ~(0x0f << 12);

    v_pIOPregs->PORTCFG10 |= (0x01 << 12);

 

    //配置寄存器为输出模式

    v_pIOPregs->GPEEN |= (0x01 << 8);

 

    //设置数据寄存器为0

    v_pIOPregs->GPECLR |=  (0x01 << 8);

 

    //禁止上拉

//  v_pIOPregs->CPUD7 &= ~(0x03 << 30);

//  v_pIOPregs->CPUD7 |= (0x02 << 30);

    return TRUE;

}

 

/*******************************************************************************************

函数名称: GPIO_Display

    述: 设置某个引脚输出低电平

输入参数: DWORD dwIoControlCode : I/O control code, 指出操作的GPIO组, 如GPA, GPB

          BYTE PinNum        : 引脚编号, 如 GPB1, 则值为 1

输出参数:

    回: TRUE: 操作成功    FALSE: 操作失败

*******************************************************************************************/

BOOL GPIO_Display(DWORD dwIoControlCode, BYTE PinNum)

{

   RETAILMSG(1,(TEXT("GPIO_Display/r/n")));

  

  // Sleep 函数   睡眠  让出权限其他驱动有可能改变寄存器的值

  for (int i = 0; i < 100; i++)

  {

     GPIO_ClrPin(dwIoControlCode, NULL);

     Sleep(1000);

     GPIO_SetPin(dwIoControlCode, NULL);

     Sleep(1000);

  }

 

   return TRUE;

}

 

/*******************************************************************************************

函数名称: PIO_IOControl

    述: 驱动程序 I/O 请求

输入参数: DWORD dwIoControlCode:  见本文件的头文件

输出参数:

   回: TRUE: 操作成功    FALSE: 操作失败

*******************************************************************************************/

BOOL

PIO_IOControl(

    DWORD Handle,

    DWORD dwIoControlCode,

    PBYTE pInBuf,

    DWORD nInBufSize,

    PBYTE pOutBuf,

    DWORD nOutBufSize,

    PDWORD pBytesReturned

    )

{

    BOOL bErr = FALSE; 

 

    switch(dwIoControlCode)

    {  

        case IOCTL_GPIO_SET_PIN:   

            GPIO_SetPin(dwIoControlCode, *pInBuf);

 

            RETAILMSG(1,(TEXT("PORTCFG10:,0x%x/r/n"), v_pIOPregs->PORTCFG10));

            RETAILMSG(1,(TEXT("CPUD7:,0x%x/r/n"), v_pIOPregs->CPUD7));

            RETAILMSG(1,(TEXT("GPEEN:,0x%x/r/n"), v_pIOPregs->GPEEN));

            RETAILMSG(1,(TEXT("IOCTL_GPIO_SET_PIN,0x%x/r/n"),v_pIOPregs->GPEDAT));

            break;

 

        case IOCTL_GPIO_CLR_PIN:           

            GPIO_ClrPin(dwIoControlCode, *pInBuf);

 

            RETAILMSG(1,(TEXT("PORTCFG10:,0x%x/r/n"), v_pIOPregs->PORTCFG10));

            RETAILMSG(1,(TEXT("CPUD7:,0x%x/r/n"), v_pIOPregs->CPUD7));

            RETAILMSG(1,(TEXT("GPEEN:,0x%x/r/n"), v_pIOPregs->GPEEN));

            RETAILMSG(1,(TEXT("IOCTL_GPIO_CLR_PIN,0x%x/r/n"), v_pIOPregs->GPEDAT));

            break;

           

        case IOCTL_GPIO_DIS_PIN:

            RETAILMSG(1,(TEXT("GPIO_Display/r/n")));

            GPIO_Display(0, NULL);

            break;

    }

 

    return true;

} 

这次写这个驱动遇到的问题:

1.初始化端口放在了PIO_INIT函数里面,在驱动加载过程中就初始化了端口!这样有可能其他驱动访问相同的端口,导致在PIO_SETPIN 和 PIO_CLRPIN函数中,PORTCFG和GPEEN寄存器的值已经被改回(今天查找一天的Bug就是这个原因)。这样得不到正确的输出波形。

2.GPIO端口默认的是输入模式,是内部拉高的!只有在输出模式下才能改变GPEDAT寄存器的值(我操作的是GPIOE8端口)。

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值