AU1200 GPIO的使用

//========================================================================
//TITLE:
//    AU1200 GPIO的使用
//AUTHOR:
//    norains
//DATE:
//    Saturday  10-May-2008
//Environment:
//    VS2005 + MIPS-SDK + DBAU1200 BOARD
//========================================================================
    如果说一款CPU的精髓在于GPIO PIN,其实一点也不为过。一个工程师能否熟练操控CPU的GPIO,几乎决定了一个产品的成败。有太多的芯片,和CPU打交道的唯一方式就是GPIO。
   
    所幸的是,DBAU1200的SDK中包含了完整的GPIO驱动。相对于其它半吊子的驱动来说,不能不让我们略感欣慰。
   
    如果安装了DBAU1200 SDK Packet,那么GPIO驱动将位于:$WINCEROOT$/PLATFORM/Db1200/Drivers/Gpio。
   
    AU1200的GPIO分为两块,分别是Primary GENERAL PURPOSE I/O和Secondary GENERAL PURPOSE I/O。
   
    Secondary GENERAL PURPOSE I/O(以下简称GPIO2)的使用比较简单,无非就是设置PIN的方向(Input/Output),读取PIN的数值(1/0),用来控制那些外围芯片的EN PIN是个非常合适的选择;而Primary GENERAL PURPOSE I/O(以下简称GPIO1)就比较复杂,它是一个多功能复用PIN,具体的功能需要设置相关的寄存器。
   
   
    首先我们先看看最简单的GPIO2。
   
    GPIO2的具体介绍可以参考RMI的AU1200文档Secondary GENERAL PURPOSE I/O一节,在这里只是挑一些重点来说明。
   
    GPIO2一共有16个PIN,它的Physical Base Address为0x0 1170 0000,KSEG1 Base Address为0xB170 0000。
   
    与GPIO2的Control Register有六个,除了一个是保留的以外,真正有作用的是五个。   
   
     Offset (Note1)   Register Name           Description
       0x0000          gpio2_dir           Direction Register       
       0x0004          —                   Reserved       
       0x0008          gpio2_output        Data Output Register       
       0x000C          gpio2_pinstate      Pin State Register       
       0x0010          gpio2_inten         Interrupt Enable Register       
       0x0014          gpio2_enable        Enable Register
   
    因为涉及到寄存器的设置,所以在使用中比较简单。假如我们需要将GPIO2_0的方向设置为ouput,则代码可以如此:
   
    #define KSEG1_GPIO_BASE  0xB1700000
    #define GPIO_OFFSET  0x0000
    *((volatile unsigned long *)(KSEG1_GPIO_BASE + GPIO_OFFSET)) = 0x0001
   
   
    相对GPIO2来说,因为GPIO1是复用多功能pin,在使用中会比GPIO2要略显麻烦。
   
    GPIO1有27个PIN,每个PIN基本上都具有两个功能,而这些功能的选择是通过写入sys_pinfunc寄存器来实现的。sys_pinfunc的地址是相对于sys_base偏移0x002C,而sys_base的Physical Base Address为0x0 1190 0000,KSEG1 Base Address为0xB190 0000。

    因为篇幅关系,在这里就不将每个PIN的复用功能列出来,有兴趣的朋友可以参考RMI关于AU1200文档的Primary General Purpose I/O and Pin Functionality一节。
   
    GPIO的Control Register有七个,分别罗列如下:
   
    Offset     Register Name      Register Description 
    0x0100     sys_trioutrd       Displays the tristate/output state of GPIO[n].             
    0x0100     sys_trioutclr      Set sys_trioutclr[n] to clear and tristate the corre-
                                  sponding bit. All input pins must be tristated.  
    0x0108     sys_outputrd       Displays the output state of GPIO[n].   
    0x0108     sys_outputset      Set sys_outputset[n] to enable a high level output.   
    0x010C     sys_outputclr      Set sys_outputclr[n] to enable a low level output.
                                  Setting an output pin brings the pin out of tristate
                                  mode and enables the output.   
    0x0110     sys_pinstaterd     Displays the state of the pins.  
    0x0110     sys_pininputen     Writing to this register allows the system to use     
                                 GPIO[7:0] as external inputs to wake the processor
                                 from Sleep. This register must be written before any
                                 GPIO[7:0] signal can be used as a Sleep wakeup
                                          input source.
  
    对该Register的读写,可以参照GPIO2寄存器的读写方法。 
   
   
   
    如果在应用程序中操作GPIO,则可以很简单地通过GPIO驱动来实现。
   
    调用GPIO驱动方法大体上有两种,现在分别以这两种方法关闭SD CARD PIN功能。因为SD CARD PIN主要存在于GPIO1,所以下面的代码都是对GPIO1进行的。
   
   
    方法一:流驱动方式 

    
    因为GPIO是流驱动,所以我们可以用通用的方法来进行读写。

    int WINAPI WinMain(    HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    LPTSTR    lpCmdLine,
                    
int       nCmdShow)
{

    
//该类型数值的定义可以在GPIO.C文件中找到。
    enum {
         IOCTL_GPIO_READSTATE 
= 0x80001000,  // some arbirary base
         IOCTL_GPIO_OUTPUTSTATESET,      // 1
         IOCTL_GPIO_OUTPUTSTATECLEAR,    // 2
         IOCTL_GPIO_SETASOUTPUT,         // 3
         IOCTL_GPIO_SETASINPUT,          // 4
         IOCTL_GPIO_READTRISTATE,        // 5
         IOCTL_GPIO_SETPINFUNC,          // 6
         IOCTL_GPIO_CLEARPINFUNC,        // 7
         IOCTL_GPIO_GETPINFUNC,          // 8
         IOCTL_GPIO_SETFREQCONTROL0,     // 9 
         IOCTL_GPIO_SETFREQCONTROL1,     // a
         IOCTL_GPIO_SETCLOCKSOURCE,      // b
         IOCTL_GPIO2_SETDIRECTION,
         IOCTL_GPIO2_GETDIRECTION,
         IOCTL_GPIO2_GETDATAOUTPUT,
         IOCTL_GPIO2_SETDATAOUTPUT,
         IOCTL_GPIO2_GETPINSTATE
         };
    
  
//打开设备驱动。GPIO的设备驱动为PIO,在DBAU1200 Boar中的序号为1.该设置可参考Gpio.reg文件
  HANDLE hd = CreateFile(TEXT("PIO1:"),GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,0);
    
if(hd == INVALID_HANDLE_VALUE )
    {        
        
return 0x01;
    }

    ULONG ulTmp;
    ULONG ulCmd;

  
//设置GPIO1的PIN功能。
    ulCmd = SYS_PINFUNC_S0C;
    DeviceIoControl(
        hd,
        IOCTL_GPIO_SETPINFUNC,
        
&ulCmd,
        
sizeof(ulCmd),
        NULL,
        
0,
        
&ulTmp,
        NULL);


  
//清除GPIO1的PIN功能
    ulCmd = SYS_PINFUNC_S0A|SYS_PINFUNC_S0B;
    DeviceIoControl(
        hd,
        IOCTL_GPIO_CLEARPINFUNC,
        
&ulCmd,
        
sizeof(ulCmd),
        NULL,
        
0,
        
&ulTmp,
        NULL);


  
//关闭设备。
    CloseHandle(hd);

    
return 0;
    }

    采用该方法,对设备进行读写的唯一通道就是DeviceIoControl函数,通过设置参数2,可以实现不同的功能。
   

    方法二:直接调用gpio.dll
   
    这种方法比较暴力,也比较直接,但所起到的作用和方法一是一致的。

int WINAPI WinMain(    HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    LPTSTR    lpCmdLine,
                    
int       nCmdShow)
{
     
// TODO: Place code here.

    
//Initialize the function

    
    typedef HANDLE (WINAPI 
*GPIO_INIT)(void);
    GPIO_INIT GPIO_Init;

    typedef 
void (WINAPI *GPIO_ClOSE)(HANDLE);
    GPIO_ClOSE GPIO_Close;

    typedef BOOL (WINAPI 
*GPIO_SETPINFUNCTION)(HANDLE,ULONG);
    GPIO_SETPINFUNCTION GPIO_SetPinFunction;

    typedef BOOL (WINAPI 
*GPIO_CLEARPINFUNCTION)(HANDLE,ULONG);
    GPIO_CLEARPINFUNCTION GPIO_ClearPinFunction;

    HINSTANCE hInstDll 
= LoadLibrary(TEXT("GPIO.dll"));
    
if(hInstDll != NULL)
    {

    GPIO_Init 
= (GPIO_INIT) GetProcAddress(hInstDll,TEXT("GPIO_Init"));   
        GPIO_Close 
= (GPIO_ClOSE) GetProcAddress(hInstDll,TEXT("GPIO_Close"));
        GPIO_SetPinFunction 
= (GPIO_SETPINFUNCTION) GetProcAddress(hInstDll,TEXT("GPIO_SetPinFunction"));
        GPIO_ClearPinFunction 
= (GPIO_CLEARPINFUNCTION) GetProcAddress(hInstDll,TEXT("GPIO_ClearPinFunction"));

        
if(!GPIO_Init || !GPIO_Close || !GPIO_SetPinFunction || !GPIO_ClearPinFunction)
        {
            MessageBox(NULL,TEXT(
"The function is NULL!"),TEXT(""),MB_OK);
        }
    }
    
else
    {
        MessageBox(NULL,TEXT(
"The instance of the Dll is NULL!"),TEXT(""),MB_OK);
        
return 0x03;
    }

    HANDLE hGPIO 
= GPIO_Init();
    
if(!hGPIO)
    {
        MessageBox(NULL,TEXT(
"Failed in GPIO init!"),TEXT(""),MB_OK);

        
return 0x04;
    }

    GPIO_SetPinFunction(hGPIO,SYS_PINFUNC_S0C);
    GPIO_ClearPinFunction(hGPIO,SYS_PINFUNC_S0A
|SYS_PINFUNC_S0B);
    

    GPIO_Close(hGPIO);


    
//释放资源
    FreeLibrary(hInstDll);

    MessageBox(NULL,TEXT(
"Succeed !"),TEXT(""),MB_OK);

    
return 0;
    }


 采用方法二有如下函数可以使用:
 
    PIO_Init
    PIO_Deinit
    PIO_Open
    PIO_Close
    PIO_Read
    PIO_Write
    PIO_Seek
    PIO_IOControl
    PIO_PowerDown
    PIO_PowerUp
    GPIO_SetPinOutputState
    GPIO_ClearPinOutputState
    GPIO_GetState
    GPIO_SetAsOutput
    GPIO_SetAsInput
    GPIO_GetTristate
    GPIO_ClearPinFunction
    GPIO_SetPinFunction
    GPIO_GetPinFunction
    GPIO_SetClockSourceControl
    GPIO_SetFrequencyControl0
    GPIO_SetFrequencyControl1
    GPIO_Init
    GPIO2_SetDirection
    GPIO2_GetDirection
    GPIO2_SetDataOutput
    GPIO2_GetDatatOutput
    GPIO2_GetPinState
    GPIO_Close
 
    因为GPIO1的每个PIN的功能都不相同,设置sys_pinfunc寄存器其实已经包含设置相对应PIN的意味。在au1x00.h文件中已经将这些功能用宏定义给出:
       
    #define SYS_PINFUNC_DMA  (1<<31)
    #define SYS_PINFUNC_S0A  (1<<30)
    #define SYS_PINFUNC_S1A  (1<<29)
    #define SYS_PINFUNC_LP0  (1<<28)
    #define SYS_PINFUNC_LP1  (1<<27)
    #define SYS_PINFUNC_LD16 (1<<26)
    #define SYS_PINFUNC_LD8  (1<<25)
    #define SYS_PINFUNC_LD1  (1<<24)
    #define SYS_PINFUNC_LD0  (1<<23)
    #define SYS_PINFUNC_P1A  (3<<21)
    #define SYS_PINFUNC_P1B  (1<<20)
    #define SYS_PINFUNC_FS3  (1<<19)
    #define SYS_PINFUNC_P0A  (3<<17)
    #define SYS_PINFUNC_CS  (1<<16)
    #define SYS_PINFUNC_CIM  (1<<15)
    #define SYS_PINFUNC_P1C  (1<<14)
    #define SYS_PINFUNC_U1T  (1<<12)
    #define SYS_PINFUNC_U1R  (1<<11)
    #define SYS_PINFUNC_EX1  (1<<10)
    #define SYS_PINFUNC_EX0  (1<<9)
    #define SYS_PINFUNC_U0R  (1<<8)
    #define SYS_PINFUNC_MC  (1<<7)
    #define SYS_PINFUNC_S0B  (1<<6)
    #define SYS_PINFUNC_S0C  (1<<5)
    #define SYS_PINFUNC_P0B  (1<<4)
    #define SYS_PINFUNC_U0T  (1<<3)
    #define SYS_PINFUNC_S1B  (1<<2)
   
   
    和GPIO1不同,每个GPIO2的功能都是相同或类似的,因此如果具体到设置每个PIN,则需要明确指出该PIN的序号:
   
    GPIO2_SetDataOutput(hd,0x0001); //设置GPIO2_0输出为1
   
   
    之前的代码都是在应用程序中调用,如果需要在驱动中使用则更方便,只需要在驱动中包含gpio.h文件即可。在该文件中,声明了如下函数原型:

    extern HANDLE
    GPIO_Init(
        VOID);
   
    extern VOID
    GPIO_Close(
        HANDLE);
   
    extern BOOL
    GPIO_GetPinFunction(
        HANDLE Handle,
        PULONG PinFunc);
   
    extern BOOL
    GPIO_ClearPinFunction(
        HANDLE Handle,
        ULONG PinStates);
   
    extern BOOL
    GPIO_SetPinFunction(
        HANDLE Handle,
        ULONG PinFunc);
   
    extern BOOL
    GPIO_GetTristate(
        HANDLE Handle,
        PULONG PinTristates);
   
    extern BOOL
    GPIO_SetAsOutput(
        HANDLE Handle,
        ULONG PinsToSet);
   
    extern BOOL
    GPIO_SetAsInput(
        HANDLE Handle,
        ULONG PinsToSet);
   
    extern BOOL
    GPIO_ClearPinOutputState(
        HANDLE Handle,
        ULONG PinsToClear);
   
    extern BOOL
    GPIO_SetPinOutputState(
        HANDLE Handle,
        ULONG PinsToSet);
   
    extern BOOL
    GPIO_GetState(
        HANDLE Handle,
        PULONG PinStates);
   
    extern BOOL
    GPIO_SetClockSourceControl(
        HANDLE Handle,
        ULONG   AndMask,
        ULONG   OrMask);
   
    extern BOOL
    GPIO_SetFrequencyControl1(
        HANDLE Handle,
        ULONG   AndMask,
        ULONG   OrMask);
    extern BOOL
    GPIO_SetFrequencyControl0(
        HANDLE Handle,
        ULONG   AndMask,
        ULONG   OrMask);
   
   
    extern BOOL
    GPIO2_GetPinState(
        HANDLE Handle,
        PULONG PinState
     );
   
    extern BOOL
    GPIO2_GetDirection(
        HANDLE Handle,
        PULONG Direction
     );
   
    extern BOOL
    GPIO2_SetDirection(
        HANDLE Handle,
        ULONG   AndMask,
        ULONG   OrMask
    );
   
    extern BOOL
    GPIO2_GetDatatOutput(
        HANDLE Handle,
        PULONG DataOutput
    );
   
   
    extern BOOL
    GPIO2_SetDataOutput(
        HANDLE Handle,
        ULONG  State
    );

posted @ 2008-05-10 23:56  我的一天  阅读(298)  评论(0编辑  收藏  举报