Chinaunix首页 | 论坛 | 博客
  • 博客访问: 380773
  • 博文数量: 149
  • 博客积分: 25
  • 博客等级: 民兵
  • 技术积分: 220
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-27 14:53
文章分类

全部博文(149)

文章存档

2016年(3)

2015年(2)

2014年(144)

我的朋友

分类: 嵌入式

2014-09-23 21:49:09

原文地址:GPIO驱动之LED灯 作者:yanhongkang928

GPIO驱动之LED

参考网页:http://blog.chinaunix.net/u3/102836/showart_2065945.html

先从底层硬件看起,4LED灯接着GPF0~GPF3, 高电平时灭,低电平时亮

然后查看相关控制寄存器和数据寄存器

rGPFCON = (rGPFCON | 0xFFFF) & 0xFFFFFF55;  //GPF0--GPF3设置为output      

     rGPFUP  = rGPFUP & 0xFFF0;                  //使能GPF上拉电阻

     rGPFDAT = 0x0F;                                            //GPF4位初始化为1

 

1. linux-2.6.31\arch\arm\plat-s3c24xx\gpio.c中定义了内核直接对GPIO的控制函数:

void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)  

/* s3c2410_gpio_cfgpin

 *

 * set the configuration of the given pin to the value passed.

 *

 * eg:

 *    s3c2410_gpio_cfgpin(S3C2410_GPA(0), S3C2410_GPA0_ADDR0);

 *    s3c2410_gpio_cfgpin(S3C2410_GPE(8), S3C2410_GPE8_SDDAT1);

*/

unsigned int s3c2410_gpio_getcfg(unsigned int pin)

/* s3c2410_gpio_getirq

 *

 * turn the given pin number into the corresponding IRQ number

 *

 * returns:

 *    < 0 = no interrupt for this pin

 *    >=0 = interrupt number for the pin

*/

void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)

/* s3c2410_gpio_pullup

 *

 * configure the pull-up control on the given pin

 *

 * to      1 => disable the pull-up

 *      0 => enable the pull-up

 *

 * eg;

 *

 *   s3c2410_gpio_pullup(S3C2410_GPB(0), 0);

 *   s3c2410_gpio_pullup(S3C2410_GPE(8), 0);

*/

int s3c2410_gpio_getpull(unsigned int pin)

/* s3c2410_gpio_getpull

 *

 * Read the state of the pull-up on a given pin

 *

 * return:

 *    < 0 => error code

 *      0 => enabled

 *      1 => disabled

*/

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)

/* s3c2410_gpio_irqfilter

 *

 * set the irq filtering on the given pin

 *

 * on = 0 => disable filtering

 *      1 => enable filtering

 *

 * config = S3C2410_EINTFLT_PCLK or S3C2410_EINTFLT_EXTCLK orred with

 *          width of filter (0 through 63)

 *

 *

*/

2.linux-2.6.31\arch\arm\mach-s3c2410\include\mach\gpio-nrs.h中定义了GPIOA~H的地址位

#define S3C2410_GPIONO(bank,offset) ((bank) + (offset))

#define S3C2410_GPIO_NEXT(__gpio) \

       ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 0)

enum s3c_gpio_number {

       S3C2410_GPIO_A_START = 0,

       S3C2410_GPIO_B_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_A),

       S3C2410_GPIO_C_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_B),

       S3C2410_GPIO_D_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_C),

       S3C2410_GPIO_E_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_D),

       S3C2410_GPIO_F_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_E),

       S3C2410_GPIO_G_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_F),

       S3C2410_GPIO_H_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_G),

};

#define S3C2410_GPF(_nr) (S3C2410_GPIO_F_START + (_nr))

 

3.linux-2.6.31\arch\arm\mach-s3c2410\include\mach\regs-gpio.h中详细定义了GPIO A~H的所有寄存器并定义了各位的置一时的代理,还有最重要的映射地址:

#define S3C2410_GPFCON    S3C2410_GPIOREG(0x50)

#define S3C2410_GPFDAT     S3C2410_GPIOREG(0x54)

#define S3C2410_GPFUP       S3C2410_GPIOREG(0x58)

#define S3C2410_GPF0_EINT0  (0x02 << 0)

#define S3C2410_GPF1_EINT1  (0x02 << 2)

#define S3C2410_GPF2_EINT2  (0x02 << 4)

#define S3C2410_GPF3_EINT3  (0x02 << 6)

#define S3C2410_GPF4_EINT4  (0x02 << 8)

#define S3C2410_GPF5_EINT5  (0x02 << 10)

#define S3C2410_GPF6_EINT6  (0x02 << 12)

#define S3C2410_GPF7_EINT7  (0x02 << 14)

#define S3C2410_GPF_PUPDIS(x)  (1<<(x))

 

 

#define S3C24XX_GPIO_BASE(x)  S3C2410_GPIO_BASE(x)

#define S3C24XX_MISCCR        S3C24XX_GPIOREG2(0x80)

 

#define S3C2410_GPIO_BASE(pin)   ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO)

#define S3C2410_GPIO_OFFSET(pin) ((pin) & 31)

 

/* general configuration options */

 

#define S3C2410_GPIO_LEAVE   (0xFFFFFFFF)

#define S3C2410_GPIO_INPUT   (0xFFFFFFF0)    /* not available on A */

#define S3C2410_GPIO_OUTPUT  (0xFFFFFFF1)

#define S3C2410_GPIO_IRQ     (0xFFFFFFF2)     /* not available for all */

#define S3C2410_GPIO_SFN2    (0xFFFFFFF2)    /* bank A => addr/cs/nand */

#define S3C2410_GPIO_SFN3    (0xFFFFFFF3)    /* not available on A */

 

/* register address for the GPIO registers.

 * S3C24XX_GPIOREG2 is for the second set of registers in the

 * GPIO which move between s3c2410 and s3c2412 type systems */

 

#define S3C2410_GPIOREG(x) ((x) + S3C24XX_VA_GPIO)

#define S3C24XX_GPIOREG2(x) ((x) + S3C24XX_VA_GPIO2)

 

 

/************************************************

LED的驱动,在TX2440A开发板上做测试

linux内核:2.6.31

 

硬件接法:

              LED1 --> GPF0

              LED2 --> GPF1

              LED3 --> GPF2

              LED4 --> GPF3

              低电平点亮

驱动用法:

              设备名称:TX2440-led

              点亮一个灯:LED_ON

              熄灭一个灯:LED_OFF

              点亮所有灯:ALL_LED_ON

              熄灭所有灯:ALL_LED_OFF

说明:

              内核源码里已经有LED的驱动,将它们注释掉

              arch/arm/plat-s3c24xx/common-smdk.c

              GPF0-GPF3设为输出,全部输出低电平

*************************************************/

#include

#include

#include

#include

#include

#include

//#include

#include     //定义了GPIO寄存器的实际物理地址

//#include

#include

#include     //定义了device, device driver, bus_type, class等多个重要的结构体

#include        

#define DEVICE_NAME       "TX2440-led"    /* 设备名称 */             

static int LED_Major = 0;                    /* 主设备号 */

 

#define LED_OFF           0

#define LED_ON             1

#define ALL_LED_OFF      3

#define ALL_LED_ON       4

 

/* 用来指定LED所用的GPIO引脚 */

static unsigned long led_table [] =

{

       S3C2410_GPF(0),

       S3C2410_GPF(1),

       S3C2410_GPF(2),

       S3C2410_GPF(3),

};

/*分别定义open ,release , ioctl 执行命令*/

static int TX2440_led_open(struct inode *inode, struct file *file)

{

//     MOD_INC_USE_COUNT;

       printk("TX2440-LED Driver Open Called!\n");

       return 0;

}

 

static int TX2440_led_release(struct inode *inode, struct file *file)

{

//     MOD_DEC_USE_COUNT;

       printk("TX2440-LED Driver Release Called!\n");

       return 0;

}

 

static int TX2440_led_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)

{

       int i;

       if (arg > 4)

       {

              return -EINVAL;

       }

       switch(cmd)

       {

              case LED_ON:  //set the pin

                     s3c2410_gpio_setpin(led_table[arg], 0);

                     break;

 

              case LED_OFF:  //clr the pin

                     s3c2410_gpio_setpin(led_table[arg], 1);

                     break;

                    

              case ALL_LED_ON:  //set all pin

                     for (i = 0; i < 4; i++)

                            s3c2410_gpio_setpin(led_table[i], 0);

                     break;

                    

              case ALL_LED_OFF:  //clr all pin

                     for (i = 0; i < 4; i++)

                            s3c2410_gpio_setpin(led_table[i], 1);

                     break;

 

              default:

                     return -EINVAL;

       }

}

 

static struct file_operations TX2440_led_fops =

{

       .owner  =   THIS_MODULE,

       .open   =   TX2440_led_open,

       .release =  TX2440_led_release,

       .ioctl  =   TX2440_led_ioctl,

};

 

static struct class *led_class;

 

static int __init TX2440_led_init(void)

{

 

       printk("TX2440 LED DRIVER MODULE INIT\n");

 

       LED_Major = register_chrdev(0, DEVICE_NAME, &TX2440_led_fops);

/*向内核注册一个设备,内核返回一个主设备号*/

       if (LED_Major < 0)

       {

              printk(DEVICE_NAME " can't register major number\n");

              return LED_Major;

       }

       printk("register TX2440-LED Driver OK! Major = %d\n", LED_Major);

 

       led_class = class_create(THIS_MODULE, DEVICE_NAME);

/*/sysfs目录下创建这个设备的类*/

       if(IS_ERR(led_class))

       {

              printk("Err: failed in TX2440-LED class. \n");

              return -1;

       }

 

       device_create(led_class, NULL, MKDEV(LED_Major, 0), NULL, DEVICE_NAME);

/*/sysfs目录下注册这个设备,并创建设备节点*/

       printk(DEVICE_NAME " initialized\n");

       return 0;

}

 

static void __exit TX2440_led_exit(void)

{

       printk("TX2440 LED DRIVER MODULE EXIT\n");

       unregister_chrdev(LED_Major, DEVICE_NAME);

       device_destroy(led_class, MKDEV(LED_Major, 0));

       class_destroy(led_class);

}

 

module_init(TX2440_led_init);

module_exit(TX2440_led_exit);

 

阅读(1366) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~