AU1200 GPIO的使用

本文详细介绍了AU1200处理器中GPIO(通用输入输出)的使用方法,包括GPIO1和GPIO2的寄存器配置、通过流驱动及dll调用方式控制GPIO等。适合于希望深入了解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是流驱动,所以我们可以用通用的方法来进行读写。

intWINAPIWinMain(HINSTANCEhInstance,
HINSTANCEhPrevInstance,
LPTSTRlpCmdLine,
intnCmdShow)
{

//该类型数值的定义可以在GPIO.C文件中找到。
enum{
IOCTL_GPIO_READSTATE
=0x80001000,//somearbirarybase
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,在DBAU1200Boar中的序号为1.该设置可参考Gpio.reg文件
HANDLEhd=CreateFile(TEXT("PIO1:"),GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,0);
if(hd==INVALID_HANDLE_VALUE)
{
return0x01;
}

ULONGulTmp;
ULONGulCmd;

//设置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);

return0;
}

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

方法二:直接调用gpio.dll

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

intWINAPIWinMain(HINSTANCEhInstance,
HINSTANCEhPrevInstance,
LPTSTRlpCmdLine,
intnCmdShow)
{
//TODO:Placecodehere.

//Initializethefunction


typedefHANDLE(WINAPI
*GPIO_INIT)(void);
GPIO_INITGPIO_Init;

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

typedefBOOL(WINAPI
*GPIO_SETPINFUNCTION)(HANDLE,ULONG);
GPIO_SETPINFUNCTIONGPIO_SetPinFunction;

typedefBOOL(WINAPI
*GPIO_CLEARPINFUNCTION)(HANDLE,ULONG);
GPIO_CLEARPINFUNCTIONGPIO_ClearPinFunction;

HINSTANCEhInstDll
=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(
"ThefunctionisNULL!"),TEXT(""),MB_OK);
}
}
else
{
MessageBox(NULL,TEXT(
"TheinstanceoftheDllisNULL!"),TEXT(""),MB_OK);
return0x03;
}

HANDLEhGPIO
=GPIO_Init();
if(!hGPIO)
{
MessageBox(NULL,TEXT(
"FailedinGPIOinit!"),TEXT(""),MB_OK);

return0x04;
}

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);

return0;
}


采用方法二有如下函数可以使用:

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
);

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值