国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品
電子工程網
標題:
fs2410開發板的按鍵驅動程序
[打印本頁]
作者:
yd2763132
時間:
2011-5-12 19:46
標題:
fs2410開發板的按鍵驅動程序
#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
歡迎光臨 電子工程網 (http://www.qingdxww.cn/)
Powered by Discuz! X3.4
主站蜘蛛池模板:
久久国产亚洲欧美日韩精品
|
欧美日韩性生活视频
|
日本三级网站在线观看
|
日韩国产成人精品视频
|
日本一区欧美
|
成人亚洲精品7777
|
思思99热在线观看精品
|
亚洲视频免费看
|
四十路在线
|
男女羞羞视频免费观看
|
91精品视频网
|
一级毛片在线免费观看
|
国产福利小视频在线播放观看
|
日本高清不卡一区久久精品
|
日韩综合在线观看
|
一级黄色a
|
国产中日韩一区二区三区
|
国产videos hd
|
97视频免费上传播放
|
一区二区三区四区在线不卡高清
|
日韩在线视精品在亚洲
|
妞干网精品
|
韩国毛片一级
|
青青91
|
精品免费tv久久久久久久
|
自拍偷自拍亚洲精品情侣
|
99视频精品全部 在线
|
亚洲品色永久网址入口app
|
亚洲欧美日韩综合精品网
|
男女啪啪抽搐一进一出免费看
|
91情侣高清精品国产
|
国产三级影院
|
日本肥婆
|
久久66热re国产毛片基地
|
香蕉草莓丝瓜茄子番茄绿巨人
|
四虎国产精品免费视
|
欧美日韩中文在线观看
|
黄色网址视频免费
|
自拍偷拍免费视频
|
91麻豆精品国产高清在线
|
毛片网站免费在线观看
|