GPIO: получение ISR на обоих ребрах, хотя для ребра установлено значение «rising».

#linux-kernel

#linux-ядро

Вопрос:

К переключателю подключен определенный вывод GPIO, при нажатии на который должен сработать ISR. Итак, у меня есть приложение пользовательского пространства для чтения ISR, но я получаю ISR по обоим краям.

Получение прерывания при нажатии переключателя, а также при отпускании. Как настроить получение ISR только по восходящему фронту

  #include <stdio.h>
 #include <stdlib.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <poll.h>

 int main(int argc, char *argv[]) {
    int fd;
    char value;
    struct pollfd poll_gpio;

    poll_gpio.events = POLLPRI;

    // export GPIO
    fd = open ("/sys/class/gpio/export", O_WRONLY);
    write (fd, "44", 4);
    close (fd);

    // configure as input
    fd = open ("/sys/class/gpio/gpio44/direction", O_WRONLY);
    write (fd, "in", 3);
    close (fd);

    // configure interrupt
    fd = open ("/sys/class/gpio/gpio44/edge", O_WRONLY);
    write (fd, "rising", 7); // configure as rising edge
    close (fd);

    // open value file
    fd = open("/sys/class/gpio/gpio44/value", O_RDONLY );
    poll_gpio.fd = fd;

    poll (amp;poll_gpio, 1, -1); // discard first IRQ
    read (fd, amp;value, 1);

    // wait for interrupt
    while (1) {
         poll (amp;poll_gpio, 1, -1);
         if ((poll_gpio.revents amp; POLLPRI) == POLLPRI) {
             lseek(fd, 0, SEEK_SET);
             read (fd, amp;value, 1);
             usleep  (50);
             printf("Interrupt GPIO val: %cn", value);
         }
    }

    close(fd); //close value file
    return EXIT_SUCCESS;
 }
 

Комментарии:

1. Использовать libgpiod . Это предпочтительнее, чем /sys/class интерфейс. and also when released. Вы уверены , что он не подпрыгивает? Вы должны исправить ошибки и проверить возвращаемое значение системных вызовов. По крайней poll мере , из write и.

2. То, чего вы пытаетесь достичь, можно легко сделать с помощью использования gpio-keys драйвера (с соответствующей выдержкой DTS или ACPI) без какого-либо кода на языке Си, подобного приведенному выше. Затем вы получите традиционное устройство ввода, к которому вы можете подключить (существующую) программу-демон для прослушивания события и запуска вашей любой программы.

Ответ №1:

Я также использовал тестовый драйвер gpio для тестирования ISR, но даже в коде драйвера я получаю ISR на обоих краях при нажатии переключателя. Вот код тестового драйвера gpio

 #include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/gpio.h>

#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/timer.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("");
MODULE_DESCRIPTION("A Button driver for the GPIO Switch");
MODULE_VERSION("0.1");

#define GPIO_NUM    44
#define GPIO_KEY_NAME   "GPIO_INT_KEY"
static int irq;

/* interrupt handler*/
static irqreturn_t gpio_int_key_isr(int irq, void *dev_id)
{
    
    printk(KERN_INFO "GPIO:Interrupt received. key: %sn", GPIO_KEY_NAME);
    return IRQ_HANDLED;
}

static int __init gpio_test_probe(struct platform_device *pdev)
{
    int ret_val;
    struct device *dev = amp;pdev->dev;

    printk(KERN_INFO "GPIO Platform_probe entern");

    gpio_request(GPIO_NUM, "sysfs");
    gpio_direction_input(GPIO_NUM);
    gpio_set_debounce(GPIO_NUM, 200);
    gpio_export(GPIO_NUM, false);

    irq = gpio_to_irq(GPIO_NUM);
    if (irq < 0)
    {
        pr_err("IRQ is not availablen");
        return -EINVAL;//1;
    }
    printk(KERN_INFO "IRQ using gpio_to_irq: %dn", irq);

    /*Register the interrupt handler*/
    ret_val = devm_request_irq(dev, irq, gpio_int_key_isr, IRQF_TRIGGER_RISING,  GPIO_KEY_NAME, pdev->dev.of_node);
    if(ret_val)
    {
        pr_err("Failed to request GPIO interrupt %d, error %dn",irq, ret_val);
        return ret_val;
    }

    return 0;
}

static int __exit gpio_test_remove(struct platform_device *pdev)
{
    pr_info("%s function is called. n",__func__);
    return 0;
}

/*Declare list of devices supported by the driver*/
static const struct of_device_id my_of_ids[] = {
        { .compatible = "gpio-intr-key"},
        {},
};

MODULE_DEVICE_TABLE(of, my_of_ids);

/*Define platform driver structure*/
static struct platform_driver my_platform_driver = {
        .probe = gpio_test_probe,
        .remove = gpio_test_remove,
        .driver = {
                .name = "gpioIntrKey",
                .of_match_table = of_match_ptr(my_of_ids),
                .owner = THIS_MODULE,
        }
};

module_platform_driver(my_platform_driver);
 

Ниже приведена запись dts

 gpio_test {
            compatible = "gpio-intr-key";
            gpio = <amp;gpio2a 44>;
            interrupt-controller;
            interrupt-parent = <amp;gpio2a>;
            interrupts = <44 IRQ_TYPE_EDGE_RISING>;
            status = "okay";
    };