I’m looking into using libgpiod to control the GPIO on the Beaglebone AI in user space. I’m starting small and trying to use the included command line tools gpioget and gpioset, but not having any success.
The Beaglebone AI System Manual lists what looks like the gpio chip and line under pinmux mode 14. P8.19 looks to be gpiochip4 line 10. Am I reading that right?
I have P8.19 configured in a device tree overlay to be an INPUT_PULLUP, pinmuxed to mode 14. I have a button wired up to P8.19, which shorts it to GND. I have verified that the button works using sysfs P8.19 GPIO number is 106, also listed in the same table from the system manual):
It would be interesting to know if libgpiod proves fast enough for
your application. It has C++ and Python bindings that allow you to
set and get multiple lines on a gpiochip with a single ioctl().
I am in communication with Bartosz, who made the libgpiod userspace
library and utilities, and Linus Walleij who created the gpiod
interface (which includes the gpiochip character devices). They both
seem open minded to improving interfaces to address real-world use
cases.
Personally. I think trying to toggle a GPIO as fast as possible in Linux is the wrong way to go about it. According to what I’ve read(and I have no personal desire to test it). An empty ioctl() has 63ns latency. Add that on top of gpiod’s time. Then it starts to add up. Not to mention: how proficient a given developer is when writing performant code.
So, for doing anything blazing fast, we’re back full circle. However, I think it would be better to use/buy hardware specialized for the task at hand. With that said, there is nothing wrong with experimenting. Until you let the blue smoke out. . .
I don’t intend to toggle a GPIO as fast as possible (except to test), but from a performance standpoint that demonstration seemed to indicate that there are issues with sysfs. Hopefully, libgpiod will prove to be better!
I’m starting to play with gpiod on a Beaglebone Black. One of the advantages of gpiod is you can toggle multiple pins on the same chip all at once.
So I try:
while true; do
gpioset 1 18=0 19=0
gpioset 1 18=1 19=1
done
This is toggling pins P9_14 and P9_16. I expect to see the two pins toggle on at the same time, but what I get is
a 4 microsecond delay from P9_14 switching and P9_16 switching.
Should there be such a long delay? I’d expect the two to switch at the same time (which is what happens when toggle pins via the PRU).
I do the same experiment with python and I see a 70 us delay.
Yes, but the hardware on the am335x can toggle multiple pins on the same chip in the same clock cycle. Seems like the software should be able to support it.
It’s unlikely to be exactly the same time, it’s just within some undefined margin for error. Compiled C code can get the two pins set within a small number of 1 GHz clocks. With a fast enough scope, you’’ll probably find at least a few ns difference, if this isn’t obscured by parasitic capacitance in the traces and wiring. Sure, this is a 3 orders of magnitude less than gpiod, but there are folks out there working in femtoseconds for whom a nanosecond would be far too long. Time is a very stretchy thing.
You could always look at the source code for libgpiod.
https://github.com/brgl/libgpiod/
"""
libgpiod - C library and tools for interacting with the linux GPIO
character device (gpiod stands for GPIO device)
Since linux 4.8 the GPIO sysfs interface is deprecated. User space should
use the character device instead. This library encapsulates the ioctl calls
and data structures behind a straightforward API.
"""
However, to save some time -- from what I can tell, while the library
consolidates multiple pins (lines) per controller chip, it then passes that
on to a kernel call. I've not located the source (kernel) for that level.
If it is somewhat generalized, it may be coded to handle hardware that can
only get/set one line at a time -- even if the actual hardware allows
parallel access.