如何在 Linux 用户空间中处理类似 GPIO 中断的处理

How to handle GPIO interrupt-like handling in Linux userspace

本文关键字:处理 中断 GPIO Linux 用户 空间      更新时间:2023-10-16

不确定我是否应该在这里发布这个,但我必须问。

上下文:

  • 嵌入式平台上的 Linux (CPU @~500MHz)
  • 一个团队致力于单一用户空间软件
  • 一个团队致力于Linux + 驱动程序 + uboot 等。

该软件必须处理GPIO,有些是输出(在需要时写入),有些是输入(某些需要时读取,其他最好是中断)。

该软件是一个多线程应用程序,SCHED_FIFO调度策略中具有~10-15个线程。

假设我有一个名为 WGPIO 的模块,它是一个处理 GPIO 的包装器。(顺便说一句,这是由Linux团队开发的。WGPIO 仍在用户空间中,但如果需要,他们可以开发驱动程序)

以下是我们发言时设计的一些pseudo_code。

gpio_state state = ON;
// IO_O is output. Set to ON, don't care if it's active_high or active_low btw
WGPIO_WriteOutput(IO_O,state);
// IO_I is input, read when needed
WGPIO_ReadInput(IO_I,&state);
// register callback when rising edge occurs on IO named IO_IT
WGPIO_SetCallback(IO_IT,EDGE_RISING,my_callback);
// Unmask to enable further IT-like processing
WGPIO_UnmaskIRQ(IO_IT);

我必须能够在 5 到 10 毫秒内处理一些 GPIO 更改。

多个 FD 上的某些用户空间轮询(WGPIO 将有一个SCHED_FIFO线程)是否足以模拟我的应用程序中的"类似中断"处理?这似乎是最简单的想法。

如果您需要更多详细信息,请随时询问。 提前谢谢。

来自内核 gpio/sysfs.txt:

"value" ... reads as either 0 (low) or 1 (high). If the GPIO
is configured as an output, this value may be written;
any nonzero value is treated as high.
If the pin can be configured as interrupt-generating interrupt
and if it has been configured to generate interrupts (see the
description of "edge"), you can poll(2) on that file and
poll(2) will return whenever the interrupt was triggered. If
you use poll(2), set the events POLLPRI and POLLERR. If you
use select(2), set the file descriptor in exceptfds. After
poll(2) returns, either lseek(2) to the beginning of the sysfs
file and read the new value or close the file and re-open it
to read the value.
"edge" ... reads as either "none", "rising", "falling", or
"both". Write these strings to select the signal edge(s)
that will make poll(2) on the "value" file return.
This file exists only if the pin can be configured as an
interrupt generating input pin.

首选方法通常是在/sys/class/gpio/gpioN/value上配置中断,/sys/class/gpio/gpioN/edgepoll(2)POLLPRI | POLLERR(重要的是它不是POLLIN!如果你的流程是一些需要实时处理事件的"实时"进程,请考虑降低它的美观度。

你甚至可以在 github 上找到一些使用轮询的示例代码,例如这个存储库。