Using arbitrary GPIO pins
Bela provides 16 digital I/O channels, which are sampled synchronously to the audio and can be easily written, read or tri-stated with a precision of ~22microseconds. However, for some uses you may want to access some of the GPIO pins directly from your program, without having them sampled automatically by the Bela real-time core. Example use cases:
- accurate, minimally invasive measurements of CPU time for specific blocks of code: simply toggle a pin before and after the section you want to measure and monitor it with an external oscilloscope
- performing non-time-critical digital I/O (e.g.: reading buttons or driving LEDs) when you need more than the 16 I/Os provided by the Bela core.
- manually driving the on-board LEDs for BelaMini (requires running with
Finding an available pin
Most pins of the BeagleBone or the PocketBeagle can perform different functions. The one function that is currently enabled depends on the pinmuxer (pin-multiplexer) controller. In order for a pin to work as a GPIO, you will have to make sure that the pinmuxer settings for the corresponding pin are in mode 7 (GPIO). Note that any of the pins normally used by Bela for digital I/O are already correctly configured as GPIO, but you will not be able to use them with the method below while Bela is running with digital enabled. However, you can disable the digital I/O in Bela (this is achieved by unticking the tickbox "Use digital" in the IDE, or equivalently, if you are using the command line, use the
-G 0 flag) and safely access those pins for your own use while a Bela program is running (so you can skip the steps below and jump to "Using a GPIO pin" below).
Whatever you do, make sure you do not use any of the other pins used by Bela (these are highlighted in the documents below).
In order to proceed, you will need the pinmuxer address (ADDR) and the GPIO number. How to retrieve these varies depending on the board you have:
Here is a list of the pins on the BeagleBone and the pins used by Bela. diagram (P8, P9).
Pick a pin that is not in use by Bela and look up the GPIO number in the corresponding column and the pinmuxer address in the ADDR/OFFSET column. The ADDR value starts with 8 or 9 (remove the leading
0x when using this value below).
The PocketBeagle does not have a nice and exhaustive list as the BeagleBone. You will first have to look at the BelaMini pinout and identify an available pin that can work as a GPIO. Once you identify your desired pin, search for the pin name(e.g.: P1.31) in this (hard to parse) page. From the column containing the pin name, look for the value of the "Control register" and "Mux mode 7" lines.
We will call the "Control register" value "ADDR" from now on. The "Mux mode 7" line should look something like
To find out the GPIO number(in order to access it with your code), you will need to get the value of the expression
x * 32 + yy. For instance,
P1.31 has ADDR =
9A0 and the Mux mode 7 value is
gpio 3.18, therefore the gpio number is
3 * 32 + 18, that is 114 (this should match the number in the BelaMini pinout).
Once you have the
ADDR value you can check what is the current pinmuxer setting for that pin (e.g.: for
P9_11 on the BeagleBone, it is
0x870) and then running on the board:
grep 870 $PINS
this will return a line like the following
pin 28 (44e10870.0) 00000027 pinctrl-single
which denotes that the pin is in mode
27, which corresponds to GPIO, receiver enabled, pulldown (see notes at the bottom of the pin diagram files above), so you are good to go.
If the pin is not set as a GPIO (and it is not used by Bela), then you can set it to GPIO by using the
config-pin utility or loading an appropriate device tree overlay.
Accessing a pin
From the command line
The Linux driver makes the GPIO chip available at
/sys/class/gpio/. Here you can use commands such as:
echo $GPIO_NUMBER > /sys/class/gpio/export echo out > /sys/class/gpio/gpio$GPIO_NUMBER/direction echo 1 > /sys/class/gpio/gpio$GPIO_NUMBER/value
There are plenty of tutorials available online for using the sysfs interface.
For proper, safe (and slow!!), access through the kernel you can use the kernel drivers sysfs interface, using the functions declared in
https://github.com/BelaPlatform/Bela/blob/master/include/GPIOcontrol.h and implemented in
https://github.com/BelaPlatform/Bela/blob/master/core/GPIOcontrol.cpp. You may want to use these in case yo have multiple processes accessing the same GPIO pins.
For accurate, fast, real-time safe access, you will instead want to use the methods of the
Gpio class. Just
#include Gpio.h and go for it. This class uses memory-mapped Gpios for real-time performance, without going through the Linux kernel. For en examples of its use, check out 02-Digital/synchronous-gpio.