S5PV210(TQ210)学习笔记——按键驱动程序
时间:11-28
来源:互联网
点击:
经过前面的配置,S5PV210开发已经可以成功进入Linux控制台了,那么,有了这个环境就可以开始学习Linux驱动的编写和测试了。学习Linux设备驱动,通常是从字符设备驱动开始。我写的第一个驱动程序是Led的,其实也就是熟悉下字符设备驱动的基本结构,本文以中断方式的按键驱动为例,简单的介绍下字符设备驱动程序。
一 按键驱动程序的简单实现
下面是基于中断和消息的按键驱动程序,其工作原理是:当应用程序读取键值时,会调用按键驱动程序的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_ad
S5PV210按键驱 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)