基于NanoPi M2A平台的按键中断驱动及Makefile


#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/gpio.h>
//#include <mach/platform.h>//kernel 3.4
//#include <mach/gpio_desc.h>
//#include <mach/gpio.h>


//gpio
enum {
    PAD_GPIO_A      = (0 * 32),
    PAD_GPIO_B      = (1 * 32),
    PAD_GPIO_C      = (2 * 32),
    PAD_GPIO_D      = (3 * 32),
    PAD_GPIO_E      = (4 * 32),
};

#define KEY_GPIO     (PAD_GPIO_B + 31)           //GPB31为触发终端源
#define KEY_GPIO_IRQ gpio_to_irq(KEY_GPIO)       //根据GPIO编号获取对应的引脚的中断编号
#define DEVICE_NAME "key_irq"

static int major;
static int minor;
struct cdev *key_irq; /* cdev 数据结构 */
struct file_operations key_irq_fops;
static dev_t devno; /* 设备编号 */
static struct class *key_irq_class;


char const irq_types[5] = {
      IRQ_TYPE_EDGE_RISING,
      IRQ_TYPE_EDGE_FALLING,
      IRQ_TYPE_EDGE_BOTH,
      IRQ_TYPE_LEVEL_HIGH,
      IRQ_TYPE_LEVEL_LOW
};


static irqreturn_t key_irq_irq_handler(unsigned int irq, void *dev_id)  //触发中断设置标志位?

printk(KERN_ERR"*************************************\n");
printk(KERN_ERR"KEY_IRQ TEST\n");
printk(KERN_ERR"*************************************\n");
    return IRQ_HANDLED;
}


static int __init key_irq_init(void)
{
      int ret;

      /*申请GPIO*/
      gpio_free(KEY_GPIO);              /*首先释放GPIO*/
      ret= gpio_request_one(KEY_GPIO, GPIOF_IN, "KEY IRQ"); /* 申请 IO ,为输入*/
      if(ret < 0) {
             printk(KERN_ERR"Failed to request GPIO for KEY\n");
      }

      gpio_direction_input(KEY_GPIO);/* 设置 GPIO 为输入 */

      /*申请GPB31对应的中断*/
      if(request_irq(KEY_GPIO_IRQ, key_irq_irq_handler, IRQF_TRIGGER_RISING, "key_irqirq", NULL) )
      {/* 申请中断 */
             printk(KERN_ERR": Can't get IRQ: %d!\n", KEY_GPIO_IRQ);
      }
      irq_set_irq_type(KEY_GPIO_IRQ,irq_types[0]); /*按键上升沿出发中断*/
      disable_irq(KEY_GPIO_IRQ);
      enable_irq(KEY_GPIO_IRQ);

      ret= alloc_chrdev_region(&devno, minor, 1, DEVICE_NAME); /* 从系统获取主设备号 */
      major= MAJOR(devno);
      if(ret < 0) {
             printk(KERN_ERR"cannot get major %d \n", major);
             return-1;
      }

      key_irq= cdev_alloc(); /* 分配 key_irq 结构 */
      if(key_irq != NULL) {
             cdev_init(key_irq,&key_irq_fops); /* 初始化 key_irq 结构 */
             key_irq->owner= THIS_MODULE;
             if(cdev_add(key_irq, devno, 1) != 0) { /* 增加 key_irq 到系统中 */
                    printk(KERN_ERR"add cdev error!\n");
                    goto error;
             }
      }
      else{
             printk(KERN_ERR"cdev_alloc error!\n");
             return-1;
      }

      key_irq_class= class_create(THIS_MODULE, "key_irq_class");//创建sys/class/key_irq_class
      if(IS_ERR(key_irq_class)) {
             printk(KERN_INFO"create class error\n");
             return-1;
      }

      device_create(key_irq_class,NULL, devno, NULL, DEVICE_NAME);
      printk("Initcompleted!\n");

      return 0;

error:
unregister_chrdev_region(devno,1); /* 释放已经获得的设备号 */
    return ret;
}

static void __exit key_irq_exit(void)
{

      gpio_free(KEY_GPIO);       /*释放为按键KEY申请的GPIO资源*/

      disable_irq(KEY_GPIO_IRQ);
      free_irq(KEY_GPIO_IRQ,NULL);
      cdev_del(key_irq);/* 移除字符设备 */
      unregister_chrdev_region(devno,1); /* 释放设备号 */
      device_destroy(key_irq_class,devno);
      class_destroy(key_irq_class);

      printk(KERN_INFO"Exit completed!\n");
}

module_init(key_irq_init);
module_exit(key_irq_exit);

MODULE_LICENSE("GPL");


Makefile 

obj-m   := gpio.o
KDIR    := /home/jiancao/linux-4.4/linux     ....内核路径
default:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) modules clean
rm -rf modules.order

猜你喜欢

转载自blog.csdn.net/weixin_42164528/article/details/80449566