Channels ▼

Al Williams

Dr. Dobb's Bloggers

Beagle I/O

May 29, 2012

Last time I wrote about the BeagleBone, a simple and inexpensive ARM Cortex-A8 development board that can run (among other things) Linux. Being Linux based, you don't have to worry about a lot of things you would when you are programming close to the "bare metal." For example, Ethernet, serial ports, USB, and the like just work, which is really very productive.

On the other hand, some devices aren't part of a normal desktop Linux OS. Luckily, the Angstrom distribution I mentioned last time even has drivers for these special devices (actually, the standard gpio-sysfs drivers). For example, consider general-purpose I/O ports. The BeagleBone can support up to 66 3.3V input/output pins. The board has 4 pins (GPIO1_21 to GPIO1_24) connected to LEDs. Well, connected to transistors that turn on LEDs. If you output a high, the LED turns on.

Turns out, there is already a device driver that handles the LEDs, but I am more interested in general-purpose I/O. The first step is to stop that and make the LEDs obey the state of the general-purpose I/O lines and release the leds-gpio driver. From a shell running on the BeagleBone, try this:

root@beaglebone:/sys/bus/platform/drivers/leds-gpio# echo leds-gpio >unbind 

Even though the drivers make it easy to deal with I/O, you also have to account for the multiplexed nature of the pins (that is, each pin can have many different functions). Luckily, there is a driver for the system multiplexer too. The real trick is figuring out what's what, since the BeagleBone documentation is a little disorganized.

One idea is to go to the source: the TI AM3359 technical reference manual. On page 4183 (no, that's not a typo), you'll find a description of the GPIO ports. Note that there are several GPIO units (we are interested in unit 1) and each has 32 pins. However, the BeagleBone will call the ports by number starting with GPIO0_0 as pin 0 and GPIO1_0 as 32. In general, the formula is unit_number*32+pin, so for the first LED pin, the port number is 32*1+21=53. Although there is a lot of good information in the reference manual, it isn't clear (in that section) which other things share a pin with the GPIO ports in question. For that you need the datasheet (which you can download at the same link).

From the datasheet (page 22 on the version I'm reading), you can find a table which shows that gpio1_21 shares a pin with gpmc_a5, gmii2_txd0, and a bunch of other signals. All the gpio1 ports are in "mode 7" and that's the information you need to know. As you'd expect, gpmc_a6 shares with gpio1_22, and so on. The driver will tell you all you need to know if you know that name. Here's a shell running on my BeagleBone (note the working directory):

root@beaglebone:/sys/kernel/debug/omap_mux# cat gpmc_a5
name: gpmc_a5.gpio1_21 (0x44e10854/0x854 = 0x0007), b NA, t NA
mode: OMAP_PIN_OUTPUT | OMAP_MUX_MODE7
signals: gpmc_a5 | mii2_txd0 | rgmii2_td0 | rmii2_txd0 | gpmc_a21 | NA | NA | gpio1_21

In this case, the pin is already set to mode 7 and it is also set as an output. You probably don't want to count on that, though. So:

root@beaglebone:/sys/kernel/debug/omap_mux# echo 7>gpmc_a5

That sets mode 7. You'd want to do that for all four pins (or, at least, the pins you plan to use).

The driver for the GPIO system doesn't show you all the possible pins, only the ones you "export" like this (note the directory change): root@beaglebone:/sys/class/gpio# echo 53 >export

Remember that 53 is actually GPIO1_21. Also note there is a space between 53 and the redirect operator. Things don't work without the space!

Now there is a directory called gpio53:

root@beaglebone:/sys/class/gpio# ls gpio53
active_low  direction  edge  power  subsystem  uevent  value

You can probably guess what at least some of these pseudo files do. The one of main interest here is "direction", which allows you to set the pin as an input or an output and set the output. Writing "low" to this file will set the pin to an output in the low state (as will writing "out"). You might guess that "high" will set the pin high (and thus light the LED). Writing "in" would turn the pin to an input, which isn't very useful for an LED. So:

root@beaglebone:/sys/class/gpio# echo high >gpio53/direction 
root@beaglebone:/sys/class/gpio# echo low >gpio53/direction 
root@beaglebone:/sys/class/gpio# echo 53 >unexport 
root@beaglebone:/sys/class/gpio# ls
export  gpiochip0  gpiochip32  gpiochip64  gpiochip96  unexport

Obviously, you don't want to unexport until you are done. You could use ports 54, 55, and 56 to control the other LEDS. In summary:

  • Unbind the leds-gpio driver so you can control the LEDs like regular ports
  • Ensure the system mux is set correctly (since the leds-gpio driver did this already, it is a safe bet for the LEDs, but not so safe for other I/O pins)
  • Ask the gpio driver to export the pins of interest
  • Manipulate the pins through the direction device file
  • Ask the driver to unexport the pins when done

Of course, if you really wanted to just use the LEDs, you could skip the unbind and use the leds-gpio driver directly. If you examine the /sys/class/leds directory, you'll easily see how it works (pay attention to the trigger and brightness device files).

Similar devices exist for other devices, like PWM. The nice thing about these being exposed as files is you can access them from almost any kind of programming language — even the shell as I did here and, of course, languages like C or Python. The disadvantage, of course, is you lose some potential performance. But if you were really trying to push the performance envelope, you are probably going to be using a different operating system to begin with.

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 


Video