Chinaunix首页 | 论坛 | 博客
  • 博客访问: 804036
  • 博文数量: 244
  • 博客积分: 10000
  • 博客等级: 上将
  • 技术积分: 2420
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-29 09:07
文章分类

全部博文(244)

文章存档

2011年(4)

2010年(3)

2009年(72)

2008年(119)

2007年(46)

我的朋友

分类: LINUX

2009-04-29 14:57:13

闲来无事,清明节的时候便想着自己动手做一个简单的驱动
做什么呢,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);
呵呵,按一下就亮,松开就灭(双边触发)
阅读(745) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~