#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";
};