1.原理图

2.设备树代码

   	pe12_gpio_interrupts {
 		compatible = "allwinner,sunxi-pinctrl-test"; 
        	pinctrl-names = "default";
		key-gpios = <&pio PE 12 GPIO_ACTIVE_HIGH>;
		status = "okay";

        	interrupt-parent = <&pio>; /* 指定中断控制器 */
        	interrupts = <&pio PE 12 IRQ_TYPE_LEVEL_LOW>; 
    	};

3.驱动代码

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/semaphore.h>
#include <linux/timer.h>
#include <linux/of_irq.h>
#include <linux/irq.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>


#define PE12_IRQ_NAME        "pe12_irq"    /* 名字         */
#define KEY0VALUE            0X01        /* KEY0按键值     */
#define INVAKEY                0XFF        /* 无效的按键值 */
#define KEY_NUM                1            /* 按键数量     */

/* 中断IO描述结构体 */
struct irq_keydesc {
    int gpio;                                /* gpio */
    int irqnum;                                /* 中断号     */
    unsigned char value;                    /* 按键对应的键值 */
    char name[10];                            /* 名字 */
    irqreturn_t (*handler)(int, void *);    /* 中断服务函数 */
};

/* imx6uirq设备结构体 */
struct pe12_dev{
    dev_t devid;            /* 设备号      */
    struct cdev cdev;        /* cdev     */
    struct class *class;    /* 类         */
    struct device *device;    /* 设备      */
    int major;                /* 主设备号      */
    int minor;                /* 次设备号   */
    struct device_node    *nd; /* 设备节点 */
    atomic_t keyvalue;        /* 有效的按键键值 */
    atomic_t releasekey;    /* 标记是否完成一次完成的按键,包括按下和释放 */
    struct timer_list timer;/* 定义一个定时器*/
    struct irq_keydesc irqkeydesc;    /* 按键描述数组 */
    unsigned char curkeynum;                /* 当前的按键号 */
};

struct pe12_dev pe12_irq;    /* irq设备 */

/* @description        : 中断服务函数,开启定时器,延时10ms,
 *                        定时器用于按键消抖。
 * @param - irq     : 中断号
 * @param - dev_id    : 设备结构。
 * @return             : 中断执行结果
 */
static irqreturn_t key0_handler(int irq, void *dev_id)
{
// 清除中断标志位,具体清除方式需根据芯片手册确认
    // 这里假设读取GPIO状态可自动清除标志位
    int pe12_state = gpio_get_value(pe12_irq.irqkeydesc.gpio);

    printk(KERN_INFO "PE12 GPID IRQ: %d\n", pe12_state);

    // 在这里可以添加具体的业务逻辑处理
    // 比如根据状态执行不同操作等

    return IRQ_HANDLED;

}

/*
 * @description    : 驱动入口函数
 * @param         : 无
 * @return         : 无
 */
static int __init pe12_irq_init(void)
{

    unsigned char i = 0;
    int ret = 0;

    pe12_irq.nd = of_find_node_by_path("/pe12_gpio_interrupts");
    if (pe12_irq.nd== NULL)
    {
        printk("key node not find!\r\n");
        return -EINVAL;
    }
    else;


    pe12_irq.irqkeydesc.gpio = of_get_named_gpio(pe12_irq.nd ,"key-gpios", 0);
    if (pe12_irq.irqkeydesc.gpio < 0)
    {
            printk("can't get key-gpios%d\r\n", i);
    }


    // 初始化key所使用的IO,并且设置成中断模式

        //memset(pe12_irq.irqkeydesc[i].name, 0, sizeof(pe12_irq.irqkeydesc[i].name));    //缓冲区清零
        //sprintf(pe12_irq.irqkeydesc[i].name, "KEY%d", i);        /* 组合名字 */
        //gpio_request(pe12_irq.irqkeydesc.gpio, "PE 12 IRQ");
        //gpio_direction_input(pe12_irq.irqkeydesc.gpio);
        //pe12_irq.irqkeydesc.irqnum = irq_of_parse_and_map(pe12_irq.nd, 0);


//#if 0
        pe12_irq.irqkeydesc.irqnum = gpio_to_irq(pe12_irq.irqkeydesc.gpio);
//#endif
        printk("key:gpio=%d, irqnum=%d\r\n", pe12_irq.irqkeydesc.gpio,pe12_irq.irqkeydesc.irqnum);


    // 申请中断


        ret = request_irq(pe12_irq.irqkeydesc.irqnum, key0_handler,
                          IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, "PE 12 GPIO_IRQ", &pe12_irq);
        if(ret < 0)
        {
            printk("irq %d request failed!\r\n", pe12_irq.irqkeydesc.irqnum);
            return -EFAULT;
        }


    return 0;
}

/*
 * @description    : 驱动出口函数
 * @param         : 无
 * @return         : 无
 */
static void __exit pe12_irq_exit(void)
{
    unsigned int i = 0;
    // 删除定时器
    //del_timer_sync(&imx6uirq.timer);    /* 删除定时器 */

    // 释放中断

    free_irq(pe12_irq.irqkeydesc.irqnum, &pe12_irq);
    gpio_free(pe12_irq.irqkeydesc.gpio);

    cdev_del(&pe12_irq.cdev);
    unregister_chrdev_region(pe12_irq.devid, 1);
    device_destroy(pe12_irq.class, pe12_irq.devid);
    class_destroy(pe12_irq.class);
}

module_init(pe12_irq_init);
module_exit(pe12_irq_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("zuozhongkai");


 

4.测试

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐