libgpiod on Beaglebone AI

432 views
Skip to first unread message

John Allwine

unread,
Mar 27, 2020, 11:33:24 AM3/27/20
to BeagleBoard
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):

echo 106 > /sys/class/gpio/export
cat /sys/class/gpio/gpio106/value 

The last command outputs 1 when the button is not depressed, 0 when it is, as expected. I'm unable to use gpioget to see the same results:

gpioget gpiochip4 10

When I run that, I always get back 0. Any thoughts?





Robert Nelson

unread,
Mar 27, 2020, 11:42:15 AM3/27/20
to Beagle Board
You can use gpioinfo to dump the whole pin list..

sudo gpioinfo

But, 106 = 3*32 +10 - which should be gpiochip3 10, as long as the
gpio's are linear..

You can also run:

sudo /opt/scripts/device/bone/show-pins.pl

Which is nicely documented, only using the legacy method..

Regards,

--
Robert Nelson
https://rcn-ee.com/

John Allwine

unread,
Mar 27, 2020, 11:47:59 AM3/27/20
to BeagleBoard
That was it! gpioget gpiochip3 10 worked.

Thanks Robert!

Drew Fustini

unread,
Mar 27, 2020, 12:46:29 PM3/27/20
to Beagle Board
On Fri, Mar 27, 2020 at 4:48 PM John Allwine <jo...@allwinedesigns.com> wrote:
>
> That was it! gpioget gpiochip3 10 worked.

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.

thanks,
drew

William Hermans

unread,
Mar 27, 2020, 2:52:08 PM3/27/20
to beagl...@googlegroups.com
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. . .

John Allwine

unread,
Mar 27, 2020, 3:45:32 PM3/27/20
to BeagleBoard
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!

Drew Fustini

unread,
Mar 27, 2020, 3:58:21 PM3/27/20
to Beagle Board
On Fri, Mar 27, 2020 at 8:45 PM John Allwine <jo...@allwinedesigns.com> wrote:
>
> 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!

Bartosz explains the differences and improvements that new gpiod
interface provides in this talk:
https://www.youtube.com/watch?v=cdTLewJCL1Y

Essentially, if you need read or set multiple lines, it is faster.
Also, it has an improved way to read events as well.

Slides if you prefer over video:
https://ostconf.com/system/attachments/files/000/001/532/original/Linux_Piter_2018_-_New_GPIO_interface_for_linux_userspace.pdf?1541021776

Mark A. Yoder

unread,
Aug 10, 2020, 10:09:09 AM8/10/20
to BeagleBoard
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.

--Mark

evilwulfie

unread,
Aug 10, 2020, 10:20:10 AM8/10/20
to beagl...@googlegroups.com
software takes time to execute.
--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to the Google Groups "BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/beagleboard/16a18eef-a649-46d9-b126-f774a8eb1522n%40googlegroups.com.

Mark A. Yoder

unread,
Aug 10, 2020, 10:27:08 AM8/10/20
to BeagleBoard
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.

Mark A. Yoder

unread,
Aug 10, 2020, 11:33:55 AM8/10/20
to BeagleBoard
Interesting....   I wrote a c version and the pins are toggle at the exact same time.  Now, how to get gpioset to work correctly.

--Mark

Steve Lentz

unread,
Aug 10, 2020, 11:43:49 AM8/10/20
to beagl...@googlegroups.com
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.  

Mark A. Yoder

unread,
Aug 10, 2020, 11:58:43 AM8/10/20
to BeagleBoard

ToggleTwo.jpg
On my 100MHz 'scope they look the same.  I think it's one instruction toggling the pair.  They are toggling at some 268KHz.

--Mark

Steve Lentz

unread,
Aug 10, 2020, 12:02:45 PM8/10/20
to beagl...@googlegroups.com
Alright then.  Something in the chip is indeed flipping them on the same clock edge.

Dennis Lee Bieber

unread,
Aug 10, 2020, 12:25:03 PM8/10/20
to Beagleboard
On Mon, 10 Aug 2020 07:27:08 -0700 (PDT), in
gmane.comp.hardware.beagleboard.user "Mark A. Yoder"
<mark.a.yoder-Re5J...@public.gmane.org> wrote:

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

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.


--
Dennis L Bieber

Mark A. Yoder

unread,
Aug 10, 2020, 12:58:36 PM8/10/20
to BeagleBoard
I've been looking through gpioset.c, but it's rather involved so I haven't figured it out yet.

Could the python libgpiod be rewritten to use just on call to set the pins so there isn't a delay?

Dennis Lee Bieber

unread,
Aug 10, 2020, 2:19:27 PM8/10/20
to Beagleboard
On Mon, 10 Aug 2020 08:33:55 -0700 (PDT), in
gmane.comp.hardware.beagleboard.user "Mark A. Yoder"
<mark.a.yoder-Re5J...@public.gmane.org> wrote:

>Interesting.... I wrote a c version
><https://github.com/MarkAYoder/BeagleBoard-exercises/blob/master/gpiod/bulk.c> and
>the pins are toggle *at the exact same time*. Now, how to get gpioset to
>work correctly.
>

It doesn't seem to use the same/direct calls... I've tracked it down to
the function at line 661
https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/tree/lib/core.c
and macro definition at line 778
https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/tree/include/gpiod.h
which seems to define a loop operation.


--
Dennis L Bieber

Mark A. Yoder

unread,
Aug 10, 2020, 2:31:46 PM8/10/20
to BeagleBoard
Interesting...  Why go through all the trouble to set bits on a chip by chip basis, and then end up setting them in a loop?

Here are the toggling standings.   
c via sysfs:       3kHz
python via sysfs:  6KHz
c via gpiod:      300KHz

Now to get python via gpiod to work.

--Mark

Dennis Lee Bieber

unread,
Aug 10, 2020, 2:37:36 PM8/10/20
to Beagleboard
On Mon, 10 Aug 2020 09:58:36 -0700 (PDT), in
gmane.comp.hardware.beagleboard.user "Mark A. Yoder"
<mark.a.yoder-Re5J...@public.gmane.org> wrote:

>I've been looking through *gpioset.c*, but it's rather involved so I
>haven't figured it out yet.
>
>Could the python *libgpiod* be rewritten to use just on call to set the
>pins so there isn't a delay?
>

For the most part, the Python library is just a wrapper of the C
library.

The Python gpiod_LineBulk_set_values invokes gpiod_line_set_value_bulk
which, at line 848 of
https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/tree/lib/core.c
operates using a loop.


--
Dennis L Bieber

John Allwine

unread,
Aug 10, 2020, 2:40:06 PM8/10/20
to Beagle Board
How is the toggling rate slower in C than in Python when using sysfs? That seems strange to me.

--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to the Google Groups "BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard...@googlegroups.com.

Mark A. Yoder

unread,
Aug 10, 2020, 2:43:58 PM8/10/20
to BeagleBoard
Well, toggling python using gpiod is around 6.5KHz for one pin and about half that for two.  Which is what you expect since it's looped.

Mark A. Yoder

unread,
Aug 10, 2020, 2:45:32 PM8/10/20
to BeagleBoard

My code is a bit sloppy.  I keep reopening the and closing the file rather than using a lseek().

Using lseek() is about the same speed as the python.

TJF

unread,
Aug 11, 2020, 3:51:02 AM8/11/20
to BeagleBoard
There're two options to control the 32 outputs of a GPIO subsystem:
  1. writes to register GPIO_DATAOUT, or
  2. writes to registers GPIO_SETDATAOUT and GPIO_CLEARDATAOUT
In the first case all pins switch at the exact same time. But there's a downside in controlling all 32 pins at once: it may override changes on lines controlled by other software.

The second option is a convenient way to avoid that overriding. The registers GPIO_SETDATAOUT and GPIO_CLEARDATAOUT can be used to change only the masked pins. As long as only one register is necessary (ie all pins set, or all pins cleared) the change is at the exact same time. In contrast when performing mixed changes (some pins set, others cleared) you'll see a delay between the output changes depending on the L3 latency.

@Mark
In order to testing gpiod you should use mixed changes

while true; do
    gpioset
1 18=0 19=1
    gpioset
1 18=1 19=0
done

Regards

BTW:
Changing multiple pins on the same chip all at once is supported in libpruio since version 0.0 (2014, kernel 3.8).
Reply all
Reply to author
Forward
0 new messages