闲来无事,清明节的时候便想着自己动手做一个简单的驱动
做什么呢,LED最简单,就整这个了.可还要在用户空间测试,好麻烦,不如直接用按键来控制了
于是便参照着资料,开始coding...
//#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define DEVICE_NAME "button"
#define MAX_KEY_BUF 16
#define KEY_NUM 4
static int button_major = 232;
typedef struct
{
unsigned int key_status[KEY_NUM];
//unsigned char buf[MAX_KEY_BUF];
//unsigned int head, tail;
//wait_queue_head_t wq;
struct cdev cdev;
}button_dev;
static button_dev *button_p;
static struct led_info
{
unsigned long gpio;
unsigned long gpio_status;
}led_table[4] =
{
{S3C2410_GPB7,S3C2410_GPB7_OUTP},
{S3C2410_GPB8,S3C2410_GPB8_OUTP},
{S3C2410_GPB9,S3C2410_GPB9_OUTP},
{S3C2410_GPB10,S3C2410_GPB10_OUTP},
};
static struct key_info
{
int irq_no;
unsigned int gpio_port;
int key_no;
}key_info_table[4] =
{
{ IRQ_EINT1, S3C2410_GPF1, 1},
{ IRQ_EINT2, S3C2410_GPF2, 2},
{ IRQ_EINT3, S3C2410_GPF3, 3},
{ IRQ_EINT7, S3C2410_GPF7, 4},
};
static void buttons_irq(int irq, void *dev_id, struct pt_regs *reg)
{
struct key_info *k;
int i,j = (int)dev_id;
printk("int %d received\n", j);
unsigned int value;
int found = 0;
for (i = 0; i < sizeof key_info_table / sizeof key_info_table[1]; i++)
{
k = key_info_table + i;
if (k->irq_no == irq)
{
found = 1;
break;
}
}
if (!found)
{
printk("bad irq %d in button\n", irq);
return;
}
printk("interrupt %d received!\n", i);
value = s3c2410_gpio_getpin(led_table[i].gpio);
if(value)
s3c2410_gpio_setpin(led_table[i].gpio,0);
else
s3c2410_gpio_setpin(led_table[i].gpio,1);
}
static int request_irqs(void)
{
struct key_info *k;
int i;
for (i = 0; i < sizeof key_info_table / sizeof key_info_table[1]; i++)
{
k = key_info_table + i;
//set_external_irq(k->irq_no, EXT_BOTH_EDGES, GPIO_PULLUP_DIS);
set_irq_type(k->irq_no, IRQT_BOTHEDGE);
if (request_irq(k->irq_no, &buttons_irq, SA_INTERRUPT, DEVICE_NAME,
i))
{
return -1;
}
}
printk("irq request successfully!\n");
return 0;
}
static void free_irqs(void)
{
struct key_info *k;
int i;
for (i = 0; i < sizeof key_info_table / sizeof key_info_table[1]; i++)
{
k = key_info_table + i;
free_irq(k->irq_no, buttons_irq);
}
}
static void button_setup(button_dev *dev, int index)
{
int err, devno = MKDEV(button_major, index);
dev->cdev.owner = THIS_MODULE;
err = cdev_add(&dev->cdev, devno, 1);
if(err)
{
printk(KERN_NOTICE"Error %d adding button", err);
}
}
static int button_init(void)
{
int ret,i;
dev_t devno = MKDEV(button_major,0);
ret = register_chrdev_region(devno, 1, "button");
if(ret)
return ret;
button_p = kmalloc(sizeof(button_dev), GFP_KERNEL);
if(!button_p)
{
ret = -ENOMEM;
goto fail;
}
memset(button_p, 0, sizeof(button_dev));
button_setup(button_p, 0);
for(i=0;i<4;i++)
{
s3c2410_gpio_cfgpin(led_table[i].gpio, led_table[i].gpio_status);
s3c2410_gpio_setpin(led_table[i].gpio, 1);
printk("led%d initialized!\n",i+1);
}
ret = request_irqs();
if(ret)
{
printk(DEVICE_NAME " can't request irqs\n");
goto fail;
}
printk("int request ok!\n");
return 0;
fail:
unregister_chrdev_region(devno, 1);
return ret;
}
static void button_exit(void)
{
cdev_del(&button_p->cdev);
kfree(button_p);
unregister_chrdev_region(MKDEV(button_major,0), 1);
free_irqs();
}
MODULE_AUTHOR("jimmy");
MODULE_LICENSE("Daul BSD/GPL");
module_param(button_major, int, S_IRUGO);
module_init(button_init);
module_exit(button_exit);
呵呵,按一下就亮,松开就灭(双边触发)
阅读(782) | 评论(0) | 转发(0) |