查看: 1273|回复: 0
打印 上一主题 下一主题

arm驱动程序——按键程序4_poll(韦东山的视频总结及针对linux-2.6.30)

[复制链接]
跳转到指定楼层
沙发
发表于 2013-6-13 15:20:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
poll机制分析在以前的都有说明了,要是不理解可以看poll机制  

测试程序中都是用while(1)死循环查询,而利用poll函数可以睡眠固定时间,然后返回,也可以发生中断时唤醒

要在测试程序中用poll函数时,必须驱动程序有poll。

用到的函数及结构体:

/*file_operations中定义的,具体定义时给予具体的函数名和参数*/

unsigned int (*poll) (struct file *, struct poll_table_struct *)

/*加入队列*/

static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address,

                             poll_table *p)

驱动程序:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/device.h>
#include <linux/poll.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <mach/irqs.h>
#include <mach/regs-gpio.h>
/*不同的linux版本,头文件会有所不同*/

static int major;
/*定义一个类*/
static struct class *second_key_class;
/*定义一个设备*/
static struct device *second_key_device;
/*定义一个等待的头文件*/
static DECLARE_WAIT_QUEUE_HEAD(button_wait_head);
/*定义一个定时器*/
struct timer_list second_key_timer;
/*中断事件标志*/
static int ev_press=0;
static unsigned int key_val;
/*定义一个引脚描述的结构体*/
struct pindec
{
   unsigned int pin;
   unsigned int val;
};
/*定义引脚描述的数组,
*松开按键时,值为;0x01,0x02,0x03,0x04
*按下按键时,值为; 0x81,0x82,0x83,0x84*/
static struct pindec pin_dec[4]={
    {S3C2410_GPF1,0x01},

    {S3C2410_GPF4,0x02},
    {S3C2410_GPF2,0x03},

    {S3C2410_GPF0,0x04},
};

static struct pindec *irq_dec;

static irqreturn_t button_irq(int irq,void *dev)
{
    irq_dec = (struct pindec*)dev;

    /*修改定时器的超时时间*/
    mod_timer(&second_key_timer,jiffies+HZ/100);
    return IRQ_RETVAL(IRQ_HANDLED);
}
static int second_key_poll_open(struct inode *inode, struct file *file)
{
    /*注册中断*/
    request_irq(IRQ_EINT1,button_irq,IRQ_TYPE_EDGE_BOTH,"s1",&pin_dec[0]);
    request_irq(IRQ_EINT4,button_irq,IRQ_TYPE_EDGE_BOTH,"s2",&pin_dec[1]);
    request_irq(IRQ_EINT2,button_irq,IRQ_TYPE_EDGE_BOTH,"s3",&pin_dec[2]);
    request_irq(IRQ_EINT0,button_irq,IRQ_TYPE_EDGE_BOTH,"s4",&pin_dec[3]);
    return 0;
}


static ssize_t second_key_poll_read(struct file *file, char __user *user_buffer,
                                    size_t count, loff_t *ppos)
{
    if(count != 1)
    return -EINVAL;
    /*ev_press中断标志为0,休眠,即未发生中断时,休眠*/
    wait_event_interruptible(button_wait_head,ev_press);
    /*传数据到用户空间*/
    copy_to_user(user_buffer,&key_val,1);
    /*中断结束,中断标志置0,休眠*/
    ev_press = 0;
    return 1;
}
static unsigned int second_key_poll(struct file *file,
                                    struct poll_table_struct*wait)
{

    unsigned int mask = 0;
    /*挂载到队列中去*/
    poll_wait(file, &button_wait_head, wait);
    if(ev_press)
    mask = POLLIN; /*普通或优先级带数据可读*/
    return mask;
}


static int second_key_poll_close(struct inode *inode, struct file *file)
{
    free_irq(IRQ_EINT1,&pin_dec[0]);
    free_irq(IRQ_EINT4,&pin_dec[1]);
    free_irq(IRQ_EINT2,&pin_dec[2]);
    free_irq(IRQ_EINT0,&pin_dec[3]);
    return 0;
}
void second_timer_function(unsigned long data)
{
    unsigned int pinval;
    struct pindec *pin_desc =irq_dec;
    /*获得引脚状态*/
    pinval=s3c2410_gpio_getpin(pin_desc->pin);
    if(pinval)
        key_val = pin_desc->val;
    else
        key_val = pin_desc->val|0x80;
    /*唤醒*/
    ev_press = 1;
    wake_up_interruptible(&button_wait_head);
}
/*定义一个file_operations结构体*/
static struct file_operations second_key_poll_fops = {
   .owner = THIS_MODULE,
   .open  = second_key_poll_open,
   .read  = second_key_poll_read,
   .poll  = second_key_poll,
   .release = second_key_poll_close,
};
static int second_key_init(void)
{
   /*注册*/
   major = register_chrdev(0,"second_key",&second_key_poll_fops);
   /*创建类在/sys/class可以查找到*/
   second_key_class = class_create(THIS_MODULE,"second_key_class");
   /*类下创建设备可以在/sys/class/second_key_class可以查找到*/
   second_key_device =
     device_create(second_key_class,NULL,MKDEV(major,0),NULL,"second_key_device");
   /*初始化定时器*/
   init_timer(&second_key_timer);
   second_key_timer.function = second_timer_function;
   /*启动定时器*/
   add_timer(&second_key_timer);
   return 0;
}
static void second_key_exit(void)
{
    /*注销*/
    unregister_chrdev(major,"second_key");
    /*删除定时器*/
    del_timer(&second_key_timer);
    /*注销类*/
    device_unregister(second_key_device);
    /*销毁定义的类*/
    class_destroy(second_key_class);

}
/*修饰*/
module_init(second_key_init);
module_exit(second_key_exit);
MODULE_LICENSE("GPL");

测试程序:

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<poll.h>
int main(){
    int fd;
    int val=1;
    unsigned char key_val;
    int ret;
    struct pollfd fds[1];
    fd=open("/dev/second_key_device",O_RDWR);
    if(fd<0)
        printf("can't open!\n");

    /*设置文件描述符*/
    fds[0].fd=fd;

    /*设置等待的事件*/
    fds[0].events = POLLIN;
    while(1){

       ret = poll(fds,1,5000);

       /*超时,打印信息*/

       if(ret==0){
            printf("time out\n");
}


       else{
           read(fd,&key_val,1);
           printf("key_val = 0x%x\n",key_val);
       }
    }
    return 0;
}

下面就是测试:

1.加载驱动程序,利用insmod

2.运行测试程序

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入中科因仑

本版积分规则

快速回复 返回顶部 返回列表