GPIO in C/C++ on the Beaglebone Black?

Just want to start a discussion. Who all is working or maybe even found a means of controlling the GPIO in C for Beaglebone Black? I have been hunting for a while and haven’t found anything reliable.

I have an almost ready library that interfaces user's application to
the IO pins. It provides mapping mechanism between the user-level
block of bits to an arbitrary set of IO pins, allowing the scattered
IOs to be accessed as a continuous and ordered set of bits.
The last (I hope) issue that prevents me from posting it on github is
denial of access to memory blocks controlling GPIOs 0, 2 and 3.

j.

Jacek,

Great to hear some work is underway. Please post an update as you make more progress. I have been able to access some of the GPIO port 1 pins through dev/mem. I have also had issues with the other GPIO ports as well. I have been trying to use a device tree overlay to set pin modes for the GPIO yet haven’t had any success yet. Such as GPIO0_5, everything I have done to change its pin mode and be able to toggle it on and off hasn’t worked. It would be really great to get access to the large group of GPIO2 pins that are initially configured for the HDMI.

MH

This is a fantastic solution. http://www.youtube.com/watch?v=wui_wU1AeQc

Nice video. The problem is that the overlay itself does not enable
GPIO modules. They start working after exporting through sysfs (as
Derek did). It's a good workaround, but not a solution to the problem
:frowning:

j.

It’s a fine solution if your program or library simply uses sysfs to enable them.

Are you pin muxing without device trees? Then the library won’t work with recent kernels?

Take a look at https://developer.ridgerun.com/wiki/index.php/Gpio-int-test.c

Worked for me.

CEB

I'm not addressing pinmuxing, as it is platform specific. The library
is designed to be platform independent, with beaglebone being only the
first implementation of the interface.
In 3.8 kernels pinmuxing is supposed to be done with device tree and
this is my preferred method of setting the pin modes.

j.

Jacek,

so after some experimenting with the libraries and using sysfs to control the GPIO pins. I have found that this method of toggling gpio pins is extremely slow. It is great for simple applications, yet is really limiting. I think the best case on-off time toggling the pins is about .1 milliseconds on the BBB. How is your library progressing? Is there anything you are particularly stuck with?

Thanks,

Mark

I'm pretty close to having some code ready for release. All what is
left is to get rid of the most obvious bugs, clean up the code a bit,
add simple makefile and I think I will be ready to post it. My current
biggest headache is the crosscompiler. I've been using pre-compiled
g++ from Angstrom, but it adds some memory leaks to the compiled
programs. Running valgrind on a trivial cross-compiled "Hello world"
shows big allocation and memory corruption problems localized
somewhere around main(). The same code compiled natively on beaglebone
passes all the checks. I'm building right now new cross-toolchain with
angstrom and I hope it will work better and will fix most of the
memory-related problems I was observing.
I will definitely need testers, so I'll post information to the list
as soon as the library will be ready for download.

j.

You’ll want to use a library that uses mmap. This should get you around 5MHz.

https://www.google.com/search?q=mmap+gpio+beaglebone

Most of the libraries from that search will be for the 3.2 kernel, but since arbitrary pin muxing on the fly isn’t really supported anymore, you could pull the mux routines out and use them for basic toggling and reading.

I wrapped the code up and posted the library on github. It is more of
a framework, which allows to write applications that can be easily
ported between different platforms. The GPIO access is just a small
part of the library.
Currently I have only implementation for Beaglebone, but RPI port
should be trivial to make. I'm also thinking about a version for
Cortex MCUs.
Please check out, clone and comment at https://github.com/piranha32/IOoo

j.

Very nice. I’ll have to give this a test on my BBB soon. I knew that if I just went back to the milling machine and lathe for a while to make more robot parts the GPIO situation would start sorting itself out. I started my own library project but honestly, I’m sure I’m going to be beat to the punch on this. Thanks for the effort and keeping the project rolling. If there are things we need to contribute please let us know!

All,

I asked Jacek about problems on the pinmuxing, but didn’t post my question to everyone (sorry). Thanks Jacek so much for your explanation. Really helps noobs like myself.

Here’s his response to my question as to how to workaround the overlay with pinmuxing issue:

For GPIOs 0,2 and 3 clocks are not enabled when you load an overlay
with pinmuxing and every access to the registers of these modules
results in a bus error. The workaround for this problem is to export
one pin from each module through sysfs. There was last month a
discussion on the group about this problem:
https://groups.google.com/d/msg/beagleboard/OYFp4EXawiI/61Zwn2Z5REgJ
I included with the library a script which enables all modules. Just
run tools/bbb_enable_gpio.sh and the bus error will be gone until next
reboot. There is no need to run this script before each run of your
program.

j.

Hello Jacek,

Looks like a great solution, but I don’t understand the problem I’m seeing.
Everything looks like it works until the first memory write to a GPIO
register. I have a BeagleBone Black rev A5 running latest Angstrom demo
build (June 17th 2013 build from website). When I run the gpio_leds example
in the IOoo package, I get a “non-linefetch” fault (output highlighted in
RED below) that happens on the mmap call for GPIO[0]. However, the other 3
mappings succeed and I see that the BeagleGoo says it is successfully
activated.

The program then runs through the rest of the initialization and then
terminates with a “Bus Error” which I traced to line 140 of BeagleGooP.cpp
when the first GPIO[0] port OE register is written:

140: parent->gpios[ports[i]][GPIO_
OE_REG / 4] &= ~masks[i];

I hope it solved the problem :slight_smile:

j.

Jacek,

That did the trick. Just played for an hour characterizing the response latency in the write function on an oscilloscope. Very cool. Thanks again for your help.

Regards,

Scott Rush

After reading Bad to the Bone, I have toask why is it that in BoneScript (Node.js) you can access the pins by:

Var pins = (typeof bone != 'undefined') ? bone : b.bone.pins;
var ledPin = pins.P8_13;
var ledPin2 = pins.USR3;
b.pinMode(ledPin, b.OUTPUT);
b.pinMode(ledPin2, b.OUTPUT);

ETC

b.diitalWrite(ledPin, b.LOW)

ETC

And in C/C++ one has to open two files for each pin nested down several levels from root???

Makes no sense!!!

Because in your JS program you're taking advantage of a library which
abstracts access to GPIO, while in C/C++ you want to implement it from
scratch. You can also use one of the existing libraries for C/C++,
<autopromo> for example this one: https://github.com/piranha32/IOoo
</autopromo>

j.

Jacek,

I appreciate your response. However, I’ve never had to open files to write to the pins of a controller or computer. This is a first for me; and may I say, I find it a very inefficient method which leaves room for many errors. Furthermore, if you have to interact with the OS to read or write to a file system, it slows the system down by several orders of magnitude. I never had to work with a file to write to an output pin on a PC, PIC Microcontroller, AVR, Arduino, (old Sinclar 1000) etc… If TI wants this development board (computer) to be a viable development platform, they need to provide a more efficient manner in addressing GPIO pins directly from within the processor. Whether that is via inline assembly, a standard library, C++ data structures that facilitate ‘.’ access to the elements and methods, etc. I stress, this needs to work within the embedded ARM processor and not through the OS file system. How many machine instructions/cycles are wasted telling the ARM to:

Open a file;
fseek…
analyze the data
fwrite…
fflush…
fclose…

And then, the processor has to go to the file system to open the file, read the data the programmer just set, and then set/write/read to/from the pin…

All the while, the ARM processor has to have assembler code that directly: 1. Reads/Sets the pin mode–to include data direction, pull-up/down resistor, etc., 2. Reads the pin value, 3. Writes a value to the pin.

The file interface has been initially provided in the kernel for
debugging. IIRC in 3.2 kernels it even resided in debug subdirectory.
Accessing GPIO via file interface is very simple from user's point of
view and makes experimenting much easier, so it quickly become very
popular. There are many GPIO libraries which are just wrappers for the
file I/O. I think that the JS library also uses the file interface.
GPIOs are also accessible through memory interface, however it is not
as simple and intuitive as writing 1 or 0 to a file. If you take a
look at the link, you will see that there are no fopens, fseeks,
freads and fwrites, but pure black magic of mmap, memory offsets and
bit shifts.

j.