GPIO poll for interrupts fails

Any help would be appreciated. I’ve Googled, studied, and stared for many hours.
Problem: Using poll to watch a GPIO pin for change, poll returns “immediately” and persistently, with no value change, with POLLPRI set.
Background: This is a prep stage for implementing a software encoder counter where 2 GPIOs are connected to an external rotary encoder with leads A and B. I am working on a user space quadrature encoder routine based on the Linux driver rotary_encoder.c logic. It didn’t work and I traced it to failing to respond to the GPIO edge events using poll. I made a single GPIO interrupt response demonstrator (shown excerpted below) and it doesn’t work either. Further, it doesn’t work on either Beaglebone Blue or Raspberry Pi 3.
Hardware: The Blue shows ’ uname -a
Linux blue1 4.19.94-ti-r42 #1buster SMP PREEMPT Tue Mar 31 19:38:29 UTC 2020 armv7l GNU/Linux’
The RPi shows ’ uname -a
Linux raspberrypi 4.19.93-v7+ #1290 SMP Fri Jan 10 16:39:50 GMT 2020 armv7l GNU/Linux’
Both have the same wheel encoders (Pololu Romi encoders item #3542 or its 2.7v version). Both bots will correctly read the encoders. The Blue using the hardware encoder and the RPi via the software driver rotary-encoder. For this demonstrator, the Blue uses other GPIOs, specifically GP0.3 and GP0.4. Signal changes on these GPIOs are read correctly in the gpioN/value register via manual testing. The RPi uses the same GPIOs (2 or 3) as the encoder driver, but with the driver disabled to eliminate the competition.
Furthermore: This has been a long standing software challenge. Googling shows many things one needs to know. GPIOs in sysFS are deprecated, but they still work. Setting an edge is what enables polling on the value to pick up the transition. Initial reads are required to clear initial spurious values. sysFS requires POLLPRI events, since POLLIN always returns for sysFS. sysFS always returns POLLERR which can be ignored. One must LSEEK on the value fd before reading the value. One must read the value, wanted or not.
Notes on the demonstrator code: I have been working on a common hardware interface module to support bots built on Blue and RPi. I have long been following StrawsonDesign’s librobotcontrol. This code uses a few routines from Strawson. One is a function to tell whether the hardware is Beaglebone or RPI and another to launch a thread. I don’t show them here. I have elided all the error handling snippets, replacing them with “gripe” comments.
The program follows the StrawsonDesign librobotcontrol rc_test examples. In this case, the main checks inputs, sets up hardware, launches a worker thread, then waits for the user to quit via Ctrl-C. Here the worker thread sets up a repeated poll loop. In the eventual quadrature application, the GPIO events feed the quadrature state machine of rotary-encoder.c. A short timeout is set for my use so the thread can be readily killed by the main application, independent of GPIO arrivals. The version here leaves the GPIOs set up upon completion so we can inspect the state of things. The Blue has pinmux helpers for the user GPIOs on GP0 and GP1 which are used to set them to GPIO mode. The RPi doesn’t do that. Apparently user GPIOS are pre-set up.
The code produces the same result on both machines. The read after poll always fails with return -1. The event is 0x0a which is POLLPRI | POLLERR. While it does stream fast, I can never see a response to manually fiddling with the physical inputs. It never reports time out.
OBTW, if you can see into what is going on here, think about how this works when I switch to SCHED_FIFO. All my bot threads run in this ‘realtime’ mode. For a software encoder that responds to GPIO interrupts, I think this doesn’t present any problem that isn’t already presented by all the other threads. On RPi, tho, the kernel catches the GPIO interrupts and runs the quadrature logic, only letting the user’s poll get control after a complete turn of +1 or -1 occurs. I presume the rotary-encoder driver runs at kernel priority level, which is below the worker thread. At least, if my app consumes too much CPU, the kernel can’t keep with its many functions, one of which is this driver. I have done that in the past. Let’s get this code to work, then I’d like help thinking through this and its impact on CPUs like Blue and RPi. Because I’m getting lots of input about the CPU load of a software rotary encoder.
So, needless to say, I don’t get it. I hope someone can see what I’m missing. I need to get past this and get back to making bots go.



  • @excerpts from my_test_gpio_interrupts.c
  • as of 19 June 2020

Any help would be appreciated. I’ve Googled, studied, and stared for many hours.
Problem: Using poll to watch a GPIO pin for change, poll returns “immediately” and persistently, with no value change, with POLLPRI set.

Please consider using libgpiod.

Good input. Out of respect for your big picture view point, it is in progress.
librobotcontrol currently uses chardev ioctl. I got that working for my simple single interrupt response demonstrator since he has all that worked out. Then I went on to gpiod and I think I have gpiod working in that simple single gpio interrupt test environment. For Blue.

StrawsonDesign & the resulting librobotcontrol has used sysFS for access to non-gpio stuff, specifically pwms. What do you see for such other non-gpio stuff in sysFS?
My original submission here included an argument for doing this task with RPis too. The code base using any of the three gpio access methods seems to work on RPi. The gpio configuration environment in Raspbian is quite different however. They specifically don’t expose pinmux functionality. I still struggle with how in the heck that community deals with gpio configurating. The mode map is well exposed, but how to take advantage of it isn’t. What physical header pin does what in what mode is well documented, but how to set things up for that mode isn’t. I find that commandeering pins by enabling kernel drivers works. I can pick pins for the software rotary-encoder driver in the boot config and apparently get them. Same with the pwm driver. There isn’t such a mechanism for free gpio pins to use for exercises such as the simple gpio interrupt response demonstrator.
You and others in BB territory may not have much interest in figuring out the RPi equivalent to the (wonderful, highly functional, really nice) Beaglebone environment unless we adopt my proposed make-it-do-both approach. The alternative of asking the RPi community doesn’t appear to be promising because they focus on so many other IoT applicatios and are not pursing bots in any similar fashion.

BeagleBoard might well not be interested, but a number of potential university adoptors of BB appear to be. Our friends at UCSD seem to. And his efforts to export to other universities has found professors with a pre-existing base in RPis. Where I am now, we are struggling with focussing on one or hedging our bets with the two.

What guidance would you provide on this front?