手把手教你使用pcDuino的外部中斷(3)

按鍵中斷—poll機制php

咱們嘗試讓按鍵具備這樣一種功能,若是必定的時間內沒有人去按按鍵,內核就提醒一下,而後咱們應用程序獲得提醒以後打印time out。
驅動程序     key.c (3.77 KB, 下載次數: 0, 售價: 5 金錢) 
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/time.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/hrtimer.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <asm/io.h>
#include <linux/platform_device.h>
//#include <mach/gpio.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <linux/syscalls.h>
#include <linux/reboot.h>
#include <linux/proc_fs.h>
#include <linux/vmalloc.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/completion.h>
#include <asm/uaccess.h>
#include <mach/irqs.h>
#include <mach/system.h>
#include <mach/hardware.h>
#include <plat/sys_config.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/errno.h>
#include <linux/poll.h>
#define GPIO_IRQ  28
#define GPIO_TEST_BASE 0xf1c20800
#define PH_CFG2                     (GPIO_TEST_BASE + 0x104)
#define PIO_INT_CFG2    (GPIO_TEST_BASE+ 0x208)
#define PIO_INT_CTL                (GPIO_TEST_BASE+ 0x210)
#define PH17_SELECT (6 << 4)
#define PH18_SELECT (6 << 8)
#define PH19_SELECT (6 << 12)
static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
/* 中斷事件標誌, 中斷服務程序將它置1,third_drv_read將它清0 */
static volatile int ev_press = 0;
static struct class *keydrv_class;
static unsigned int status;
static irqreturn_t key_irq(int irq, void *dev_id)
{
         status =readl(GPIO_TEST_BASE + 0x214 ) ;
         
         ev_press = 1;                  /* 表示中斷髮生了 */
             wake_up_interruptible(&button_waitq);   /* 喚醒休眠的進程 */
         writel(status,GPIO_TEST_BASE + 0x214);      
         return IRQ_HANDLED;
}
static int key_drv_open(struct inode *inode, struct file *file)
{
         int error;
         int irq_ctl;
         /*1,設置中斷位*/
         irq_ctl =readl(PH_CFG2);
         writel(PH19_SELECT|PH17_SELECT|PH18_SELECT| irq_ctl ,PH_CFG2);
         /*2,設置中斷方式*/
         irq_ctl =readl(PIO_INT_CFG2);
         writel((0x4<<(1*4))|(0x4 <<(2*4))|(0x4 <<(3*4)) | irq_ctl,PIO_INT_CFG2);
         /*3,開中斷*/        
         irq_ctl =readl(PIO_INT_CTL);
         writel((0xf <<16)|irq_ctl,PIO_INT_CTL);
         error =request_irq(GPIO_IRQ, key_irq,0, "button", 1);
    if (error) {
        printk("failed toregister keypad interrupt\n");
    }
         
         printk(KERN_ALERT"keyopeni\n");
         
         return 0;
}
static unsigned key_drv_poll(struct file *file, poll_table *wait)
{
         unsigned int mask = 0;
         poll_wait(file,&button_waitq, wait); // 不會當即休眠
         if (ev_press)
                   mask |=POLLIN | POLLRDNORM;
         return mask;
}
ssize_t key_drv_read(struct file *file, char __user *buf, size_tsize, loff_t *ppos)
{
         /* 若是沒有按鍵動做, 休眠 */
         wait_event_interruptible(button_waitq,ev_press);
         /* 若是有按鍵動做, 返回鍵值 */
         copy_to_user(buf,&status, sizeof(unsigned int));
         ev_press = 0;
         
         return 1;
}
static ssize_t key_drv_write(struct file *file, const char __user*buf, size_t count, loff_t * ppos)
{
         printk(KERN_ALERT"keywrite\n");
         return 0;
}
int key_drv_close(struct inode *inode, struct file *file)
{
         free_irq(GPIO_IRQ,1);
         return 0;
}
static struct file_operations key_drv_fops = {
    .owner  =  THIS_MODULE,    /* 這是一個宏,推向編譯模塊時自動建立的__this_module變量 */
    .open   =  key_drv_open,     
    .write  =          key_drv_write,         
    .read   =       key_drv_read,
         .release =  key_drv_close,
         .poll    = key_drv_poll,
};
int major;
static int key_drv_init(void)
{        
         major =register_chrdev(0, "key_drv", &key_drv_fops);
         keydrv_class =class_create(THIS_MODULE,"key_drv");
         device_create(keydrv_class,NULL,MKDEV(major,0),NULL,"key");
         printk(KERN_ALERT"register\n");
         return 0;
}
static void key_drv_exit(void)
{
         unregister_chrdev(major,"key_drv"); // 卸載
         device_destroy(keydrv_class,MKDEV(major,0));
         class_destroy(keydrv_class);
         printk(KERN_ALERT"unregister\n");
}
module_init(key_drv_init);
module_exit(key_drv_exit);
MODULE_LICENSE("GPL");


測試程序     test_key.c (706 Bytes, 下載次數: 0, 售價: 5 金錢) 
#include<stdio.h>
#include<stdlib.h>
#include <poll.h>
         int kbit = 0;
void PrintBinary(unsigned int c)
{
    if (c>>1)PrintBinary(c>>1);
    printf("%d:%d",kbit, c&1);
         kbit++;
}
int main()
{
         int fd;
         unsigned int val = 1;
         int ret;
         struct pollfd fds[1];
         fd =open("/dev/key",0666);
         if(fd < 0)
         {
                   printf("cannotopen\n");
                   return 0;
         }
         fds[0].fd     = fd;
         fds[0].events =POLLIN;
         while(1)
         {
                   kbit = 0;
                   ret =poll(fds, 1, 5000);
                   if (ret ==0)
                   {
                            printf("timeout\n");
                   }
                   else
                   {
                            read(fd,&val,sizeof(unsignedint));
                            PrintBinary(val);
                            if(val&(1<<17))printf("Back\n");
                            if(val&(1<<18))printf("home\n");
                            if(val&(1<<19))printf("menu\n");
                   }
         }
         close(fd);
         return 0;
}


編譯:
gcc test_key.c
測試:
root @ubuntu :/home/ubuntu/driver/key_02# ./a.out
[10049.740000] key openi
0:1 1:0 2:0 3:0 4:0 5:0 6:0 7:0 8:0 9:0 10:0 11:0 12:0 13:0 14:015:0 16:0 17:0 18:0 home
0:1 1:0 2:0 3:0 4:0 5:0 6:0 7:0 8:0 9:0 10:0 11:0 12:0 13:0 14:015:0 16:0 17:0 18:0 home
time out
time out
time out
time out
0:1 1:0 2:0 3:0 4:0 5:0 6:0 7:0 8:0 9:0 10:0 11:0 12:0 13:0 14:015:0 16:0 17:0 Back
0:1 1:0 2:0 3:0 4:0 5:0 6:0 7:0 8:0 9:0 10:0 11:0 12:0 13:0 14:015:0 16:0 17:0 Back
相關文章
相關標籤/搜索