S5PV210(TQ210)学习笔记——按键驱动程序
一 按键驱动程序的简单实现
本文引用地址:https://www.eepw.com.cn/article/201611/322807.htm下面是基于中断和消息的按键驱动程序,其工作原理是:当应用程序读取键值时,会调用按键驱动程序的read函数,而我们实现的read函数检测完读取长度后没有直接读取键值而是等待按键消息,如果没有按键,程序会进入休眠状态,这样可以节省大量的CPU,而当我们按键时硬件会产生中断,程序自动进入中断处理函数,在中断处理函数中,驱动程序读取键值存入全局变量并激活read函数中等待的消息,应用程序被迅速唤醒并通过read函数读取键值,如此,完成了获取键值的工作。下面是源码,比较简单,也就不多说了。
源码:
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- staticdev_tdevno;
- staticstructcdevcdev;
- staticstructclass*buttons_class;
- staticstructdevice*buttons_device;
- staticwait_queue_head_tbutton_waitq;
- staticvolatileintpressed=0;
- staticunsignedcharkey_val;
- structkey_desc{
- unsignedintpin;
- unsignedcharvalue;
- };
- staticstructkey_desckey_descs[8]={
- [0]={
- .pin=S5PV210_GPH0(0),
- .value=0x00,
- },
- [1]={
- .pin=S5PV210_GPH0(1),
- .value=0x01,
- },
- [2]={
- .pin=S5PV210_GPH0(2),
- .value=0x02,
- },
- [3]={
- .pin=S5PV210_GPH0(3),
- .value=0x03,
- },
- [4]={
- .pin=S5PV210_GPH0(4),
- .value=0x04,
- },
- [5]={
- .pin=S5PV210_GPH0(5),
- .value=0x05,
- },
- [6]={
- .pin=S5PV210_GPH2(6),
- .value=0x06,
- },
- [7]={
- .pin=S5PV210_GPH2(7),
- .value=0x07,
- },
- };
- staticirqreturn_tbuttons_irq(intirq,void*dev_id){
- volatilestructkey_desc*key=(volatilestructkey_desc*)dev_id;
- if(gpio_get_value(key->pin)){
- key_val=key->value|0x80;
- }
- else{
- key_val=key->value;
- }
- pressed=1;
- wake_up_interruptible(&button_waitq);
- returnIRQ_RETVAL(IRQ_HANDLED);
- }
- staticintbuttons_open(structinode*inode,structfile*file){
- intret;
- ret=request_irq(IRQ_EINT(0),buttons_irq,IRQ_TYPE_EDGE_BOTH,"key1",&key_descs[0]);
- if(ret)
- returnret;
- ret=request_irq(IRQ_EINT(1),buttons_irq,IRQ_TYPE_EDGE_BOTH,"key2",&key_descs[1]);
- if(ret)
- returnret;
- ret=request_irq(IRQ_EINT(2),buttons_irq,IRQ_TYPE_EDGE_BOTH,"key3",&key_descs[2]);
- if(ret)
- returnret;
- ret=request_irq(IRQ_EINT(3),buttons_irq,IRQ_TYPE_EDGE_BOTH,"key4",&key_descs[3]);
- if(ret)
- returnret;
- ret=request_irq(IRQ_EINT(4),buttons_irq,IRQ_TYPE_EDGE_BOTH,"key5",&key_descs[4]);
- if(ret)
- returnret;
- ret=request_irq(IRQ_EINT(5),buttons_irq,IRQ_TYPE_EDGE_BOTH,"key6",&key_descs[5]);
- if(ret)
- returnret;
- ret=request_irq(IRQ_EINT(22),buttons_irq,IRQ_TYPE_EDGE_BOTH,"key7",&key_descs[6]);
- if(ret)
- returnret;
- ret=request_irq(IRQ_EINT(23),buttons_irq,IRQ_TYPE_EDGE_BOTH,"key8",&key_descs[7]);
- if(ret)
- returnret;
- return0;
- }
- staticssize_tbuttons_read(structfile*file,char__user*data,size_tcount,loff_t*loff){
- if(count!=1){
- printk(KERN_ERR"Thedrivercanonlygiveonekeyvalueonce!");
- return-ENOMEM;
- }
- wait_event_interruptible(button_waitq,pressed);
- pressed=0;
- if(copy_to_user(data,&key_val,1)){
- printk(KERN_ERR"Thedrivercannotcopythedatatouserarea!");
- return-ENOMEM;
- }
- return0;
- }
- staticintbuttons_close(structinode*inode,structfile*file){
- free_irq(IRQ_EINT(0),&key_descs[0]);
- free_irq(IRQ_EINT(1),&key_descs[1]);
- free_irq(IRQ_EINT(2),&key_descs[2]);
- free_irq(IRQ_EINT(3),&key_descs[3]);
- free_irq(IRQ_EINT(4),&key_descs[4]);
- free_irq(IRQ_EINT(5),&key_descs[5]);
- free_irq(IRQ_EINT(22),&key_descs[6]);
- free_irq(IRQ_EINT(23),&key_descs[7]);
- return0;
- }
- structfile_operationsbuttons_ops={
- .open=buttons_open,
- .read=buttons_read,
- .release=buttons_close,
- };
- intbuttons_init(void){
- intret;
- cdev_init(&cdev,&buttons_ops);
- cdev.owner=THIS_MODULE;
- ret=alloc_chrdev_region(&devno,0,1,"buttons");
- if(ret){
- printk(KERN_ERR"allocchardeviceregionfaild!");
- returnret;
- }
- ret=cdev_add(&cdev,devno,1);
- if(ret){
- printk(KERN_ERR"addchardevicefaild!");
- gotoadd_error;
- }
- buttons_class=class_create(THIS_MODULE,"buttonsdrv");
- if(IS_ERR(buttons_class)){
- printk(KERN_ERR"createclasserror!");
- gotoclass_error;
- }
- buttons_device=device_create(buttons_class,NULL,devno,NULL,"buttons");
- if(IS_ERR(buttons_device)){
- printk(KERN_ERR"createbuttonsdeviceerror!");
- gotodevice_error;
- }
关键词:
S5PV210按键驱
评论