详解内核驱动操作GPIO引脚API函数【转载】

函数原型:

void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function);

unsigned int s3c2410_gpio_getcfg(unsigned int pin);

void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);

void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);

unsigned int s3c2410_gpio_getpin(unsigned int pin);

unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change);

int s3c2410_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-s3c2410/regs-gpio.h中定义:

eg:

S3C2410_GPACON       

S3C2410_GPADAT

S3C2410_GPA0 - S3C2410_GPA22             //引脚

S3C2410_GPA0_OUT - S3C2410_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 s3c2410_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 s3c2410_gpio_pullup(unsigned int pin, unsigned int to);

作用:设置相应GPIO口的上拉电阻

eg 

s3c2410_gpio_pullup(S3C2410_GPB5,0)//设置S3C2410_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 (S3C2410_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

s3c2410_gpio_ getirq (S3C2410_GPF0 );// 读取S3C2410_GPF0位的状态,看是否产生EINT8中断。

作者: huazaicola   发布时间: 2010-09-16