详解内核驱动操作GPIO引脚API函数

详解内核驱动操作GPIO引脚API函数

函数原型:
void s 3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
unsigned int s3c2410_gpio_getcfg(unsigned int pin)
void s 3c2410_gpio_pullup(unsigned int pin, unsigned int to)
void s 3c2410_gpio_setpin(unsigned int pin, unsigned int to)
unsigned int s3c2410_gpio_getpin(unsigned int pin)
unsigned int s 3c2410_modify_misccr(unsigned int clear, unsigned int change)
int s 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 引脚 及特殊功能寄存器助记符都在 linux/include/asm-arm/arch-s 3c2410/regs-gpio.h 中定义:
eg:
S3C2410_GPACON 
S3C2410_GPADAT
S 3C2410_GPA0 - S3C2410_GPA22 // 引脚
S3C2410_GPA0_OUT -  S 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 中定义。
函数功能:
1  原型: void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
作用:配置 GPIO 引脚 功能,即是配置相应的 CON
eg  
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 */
local_irq_save (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 的中断使能状态
}

2  原型: unsigned int s 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;
}

原型: void  s 3c2410_gpio_pullup(unsigned int pin, unsigned int to)
作用 : 设置相应 GPIO 口的上拉电阻
eg 
s3c2410_gpio_pullup S3C2410_GPB5 0 // 设置 S 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);  //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 位。
eg
s3c2410_gpio_setpin ( S 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);
}
6 原型: unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
作用:   主要是设置混杂控制寄存器( Miscellaneous control  :物理地址 0x56000080 ),   此寄存器控制数据口上拉寄存器, hi-z  状态, USB 块和 CLKOUT 选择
7 原型: int s3c2410_gpio_ getirq (unsigned int pin)
作用:   读取中断 引脚 的状态   GPF0-GPF7、GPG0-GPG7
eg
s 3c2410_gpio_ getirq (S3C2410_GPF0 ) //  读取 S3C2410 _ GPF0 位的状态 , 看是否产生 EINT8 中断。

你可能感兴趣的:(一步一步学驱动)