SOKS
SOKS

Reputation: 190

How to handle GPIO interrupt-like handling in Linux userspace

Not sure whether I should post this here or not but I gotta ask.

Context :

The software has to handle GPIO, some are output (write when needed), some are input (read when needed for some, preferably interrupt-like for others).

The software is a multi-threaded app with ~10-15 threads in SCHED_FIFO scheduling policy.

Let's say I have a module called WGPIO which is a wrapper handling GPIO. (this is developed by the Linux team btw. WGPIO is still in user-space, but they could develop a driver if needed)

Here is some pseudo_code of what is designed as we speak.

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);

I must be able to handle some of the GPIO changes in 5 to 10ms.

Is some userspace polling (WGPIO would have a SCHED_FIFO thread then) on multiple FDs enough to simulate an "interrupt-like" handling in my app ? This looks like the most simple idea.

If you need more details, feel free to ask. Thanks in advance.

Upvotes: 0

Views: 12485

Answers (1)

KamilCuk
KamilCuk

Reputation: 140970

From kernel 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.

The preferred way is usually to configure the interrupt with /sys/class/gpio/gpioN/edge and poll(2) for POLLPRI | POLLERR (important it's not POLLIN!) on /sys/class/gpio/gpioN/value. If your process is some "real-time" process that needs to handle the events in real time, consider decreasing it's niceness.

You can even find some example code on github that uses poll, ex. this repo.

Upvotes: 5

Related Questions