分类: LINUX
2010-09-16 20:49:59
函数原型:
3c2410_gpio_cfgpin(unsigned int pin, unsigned int function);
unsigned int s3c2410_gpio_getcfg(unsigned int pin);
3c2410_gpio_pullup(unsigned int pin, unsigned int to);
3c2410_gpio_setpin(unsigned int pin, unsigned int to);
unsigned int s3c2410_gpio_getpin(unsigned int pin);
3c2410_modify_misccr(unsigned int clear, unsigned int change);
3c2410_gpio_getirq(unsigned int pin);
关于函数中用到的虚拟地址到物理地址转换的变量及算法可以参考
http://blog.163.com/hefeng330467115@126/blog/static/782058422010620511659/
或http://blog.chinaunix.net/u3/102836/showart_2065945.html
看简单led驱动程序是用到的文件及头文件可能有:
linux/include/asm-arm/arch-s3c2410/map.h
linux/include/asm-arm/arch-s3c2410/regs-gpio.h
linux/arch/arm/plat-s3c24xx/gpio.c
linux/include/asm-arm/io.h
用Source Insight 打开这些文件,然后再看驱动程序,可以随意跳转到定义处,很是方便
pin参数:
gpio引脚及特殊功能寄存器助记符都在3c2410/regs-gpio.h中定义:
eg:
S3C2410_GPACON
S3C2410_GPADAT
3C2410_GPA0 - S3C2410_GPA22 //引脚
S3C2410_GPA0_OUT - 3C2410_GPA22_OUT //设置引脚为输出
用到哪个不清楚的可以直接到这个文件去查找
还有中断和GSTATUS:
S3C2410_EXTINT0 -> irq sense control for EINT0..EINT7
S3C2410_EXTINT1 -> irq sense control for EINT8..EINT15
S3C2410_EXTINT2 -> irq sense control for EINT16..EINT23
……
function参数:
指定引脚功能:输出、输入还是特殊功能,也在linux/include/asm-arm/arch-s3c2410/regs-gpio.h中定义。
函数功能:
原型:void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function);
作用:配置GPIO引脚功能,即是配置相应的CON位
:
s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_OUTP);//设置B5脚为输出功能
(这个函数注释的比较详细,后面类似的不再重复注释)
void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
{
void __iomem *base = S3C24XX_GPIO_BASE(pin);
//取引脚基地址即是:GPA0、GPB0 …… 的虚拟基地址
unsigned long mask;
unsigned long con;
unsigned long flags;
if (pin < S3C2410_GPIO_BANKB) {
mask = 1 << S3C2410_GPIO_OFFSET(pin);
用于查找对应的引脚位(端口A一位控制一个引脚)
} else {
mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
//除端口A外其他端口都是两位控制一个引脚
}
//根据function值具体确定怎么来调整function
switch (function) {
case S3C2410_GPIO_LEAVE:
mask = 0;
function = 0;
break;
case S3C2410_GPIO_INPUT:
case S3C2410_GPIO_OUTPUT:
case S3C2410_GPIO_SFN2:
case S3C2410_GPIO_SFN3:
if (pin < S3C2410_GPIO_BANKB)
{ // 当某位被设为0时,相应引脚为输出,此时可
function -= 1; //以在GPADAT中相应位写入1或0;当某位被
function &= 1; //设为1时,相应引脚为地址线或用于地址控制。
function <<= S3C2410_GPIO_OFFSET(pin); //偏移量即是相应的引脚位
} else {
function &= 3;
function <<= S3C2410_GPIO_OFFSET(pin)*2; //除A端口以外的其他端口都是
} //两位控制一个引脚
}
/* modify the specified register wwith IRQs off */
(flags); //调用该宏函数来保存IRQ 中断使能状态,并禁止IRQ 中断
con = __raw_readl(base + 0x00);
// 基地址加偏移量得到相应端口的控制寄存器(GPxCON)地址,然后读取该寄存器的值
con &= ~mask; // 找到需要修改的引脚的控制位
con |= function; // 使对应的引脚的功能为function
__raw_writel(con, base + 0x00); // 重写控制寄存器的值,实现引脚功能修改
local_irq_restore(flags); //恢复IRQ 和FIQ 的中断使能状态
}
原型:3c2410_gpio_getcfg(unsigned int pin);
作用:该函数根据引脚获得指定引脚配置的功能值
eg:
s3c2410_gpio_getcfg (S3C2410_GPB5);//读取B5脚为的配置功能 输入00、输出01、特殊功能02 ……
unsigned int s3c2410_gpio_getcfg(unsigned int pin)
{
void __iomem *base = S3C24XX_GPIO_BASE(pin);
unsigned long val = __raw_readl(base);
if (pin < S3C2410_GPIO_BANKB) { //此判断操作主要是针对A端口,原因前面已解释
val >>= S3C2410_GPIO_OFFSET(pin);
val &= 1;
val += 1;
} else {
val >>= S3C2410_GPIO_OFFSET(pin)*2;
val &= 3;
}
return val | S3C2410_GPIO_INPUT;
}
3 原型:void 3c2410_gpio_pullup(unsigned int pin, unsigned int to);
作用:设置相应GPIO口的上拉电阻
eg
s3c2410_gpio_pullup(S3C2410_GPB5,0)//3C2410_GPB5不要上拉电阻
s3c2410_gpio_pullup(S3C2410_GPB5,1)//设置S3C2410_GPB5要上拉电阻
void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
{
void __iomem *base = S3C24XX_GPIO_BASE(pin);
unsigned long offs = S3C2410_GPIO_OFFSET(pin);
unsigned long flags;
unsigned long up;
if (pin < S3C2410_GPIO_BANKB)
return;
local_irq_save(flags);
up = __raw_readl(base + 0x08); // //0x08是GPxUP寄存器的物理偏移量
up &= ~(1L << offs); //1L是什么东西,暂时没看明白,可能是错误,感觉应该是1
up |= to << offs;
__raw_writel(up, base + 0x08);
local_irq_restore(flags);
}
4原型:void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
作用:该函数给指定的引脚位写入0或1,即是配置相应的DAT位。
eg
s3c2410_gpio_setpin (S3C2410_GPB5 ,0);//设置S3C2410_GPB5的输出值为0
s3c2410_gpio_setpin (S3C2410_GPB5 ,1);//设置S3C2410_GPB5的输出值为1
void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
{
void __iomem *base = S3C24XX_GPIO_BASE(pin);
unsigned long offs = S3C2410_GPIO_OFFSET(pin);
unsigned long flags;
unsigned long dat;
local_irq_save(flags);
dat = __raw_readl(base + 0x04); 是GPxDAT寄存器的物理偏移量
dat &= ~(1 << offs);
dat |= to << offs;
__raw_writel(dat, base + 0x04);
local_irq_restore(flags);
}
5原型:void s3c2410_gpio_getpin(unsigned int pin);
作用:该函数读取指定引脚的状态 返回0或 1,即是读取相应的DAT位。
s3c2410_gpio_setpin (3C2410_GPB5 );// 读取S3C2410_GPB5位的状态。
函数原代码及注释:
unsigned int s3c2410_gpio_getpin(unsigned int pin)
{
void __iomem *base = S3C24XX_GPIO_BASE(pin);
unsigned long offs = S3C2410_GPIO_OFFSET(pin);
return __raw_readl(base + 0x04) & (1<< offs);
}
原型:unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change);
作用: 主要是设置混杂控制寄存器(Miscellaneous control :物理地址0x56000080), 此寄存器控制数据口上拉寄存器,hi-z 状态,USB块和CLKOUT选择
7原型:int s3c2410_gpio_(unsigned int pin);
作用: 读取中断引脚的状态 GPF0-GPF7、GPG0-GPG7
eg
3c2410_gpio_ getirq (S3C2410_GPF0 );// 读取S3C2410_GPF0位的状态,看是否产生EINT8中断。
chinaunix网友2010-09-17 16:07:09
很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com