Linux 外部中断例子

喝咖啡的IT羊 2012-12-17

Linux 外部中断例子代码:

#include <linux/kernel.h> 
#include <linux/module.h> 
#include <linux/cdev.h> 
#include <linux/fs.h> 
#include <linux/device.h> 
#include <linux/syscalls.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/uaccess.h> 
#include <linux/string.h>

#include <mach/gpio.h>
#include <mach/irqs.h>

#define GPIO_TO_PIN(bank, gpio) (32 * (bank) + (gpio))


struct fpga_key_dev 

    struct cdev cdev; 
    dev_t devno; 
    char test[20];
    struct class *fpga_key_class;
 struct fasync_struct *async_queue;

 int message_cdev_open;
}; 

irqreturn_t irq_handler(int irqno, void *dev_id)

{
 printk("fpga key down\n");

 return IRQ_HANDLED;
}

static int fpga_key_open(struct inode *node, struct file *fd) 

 struct fpga_key_dev *dev;
 
 printk("fpga_key_open()++\n"); 

 printk("node->i_cdev = %x\n", (unsigned int)node->i_cdev);
 dev = container_of(node->i_cdev, struct fpga_key_dev, cdev);
 printk("dev->cdev = %x\n", (unsigned int)&dev->cdev);
 printk("dev = %x\n", (unsigned int)dev);
 
 if (!dev->message_cdev_open) {
  dev->message_cdev_open = 1;
  fd->private_data = dev;
 }
 else{
  return -EFAULT;
 }
 
 printk("test[20] = %s\n",dev->test);
 
    printk("fpga_key_open()--\n"); 
 
    return 0; 

 
static ssize_t fpga_key_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) 

    char temp_buffer [20]; 
    int print_size = 0; 
 struct fpga_key_dev *dev = fd->private_data;
     
    printk("fpga_key_wirte()++\n"); 
    if(len > 20) 
        print_size = 20; 
    else 
        print_size = len; 
    printk("print_size = %d; len = %d\n", print_size, len); 
    if(copy_from_user(temp_buffer, buf, print_size)) 
        return -EFAULT; 

 if (dev->async_queue)
  kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
 
    printk("writing data:%s", temp_buffer); 
     
    printk("fpga_key_wirte()--\n"); 
 
    return print_size; 

static ssize_t fpga_key_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr) 

      char *temp_buffer = "Hello fpga_key_read !\n"; 
      int print_size = 0; 
       
    printk("fpga_key_read()++\n"); 
     
    if(len > strnlen(temp_buffer,20)) 
        print_size = strnlen(temp_buffer,20); 
    else 
        print_size = len; 
    printk("print_size = %d; len = %d\n", print_size, len); 
    if(copy_to_user(buf, temp_buffer, print_size)) 
        return -EFAULT; 
    printk("%s", temp_buffer); 
    printk("fpga_key_read()--\n"); 
 
    return print_size; 

static int fpga_key_fasync(int fd, struct file *filp, int mode)
{
 struct fpga_key_dev  *dev = filp->private_data;

 printk("fpga_key_fasync()++\n");
 
 fasync_helper(fd, filp, mode, &dev->async_queue);

 printk("fpga_key_fasync()--\n");
 
 return 0;
}

static int fpga_key_release(struct inode *node, struct file *fd) 

 struct fpga_key_dev *dev = fd->private_data;
 
 printk("fpga_key_release()++\n");

 dev->message_cdev_open = 0;
 fpga_key_fasync(-1, fd, 0);
 
    printk("fpga_key_release()--\n"); 
    return 0; 
}


struct file_operations meassage_operatons = 

    .owner = THIS_MODULE, 
    .open = fpga_key_open, 
    .write = fpga_key_write,
    .read = fpga_key_read,
    .fasync = fpga_key_fasync,
    .release = fpga_key_release, 
}; 
 
struct fpga_key_dev fpga_key_dev; 
static int __init fpga_key_init(void) 

    struct fpga_key_dev * dev; 
 char * temp_char = "hello world\n";
 int ret = 0;
 int inter = 0;
 
    printk("fpga_key_to_app_init(void)++\n"); 
 
    dev = &fpga_key_dev; 
 strcpy(dev->test, temp_char);;

    alloc_chrdev_region(&dev->devno, 0, 1, "fpga_key_to_app"); 
    cdev_init(&dev->cdev, &meassage_operatons); 
    cdev_add(&dev->cdev, dev->devno, 1); 

    dev->fpga_key_class = class_create(THIS_MODULE, "fpga_key_class"); 
    if(IS_ERR(dev->fpga_key_class)) { 
        printk("Err: failed in creating class./n"); 
        goto fail1; 
    } 
    device_create(dev->fpga_key_class, NULL, dev->devno, NULL, "fpga_key"); 

 
 //init irq
 ret = gpio_request(GPIO_TO_PIN(1, 27), "fpga_key_inter");
 if(ret){
  printk("gpio_request() failed !\n");
  goto fail1;
 }
 ret = gpio_direction_input(GPIO_TO_PIN(1, 27));
 if(ret){
  printk("gpio_direction_input() failed !\n");
  goto fail2; 
 }
 inter = gpio_to_irq(GPIO_TO_PIN(1, 27));
 if(inter < 0){
  printk("gpio_to_irq() failed !\n");
  ret = inter;
  goto fail2; 
 }
 printk("inter = %d", inter);
 ret = request_irq(inter,
     irq_handler,
     IRQF_TRIGGER_FALLING | IRQF_SHARED,
     "fpga_key_inter",
     &dev->devno);
 if(ret){
  printk("request_irq() failed ! %d\n", ret);
  goto fail2;
 }
 
    printk("fpga_key_to_app_init(void)--\n");     
    return 0; 

fail2: 
 gpio_free(GPIO_TO_PIN(1, 27)); 
fail1:   
 device_destroy(dev->fpga_key_class, dev->devno); 
    class_destroy(dev->fpga_key_class); 
    cdev_del(&dev->cdev); 
    unregister_chrdev_region(dev->devno, 1); 

 return ret;

static void __exit fpga_key_exit(void) 

    struct fpga_key_dev *dev = &fpga_key_dev; 
 
    printk("fpga_key_to_app_exit(void)++\n");

 free_irq(AM33XX_IRQ_GPIO1_1, NULL);
 gpio_free(GPIO_TO_PIN(1, 27));
 
    device_destroy(dev->fpga_key_class, dev->devno); 
    class_destroy(dev->fpga_key_class); 
    cdev_del(&dev->cdev); 
    unregister_chrdev_region(dev->devno, 1); 
     
    printk("fpga_key_to_app_exit(void)--\n"); 

module_init(fpga_key_init); 
module_exit(fpga_key_exit); 
 
MODULE_LICENSE("GPL"); 
MODULE_AUTHOR("Driver Monkey"); 
MODULE_DESCRIPTION("Test fpga_key to App");