简体   繁体   中英

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 :

  • Linux on an embedded platform (CPU @~500MHz)
  • One team working on the single userspace software
  • One team working on Linux + driver + uboot etc.

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM