新闻中心

EEPW首页>嵌入式系统>设计应用> S5PV210(TQ210)学习笔记——按键驱动程序

S5PV210(TQ210)学习笔记——按键驱动程序

作者: 时间:2016-11-28 来源:网络 收藏
  • init_waitqueue_head(&button_waitq);
  • return0;
  • device_error:
  • class_destroy(buttons_class);
  • class_error:
  • cdev_del(&cdev);
  • add_error:
  • unregister_chrdev_region(devno,1);
  • return-ENODEV;
  • }
  • voidbuttons_exit(void){
  • device_destroy(buttons_class,devno);
  • class_destroy(buttons_class);
  • cdev_del(&cdev);
  • unregister_chrdev_region(devno,1);
  • }
  • module_init(buttons_init);
  • module_exit(buttons_exit);
  • MODULE_LICENSE("GPL");
  • 测试程序代码:

    本文引用地址: //m.amcfsurvey.com/article/201611/322807.htm
    1. #include
    2. #include
    3. intmain(){
    4. intfd=open("/dev/buttons",O_RDWR);
    5. if(fd<0){
    6. printf("openerror");;
    7. return0;
    8. }
    9. unsignedcharkey;
    10. while(1){
    11. read(fd,&key,1);
    12. printf("Thekey=%x",key);
    13. }
    14. close(fd);
    15. }

    相比轮询方式的按键驱动程序,中断方式编写的按键驱动程序可以很大程度上节省CPU资源,因此,推荐使用中断方式。

    二 支持POLL机制

    上面这种方式实现的按键驱动程序有个弊端,如果我们不按键,应用程序将会永远阻塞在这里,幸运的是,linux内核提供了poll机制,可以设置超时等待时间,如果在这个时间内读取到键值则正常返回,反之则超时退出。使内核支持poll非常简单,为file_operations的poll成员提供poll处理函数即可。

    使内核支持poll还需要以下几步:

    添加poll头文件

    1. #include

    编写poll处理函数:

    1. staticunsignedbuttons_poll(structfile*file,poll_table*wait){
    2. unsignedintmask=0;
    3. poll_wait(file,&button_waitq,wait);
    4. if(pressed)
    5. mask|=POLLIN|POLLRDNORM;
    6. returnmask;
    7. }
    将poll处理函数添加给file_operations:
    1. .poll=buttons_poll,
    这样,驱动程序就支持poll机制了。下面是poll方式的测试程序:
    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. intmain(intargc,char**argv){
    7. intfd;
    8. unsignedcharkey_val;
    9. intret;
    10. structpollfdfds[1];
    11. fd=open("/dev/buttons",O_RDWR);
    12. if(fd<0){
    13. printf("cantopen!");
    14. }
    15. fds[0].fd=fd;
    16. fds[0].events=POLLIN;
    17. while(1){
    18. ret=poll(fds,1,5000);
    19. if(ret==0){
    20. printf("timeout");
    21. }
    22. else{
    23. read(fd,&key_val,1);
    24. printf("key_val=0x%x",key_val);
    25. }
    26. }
    27. return0;
    28. }

    这样,应用程序可以限制时间,如果在一定时间内读取不到键值就可以做特殊处理,这种思想在网络通信中应用广泛。

    三 支持异步机制

    很多情况下,我们的程序在等待按键期间需要处理其它任务而不是在这里空等,这时,就需要采用异步模式了。所谓异步模式,实际上是采用消息机制(以本文的按键程序为例),即当驱动程序检测到按键后发送消息给应用程序,应用程序接收到消息后再去读取键值。与前面的两种模式相比,最大的不同在于异步方式是驱动告诉应用程序来读而不是应用程序主动去读。添加异步支持更加简单,首先是为file_operations注册fasync函数,函数内容如下:

    1. staticintbuttons_fasync(intfd,structfile*file,inton){
    2. returnfasync_helper(fd,file,on,&button_async);
    3. }
    然后再buttons_read函数中添加一行代码,修改后的代码如下:
    1. staticssize_tbuttons_read(structfile*file,char__user*data,size_tcount,loff_t*loff){
    2. if(count!=1){
    3. printk(KERN_ERR"Thedrivercanonlygiveonekeyvalueonce!");
    4. return-ENOMEM;
    5. }
    6. wait_event_interruptible(button_waitq,pressed);
    7. pressed=0;
    8. if(copy_to_user(data,&key_val,1)){
    9. printk(KERN_ERR"Thedrivercannotcopythedatatouserarea!");
    10. return-ENOMEM;
    11. }
    12. return0;
    13. }
    这样,驱动程序就支持异步获取键值了,为了测试效果,测试程序也需要修改,代码如下:
    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. /*sixthdrvtest
    9. */
    10. intfd;
    11. voidmy_signal_fun(intsignum)
    12. {
    13. unsignedcharkey_val;
    14. read(fd,&key_val,1);
    15. printf("key_val:0x%x",key_val);
    16. }
    17. intmain(intargc,char**argv)
    18. {
    19. unsignedcharkey_val;
    20. intret;
    21. intOflags;
    22. signal(SIGIO,my_signal_fun);
    23. fd=open("/dev/buttons",O_RDWR|O_NONBLOCK);
    24. if(fd<0){
    25. printf("cantopen!");
    26. return-1;
    27. }
    28. fcntl(fd,F_SETOWN,getpid());
    29. Oflags=fcntl(fd,F_GETFL);
    30. fcntl(fd,F_SETFL,Oflags|FASYNC);
    31. intrest;
    32. while(1){
    33. printf("Hello");
    34. while(rest=sleep(50)){
    35. sleep(rest);
    36. }
    37. }
    38. return0;
    39. }
    这里需要注意的是,应用程序接收到消息会打断sleep,比如执行sleep(5)之后程序接收到了一个消息,这时,应用程序就被唤醒了,虽然是去执行的消息处理函数。如果程序接收到消息时仅睡眠了2秒,那么sleep被中断时会返回5-2=3,所以代码中采用while循环方式进行sleep,这样,即使接收到了消息也能完整的休眠5秒,当然,sleep函数本身是不够精确的,不过相差无几。

    到这里,这个驱动程序基本上就算可以了,当然,还有对阻塞和非阻塞的支持,同步与互斥的支持,而阻塞与非阻塞无非是加上个逻辑判断,同步与互斥根应用程序的同步控制也差不多,无非就是信号量或者原子操作,这里就不多说了,如果有朋友需要这些内容可以留言讨论。


    上一页 1 2 下一页

    关键词:S5PV210按键驱

    评论


    相关推荐

    技术专区

    关闭