国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

查看: 3469|回復(fù): 0
打印 上一主題 下一主題

fs2410開發(fā)板的按鍵驅(qū)動程序

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2011-5-12 19:46:31 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
關(guān)鍵詞: linux
#include
#include
#include #include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include #include
#include
#include
#include
#include
#include #define MAX_KEY_BUF 16#define UP 0
#define DOWN 1
#define NAME "s3c2410-key"static int key_major;
dev_t devno;typedef struct {
        unsigned char pressure;
        unsigned char number;
} KEY_RET;typedef struct
{
        KEY_RET buf[MAX_KEY_BUF];
        int head,tail;        
        wait_queue_head_t wq;
        spinlock_t lock;
        struct cdev cdev;
} KEY_DEV;
KEY_DEV s3c2410_key_dev; #define BUF_HEAD                (s3c2410_key_dev.buf[s3c2410_key_dev.head])
#define BUF_TAIL                (s3c2410_key_dev.buf[s3c2410_key_dev.tail])
#define DELAY                 (HZ/100) /* 10 ms */
#define INCBUF(x,mod)         ((++(x)) & ((mod) - 1))static struct timer_list key_timer[4];static struct key_info
{
        int irq_no;
        int key_no;
} key_info_tab[16] =
{
  {IRQ_EINT19,1},{IRQ_EINT19,2},{IRQ_EINT19,3},{IRQ_EINT19,13},
  {IRQ_EINT11,4},{IRQ_EINT11,5},{IRQ_EINT11,6},{IRQ_EINT11,14},
  {IRQ_EINT2,7}, {IRQ_EINT2,8}, {IRQ_EINT2,9}, {IRQ_EINT2,15},
  {IRQ_EINT0,10},{IRQ_EINT0,11},{IRQ_EINT0,12},{IRQ_EINT0,16},
};static void gpio_set(void)
{
        s3c2410_gpio_cfgpin(S3C2410_GPE11,S3C2410_GPE11_OUTP);s3c2410_gpio_cfgpin(S3C2410_GPE13,S3C2410_GPE13_OUTP);
        s3c2410_gpio_cfgpin(S3C2410_GPG2,S3C2410_GPG2_OUTP);s3c2410_gpio_cfgpin(S3C2410_GPG6,S3C2410_GPG6_OUTP);        s3c2410_gpio_setpin(S3C2410_GPE11,0);s3c2410_gpio_setpin(S3C2410_GPE13,0);
        s3c2410_gpio_setpin(S3C2410_GPG2,0);s3c2410_gpio_setpin(S3C2410_GPG6,0);        s3c2410_gpio_cfgpin(S3C2410_GPF0,S3C2410_GPF0_EINT0);s3c2410_gpio_cfgpin(S3C2410_GPF2,S3C2410_GPF2_EINT2);
        s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_EINT11);s3c2410_gpio_cfgpin(S3C2410_GPG11,S3C2410_GPG11_EINT19);        set_irq_type(IRQ_EINT0,IRQT_FALLING);set_irq_type(IRQ_EINT2,IRQT_FALLING);
        set_irq_type(IRQ_EINT11,IRQT_FALLING);set_irq_type(IRQ_EINT19,IRQT_FALLING);
}static void irq_unmask(void)
{
        enable_irq(IRQ_EINT0);enable_irq(IRQ_EINT2);enable_irq(IRQ_EINT11);enable_irq(IRQ_EINT19);
}static void irq_mask(void)
{
        disable_irq(IRQ_EINT0);disable_irq(IRQ_EINT2);disable_irq(IRQ_EINT11);disable_irq(IRQ_EINT19);
}static unsigned char key_scan(void)
{
        s3c2410_gpio_cfgpin(S3C2410_GPF0,S3C2410_GPF0_INP);s3c2410_gpio_cfgpin(S3C2410_GPF2,S3C2410_GPF2_INP);
        s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_INP);s3c2410_gpio_cfgpin(S3C2410_GPG11,S3C2410_GPG11_INP);        s3c2410_gpio_setpin(S3C2410_GPE11,0);s3c2410_gpio_setpin(S3C2410_GPE13,1);
        s3c2410_gpio_setpin(S3C2410_GPG2,1);s3c2410_gpio_setpin(S3C2410_GPG6,1);
        if(s3c2410_gpio_getpin(S3C2410_GPF0) == 0) return 0x0a;
        if(s3c2410_gpio_getpin(S3C2410_GPF2) == 0) return 0x07;
        if(s3c2410_gpio_getpin(S3C2410_GPG3) == 0) return 0x04;
        if(s3c2410_gpio_getpin(S3C2410_GPG11) == 0) return 0x01;        s3c2410_gpio_setpin(S3C2410_GPE11,1);s3c2410_gpio_setpin(S3C2410_GPE13,0);
        s3c2410_gpio_setpin(S3C2410_GPG2,1);s3c2410_gpio_setpin(S3C2410_GPG6,1);
        if(s3c2410_gpio_getpin(S3C2410_GPF0) == 0) return 0x0C;
        if(s3c2410_gpio_getpin(S3C2410_GPF2) == 0) return 0x09;
        if(s3c2410_gpio_getpin(S3C2410_GPG3) == 0) return 0x06;
        if(s3c2410_gpio_getpin(S3C2410_GPG11) == 0) return 0x03;        s3c2410_gpio_setpin(S3C2410_GPE11,1);s3c2410_gpio_setpin(S3C2410_GPE13,1);
        s3c2410_gpio_setpin(S3C2410_GPG2,0);s3c2410_gpio_setpin(S3C2410_GPG6,1);
        if(s3c2410_gpio_getpin(S3C2410_GPF0) == 0) return 0x10;
        if(s3c2410_gpio_getpin(S3C2410_GPF2) == 0) return 0x0F;
        if(s3c2410_gpio_getpin(S3C2410_GPG3) == 0) return 0x0E;
        if(s3c2410_gpio_getpin(S3C2410_GPG11) == 0) return 0x0D;        s3c2410_gpio_setpin(S3C2410_GPE11,1);s3c2410_gpio_setpin(S3C2410_GPE13,1);
        s3c2410_gpio_setpin(S3C2410_GPG2,1);s3c2410_gpio_setpin(S3C2410_GPG6,0);
        if(s3c2410_gpio_getpin(S3C2410_GPF0) == 0) return 0x0B;
        if(s3c2410_gpio_getpin(S3C2410_GPF2) == 0) return 0x08;
        if(s3c2410_gpio_getpin(S3C2410_GPG3) == 0) return 0x05;
        if(s3c2410_gpio_getpin(S3C2410_GPG11) == 0) return 0x02;
}static irqreturn_t irq_isr(int irq, void *dev_id, struct pt_regs *reg)
{
        int i = *((int *)dev_id);        spin_lock_irq(&(s3c2410_key_dev.lock));//防止此中斷被再次調(diào)用發(fā)生死鎖故而關(guān)閉此CPU中斷
        BUF_HEAD.pressure = DOWN;
        BUF_HEAD.number = key_scan();
        if(i == IRQ_EINT19) {key_timer[0].expires =jiffies+DELAY;add_timer(key_timer);}
        if(i == IRQ_EINT11) {key_timer[1].expires =jiffies+DELAY;add_timer(key_timer+1);}
        if(i == IRQ_EINT2) {key_timer[2].expires =jiffies+DELAY;add_timer(key_timer+2);}
        if(i == IRQ_EINT0) {key_timer[3].expires =jiffies+DELAY;add_timer(key_timer+3);}
        gpio_set();
        spin_unlock_irq(&(s3c2410_key_dev.lock));
        return IRQ_HANDLED;
}static void key_timer_handler(unsigned long data)
{
        unsigned long i = data;        if(BUF_HEAD.number == key_scan())
        {
                if(BUF_HEAD.pressure == DOWN)
                {
                        BUF_HEAD.pressure = UP;
                        INCBUF(s3c2410_key_dev.head,MAX_KEY_BUF);
                        wake_up_interruptible(&(s3c2410_key_dev.wq));//喚醒進(jìn)程               
                }
        }
        gpio_set();
        if(i == IRQ_EINT19) {key_timer[0].expires =jiffies+DELAY;add_timer(key_timer);}
        if(i == IRQ_EINT11) {key_timer[1].expires =jiffies+DELAY;add_timer(key_timer+1);}
        if(i == IRQ_EINT2)  {key_timer[2].expires =jiffies+DELAY;add_timer(key_timer+2);}
        if(i == IRQ_EINT0)  {key_timer[3].expires =jiffies+DELAY;add_timer(key_timer+3);}
}static int request_irqs(void)
{
        struct key_info *k=key_info_tab;
        int i,j;        for(i=0;i<16;i+=4)
        {
                j=request_irq((k+i)->irq_no,irq_isr,SA_INTERRUPT,NAME,&((k+i)->irq_no));
                if(j)
                        return j;
        }
        return 0;
}static void free_irqs(void)
{
        struct key_info *k=key_info_tab;
        int i;        for(i=0;i<16;i+=4)
                free_irq((k+i)->irq_no,NULL);
}static int s3c2410key_open(struct inode *inode, struct file *file)
{
        s3c2410_key_dev.head = s3c2410_key_dev.tail = 0;
        gpio_set();
        irq_unmask();
        return 0;
}static int s3c2410key_release(struct inode *inode, struct file *file)
{
        int i;        irq_mask();
        for(i = 0 ;i < 4 ; i++) del_timer(key_timer+i);
        return 0;
}static ssize_t read_key(KEY_RET *addr,size_t data)
{
        size_t i;        spin_lock_irq(&(s3c2410_key_dev.lock));
        if(!data) return 0;
        for(i= 0;i < data;i++)
        {
                addr->pressure = BUF_TAIL.pressure;
                addr->number = BUF_TAIL.number;
                addr++;
                INCBUF(s3c2410_key_dev.tail,MAX_KEY_BUF);
        }
        spin_unlock_irq(&(s3c2410_key_dev.lock));
        return (data*sizeof(KEY_RET));
}static ssize_t s3c2410key_read(struct file *filp,char __user *buffer,size_t count, loff_t *ppos)
{
        KEY_RET ret;
next:
        if(s3c2410_key_dev.head != s3c2410_key_dev.tail)
        {
                if(count >= s3c2410_key_dev.head-s3c2410_key_dev.tail)
                        count = s3c2410_key_dev.head-s3c2410_key_dev.tail;
                count = read_key(&ret,count);
                if (count) copy_to_user(buffer, (char *)&ret, count);
                return count;
        }
        else
        {
                if(filp->f_flags & O_NONBLOCK)
                        return -EAGAIN;
                interruptible_sleep_on(&(s3c2410_key_dev.wq));
                goto next;
        }
}static struct file_operations s3c2410_key_ops = {
        .owner                = THIS_MODULE,
        .open                = s3c2410key_open,
        .release        = s3c2410key_release,
        .read                 = s3c2410key_read,
};static char __initdata banner[] = "S3C2410 keydriver, 2009 yangdan edit\n";static int __init s3c2410_key_init(void)
{
        int result,i;        printk(banner);
        result=alloc_chrdev_region(&devno,0,1,"keydev");
        key_major =MAJOR(devno);
        if(result < 0)
        {
                printk(KERN_NOTICE "error %d request device no",result);               
                return result;
        }        cdev_init(&s3c2410_key_dev.cdev,&s3c2410_key_ops);
        s3c2410_key_dev.cdev.owner = THIS_MODULE;
        result = cdev_add(&s3c2410_key_dev.cdev,devno,1);
        if(result)
        {
                printk(KERN_NOTICE "error %d adding keydev",result);
                goto error;
        }
                        
        for(i=0;i < MAX_KEY_BUF ; i++)
                s3c2410_key_dev.buf.pressure = UP;
        init_waitqueue_head(&(s3c2410_key_dev.wq));
        
#ifdef CONFIG_DEVFS_FS
        devfs_mk_dir("char/key");
        devfs_mk_cdev(MKDEV(key_major,0),S_IFCHR|S_IRUGO|S_IWUSR,"char/key/%s",NAME);
#endif        result=request_irqs();
        if(result)
        {
                printk(KERN_NOTICE "error %d request irq",result);
                goto error;
        }        for(i=0;i < 4 ; i++)
        {        
                if(i == 0)
                        setup_timer(key_timer+i,key_timer_handler,IRQ_EINT19);
                else if(i == 1)
                        setup_timer(key_timer+i,key_timer_handler,IRQ_EINT11);
                else if(i == 2)
                        setup_timer(key_timer+i,key_timer_handler,IRQ_EINT2);
                else
                        setup_timer(key_timer+i,key_timer_handler,IRQ_EINT0);
        }
        return 0; error:
        unregister_chrdev_region(devno,1);
        return result;
}static void __exit s3c2410_key_exit(void)
{
        free_irqs();#ifdef CONFIG_DEVFS_FS
        devfs_remove("char/key/%s", NAME);
        devfs_remove("char/key");
#endif                cdev_del(&s3c2410_key_dev.cdev);
        unregister_chrdev_region(devno,1);        
}module_init(s3c2410_key_init);
module_exit(s3c2410_key_exit);MODULE_AUTHOR("yangdan, ");
MODULE_DESCRIPTION("ucdragon fs2410 key Driver");
MODULE_LICENSE("GPL");添加了devfs功能用于自動生成設(shè)備文件,所以使用時內(nèi)核要添加devfs選項。鍵盤驅(qū)動
編寫一個鍵盤驅(qū)動程序,有一些細(xì)節(jié)需要總結(jié)。
對于按鍵和觸摸屏等設(shè)備需要使用一個環(huán)形緩沖區(qū)來保存數(shù)據(jù)(其中緩沖區(qū)的長度要選取16的倍數(shù),以方便其自動復(fù)位),在這里是用head和tail來分別指向數(shù)據(jù)寫入和數(shù)據(jù)讀出,即當(dāng)有一個按鍵按下時對應(yīng)一個數(shù)據(jù)寫入時則添加head;當(dāng)應(yīng)用程序讀出一個數(shù)據(jù)時則添加tail;當(dāng)head不等于tail時則表明有資源可讀取,具體參照按鍵驅(qū)動程序。
在程序中大量使用了中斷和通用IO口設(shè)置程序,arch/arm/mach-s3c2410/gpio.c中有大量的函數(shù)用于根據(jù)引腳來配置功能函數(shù)可以很方便的簡化程序設(shè)計:
由于IO口配置時要無縫配置故而要參照以下函數(shù)的寫法
s3c2410_gpio_cfgpin //設(shè)置引腳為輸出 輸入 外部中斷模式
s3c2410_gpio_getcfg //獲取配置值以查看引腳處于那種工作模式
s3c2410_gpio_pullup //將引腳設(shè)為上拉功能
s3c2410_gpio_setpin //將引腳設(shè)置為輸出0或1
s3c2410_gpio_getpin //讀取引腳輸入值當(dāng)輸入為0時則值為0,為非0時則輸入為1
在寫讀函數(shù)時一定要將自己定義的結(jié)構(gòu)體轉(zhuǎn)換為字節(jié)數(shù)來傳遞給應(yīng)用程序,否則會出錯。 本文來自CSDN博客,轉(zhuǎn)載請標(biāo)明出處:http://blog.csdn.net/yd4330152763132/archive/2010/02/01/5275689.aspx
您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

關(guān)于我們  -  服務(wù)條款  -  使用指南  -  站點(diǎn)地圖  -  友情鏈接  -  聯(lián)系我們
電子工程網(wǎng) © 版權(quán)所有   京ICP備16069177號 | 京公網(wǎng)安備11010502021702
快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 黄h视频| 亚洲系列国产系列 | 亚洲图片视频在线 | 欧美视频xx | 黄色免费在线观看网站 | 国产一级做a爰片在线 | 在线视频一区二区日韩国产 | 算你色永久免费视频播放 | 四十路在线 | 久久婷婷五夜综合色频 | 女人高潮特级毛片 | 538porm在线看国产亚洲 | 69视频在线观看高清 | 中文字幕一区二区在线播放 | 亚洲国产二区三区久久 | 亚洲一区二区三区高清网 | 影院亚洲 | 黄色在线视频播放 | 精品视频一区二区三三区四区 | 亚洲区一| 青青久| 黄h视频在线观看视频 | 欧美国产成人精品一区二区三区 | 国产精品久久久久久免费播放 | 最新色网站 | 亚洲国产精品成人综合久久久 | 天天干天天操天天舔 | 色交视频 | 日韩特黄| 久久久国产成人精品 | 欧美1级| 国产线视频精品免费观看视频 | 香蕉视频地址 | 最新69国产成人精品视频69 | 久久精品免视着国产成人 | 国产高清在线免费观看 | 精品国产人成在线 | 一本久道热中字伊人 | 久草新视频 | 一卡二卡四卡无人区免费 | 2017亚洲天堂 |