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

查看: 3430|回復: 0
打印 上一主題 下一主題

fs2410開發板的按鍵驅動程序

[復制鏈接]
跳轉到指定樓層
樓主
發表于 2011-5-12 19:46:31 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
關鍵詞: 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));//防止此中斷被再次調用發生死鎖故而關閉此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));//喚醒進程               
                }
        }
        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功能用于自動生成設備文件,所以使用時內核要添加devfs選項。鍵盤驅動
編寫一個鍵盤驅動程序,有一些細節需要總結。
對于按鍵和觸摸屏等設備需要使用一個環形緩沖區來保存數據(其中緩沖區的長度要選取16的倍數,以方便其自動復位),在這里是用head和tail來分別指向數據寫入和數據讀出,即當有一個按鍵按下時對應一個數據寫入時則添加head;當應用程序讀出一個數據時則添加tail;當head不等于tail時則表明有資源可讀取,具體參照按鍵驅動程序。
在程序中大量使用了中斷和通用IO口設置程序,arch/arm/mach-s3c2410/gpio.c中有大量的函數用于根據引腳來配置功能函數可以很方便的簡化程序設計:
由于IO口配置時要無縫配置故而要參照以下函數的寫法
s3c2410_gpio_cfgpin //設置引腳為輸出 輸入 外部中斷模式
s3c2410_gpio_getcfg //獲取配置值以查看引腳處于那種工作模式
s3c2410_gpio_pullup //將引腳設為上拉功能
s3c2410_gpio_setpin //將引腳設置為輸出0或1
s3c2410_gpio_getpin //讀取引腳輸入值當輸入為0時則值為0,為非0時則輸入為1
在寫讀函數時一定要將自己定義的結構體轉換為字節數來傳遞給應用程序,否則會出錯。 本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/yd4330152763132/archive/2010/02/01/5275689.aspx
您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲综合成人网在线观看 | 影音先锋5566夜色资源网 | 国产在线观看一区二区三区四区 | 免费av片在线观看网站 | 香蕉视频国产精品 | 国产精品密播放国产免费看 | 敢死队4完整版在线观看 | 欧美高清国产在线观看 | 日产精品卡2卡三卡乱码网站 | 国产成人毛片 | 99视频在线精品免费 | 色妹子综合 | 91热久久免费频精品黑人99 | 我不卡在线观看 | 老司机免费精品视频 | 亚洲欧美日韩一区 | 四虎影视永久地址www成人 | 国产日韩中文字幕 | 97精品国产91久久久久久久 | 精品国产高清a毛片 | 男人天堂综合网 | 色视频网站大全免费 | 受胎岛无删减全集在线观看 | 高清乱码精品福利在线视频 | ww欧美| 日韩在线观看免费完整版视频 | 国产一卡二卡三卡四卡 | 亚洲欧美在线视频 | 毛片一级在线观看 | 天天操夜夜拍 | 男女男在线观看视频网站 | 美女视频黄频a免费大全 视频 | 成年男女免费视频网站 | 巨大挺进湿润黑人粗大视频 | 精品国产看高清国产毛片 | 国产精品久久久久久久久久免费 | 国产极品美女网站在线观看 | 日韩免费高清一级毛片在线 | 国产精品免费久久久免费 | 高清毛片一区二区三区 | 国内精品久久国产 |