工作需要,编写GPIO驱动,已经测试通过。虽然现在看起来很简单,但是我刚出道,当时是绞尽了脑汁,分享一下给一些Linux刚上道的兄弟,让大家少走点弯路。注意,cmd=2在Linux-3.6.9中,ioctl不可以用此值,经核查此cmd已经被内核占用。我在这里也走过弯路,希望兄弟们不要再走了。
/*
@ lanjun
@2013.12.10
@cpu : AT91SAM9G45
@kerbel:linux-3.6.9
@gpio_c.c
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <mach/gpio.h>
#include <asm/uaccess.h>
#include "./GpioCaseCode.h"
#define DEVICE_NAME "gpio_c"
static long gpio_c_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
long val=0;
printk();
switch (cmd)
{
case INPUT_PB21:
{
val=at91_get_gpio_value(AT91_PIN_PB21);
put_user(val,(long *)arg);
break;
}
case INPUT_PB22:
{
val=at91_get_gpio_value(AT91_PIN_PB22);
put_user(val,(long *)arg);
break;
}
case INPUT_PB23:
{
val= at91_get_gpio_value(AT91_PIN_PB23);
put_user(val,(long *)arg);
break;
}
case INPUT_PB24:
{
val=at91_get_gpio_value(AT91_PIN_PB24);
put_user(val,(long *)arg);
break;
}
case INPUT_PB25:
{
val=at91_get_gpio_value(AT91_PIN_PB25);
put_user(val,(long *)arg);
break;
}
case INPUT_PB26:
{
val= at91_get_gpio_value(AT91_PIN_PB26);
put_user(val,(long *)arg);
break;
}
/* case INPUT_PB27:
{
val= at91_get_gpio_value(AT91_PIN_PB27);
put_user(val,(long *)arg);
break;
}*/
case OUTPUT_PB20:
{
at91_set_gpio_value(AT91_PIN_PB20,arg);
break;
}
case OUTPUT_PB28:
{
at91_set_gpio_value(AT91_PIN_PB28,arg);
break;
}
case OUTPUT_PB29:
{
at91_set_gpio_value(AT91_PIN_PB29,arg);
break;
}
case OUTPUT_PB30:
{
at91_set_gpio_value(AT91_PIN_PB30,arg);
break;
}
case OUTPUT_PB31:
{
at91_set_gpio_value(AT91_PIN_PB31,arg);
break;
}
case OUTPUT_PC24:
{
at91_set_gpio_value(AT91_PIN_PC24,arg);
break;
}
case OUTPUT_PC22:
{
at91_set_gpio_value(AT91_PIN_PC22,arg);
break;
}
case OUTPUT_PC20:
{
at91_set_gpio_value(AT91_PIN_PC20,arg);
break;
}
case OUTPUT_PC18:
{
at91_set_gpio_value(AT91_PIN_PC18,arg);
break;
}
case OUTPUT_PC16:
{
at91_set_gpio_value(AT91_PIN_PC16,arg);
break;
}
default: return -ENOTTY;
}
return 0;
}
static int gpio_c_open(struct inode *inode, struct file *file)
{
printk("Now device open successfully !\n");
return 0;
}
static struct file_operations gpio_c_dev_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = gpio_c_ioctl,
.open = gpio_c_open,
};
static struct miscdevice gpio_c_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &gpio_c_dev_fops,
};
static int __init gpio_c_dev_init(void) {
int ret=0;
ret = misc_register(&gpio_c_dev);
//use_pullup inside set 1,otherwise clear 0
at91_set_gpio_input(AT91_PIN_PB21, 0);
at91_set_gpio_input(AT91_PIN_PB22, 0);
at91_set_gpio_input(AT91_PIN_PB23, 0);
at91_set_gpio_input(AT91_PIN_PB24, 0);
at91_set_gpio_input(AT91_PIN_PB25, 0);
at91_set_gpio_input(AT91_PIN_PB26, 0);
at91_set_gpio_input(AT91_PIN_PB27, 0);
//at91_set_gpio_output(unsigned pin, int value)
at91_set_gpio_output(AT91_PIN_PB20, LOW);
at91_set_gpio_output(AT91_PIN_PB28, LOW);
at91_set_gpio_output(AT91_PIN_PB29, LOW);
at91_set_gpio_output(AT91_PIN_PB30, LOW);
at91_set_gpio_output(AT91_PIN_PB31, LOW);
at91_set_gpio_output(AT91_PIN_PC24, LOW);
at91_set_gpio_output(AT91_PIN_PC22, LOW);
at91_set_gpio_output(AT91_PIN_PC20, LOW);
at91_set_gpio_output(AT91_PIN_PC18, LOW);
at91_set_gpio_output(AT91_PIN_PC16, LOW);
printk(DEVICE_NAME"\tinitialized\n");
return ret;
}
static void __exit gpio_c_dev_exit(void) {
misc_deregister(&gpio_c_dev);
printk(DEVICE_NAME"\t exit\n");
}
module_init(gpio_c_dev_init);
module_exit(gpio_c_dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("lj_6@163.com");
/*
@ lanjun
@2013.12.10
@cpu : AT91SAM9G45
@GpioCaseCode.h
*/
#ifndef __GPIO_CASE_CODES_H__
#define __GPIO_CASE_CODES_H__
/*
addby lanjun 2013.11.10
ioctl(fd,CASE_CODES,arg) instruction:
1.CASE_CODES can be defined as follows.
2.If CASE_CODE is output_class ,you need to give the arg to
tell driver what you want to output: HIGH or LOW.
3.Corresponding to each case, there is only one pin .
*/
//input pins CASE_CODES without pullup inside of CPU
#define INPUT_PB21 (1)
#define INPUT_PB22 (8)
#define INPUT_PB23 (3)
#define INPUT_PB24 (4)
#define INPUT_PB25 (5)
#define INPUT_PB26 (6)
//#define INPUT_PB27 (7)
//output pins CASE_CODES
#define OUTPUT_PB20 (10)
#define OUTPUT_PB28 (11)
#define OUTPUT_PB29 (12)
#define OUTPUT_PB30 (13)
#define OUTPUT_PB31 (14)
#define OUTPUT_PC24 (15)
#define OUTPUT_PC22 (16)
#define OUTPUT_PC20 (17)
#define OUTPUT_PC18 (18)
#define OUTPUT_PC16 (19)
#define HIGH 1
#define LOW 0
#endif