May 23, 2013

GPIO access from a C program

I originally wrote this section when I had made it my goal to write a C program that would blink one of the four user LED's on a beaglebone black. We are well aware than on a linux system, code that we write will run in user space and need to talk to hardware through device drivers. We don't want to write drivers ourselves, but want to learn what drivers have already been written and what API they expose to us.

I never have reached the goal of writing a C program to blink an LED. In the process of researching the GPIO interface, I was somewhat disgusted by what I found and realized that programming in C offers no particular advantage.

It turns out that it is easy (although hardly sophisticated or efficient) to control GPIO bits by writing to special files. It is just as easy to do this from a bash script (or any scripting language you might choose) as it is to do from C. In other words, a C program offers no performance advantage, and is significantly more effort to write. For this reason the rest of this page documents how to turn an LED on or off from the command line.

Apparently a generic GPIO specification has been written (by Linux Torvalds) for linux that is the "inspiration" for the scheme that will soon be described.

Obviously there is a huge amount of overhead using writes to files to control PIO bits. However, it is worth reading further -- there are timer modes built into the GPIO driver that can be used to do some interesting things, perhaps in real time.

See the links below, some folks have used mmap() to map the GPIO registers into user space.

GPIO access via the filesystem

The following links are instructive:

The BBB has four surface mount LED's soldered onto the PCB as follows:

There is a directory full of special files for each LED:
ls /sys/class/leds
beaglebone:green:usr0
beaglebone:green:usr1
beaglebone:green:usr2
beaglebone:green:usr3
Just for the record, the above are all links, as follows:
ls -l /sys/class/leds
lrwxrwxrwx 1 root root 0 Jan  1  2000 beaglebone:green:usr0 -> ../../devices/ocp.2/gpio-leds.7/leds/beaglebone:green:usr0
lrwxrwxrwx 1 root root 0 Jan  1  2000 beaglebone:green:usr1 -> ../../devices/ocp.2/gpio-leds.7/leds/beaglebone:green:usr1
lrwxrwxrwx 1 root root 0 Jan  1  2000 beaglebone:green:usr2 -> ../../devices/ocp.2/gpio-leds.7/leds/beaglebone:green:usr2
lrwxrwxrwx 1 root root 0 Jan  1  2000 beaglebone:green:usr3 -> ../../devices/ocp.2/gpio-leds.7/leds/beaglebone:green:usr3
Each of these is (amazingly) a directory containing:
-rw-r--r-- 1 root root 4096 May 23 17:16 brightness
lrwxrwxrwx 1 root root    0 May 23 17:16 device -> ../../../gpio-leds.7
-r--r--r-- 1 root root 4096 May 23 17:16 max_brightness
drwxr-xr-x 2 root root    0 May 23 17:16 power
lrwxrwxrwx 1 root root    0 May 23 17:16 subsystem -> ../../../../../class/leds
-rw-r--r-- 1 root root 4096 May 23 17:16 trigger
-rw-r--r-- 1 root root 4096 Jan  1  2000 uevent
And we can see what "mode" the light is in (USR0 is in heartbeat mode):
cat trigger
none nand-disk mmc0 mmc1 timer oneshot [heartbeat] backlight gpio cpu0 default-on transient 
To control a light by hand, this will do:
echo none >trigger
echo 1 >brightness
echo 0 >brightness
And here is something interesting, put the led into timer mode and two new "files" miraculously appear (delay_on and delay_off), you can set up a timer using these:
cd /sys/class/leds/beaglebone:green:usr2
echo timer >trigger
ls
brightness  delay_off  delay_on  device  max_brightness  power	subsystem  trigger  uevent
echo 100 >delay_on
echo 400 >delay_off

I am not clear which of the following modules (if any) are handling the calls to these special files.

beaglebone:/proc# lsmod
Module                  Size  Used by
g_multi                55953  0 
libcomposite           15260  1 g_multi
ip_tables               8318  0 
x_tables               15096  1 ip_tables
rfcomm                 25134  0 
ircomm_tty             14531  0 
ircomm                  8874  1 ircomm_tty
irda                   90018  2 ircomm_tty,ircomm
ipv6                  229821  12 
hidp                   10136  0 
bluetooth             146108  4 hidp,rfcomm
rfkill                 16550  2 bluetooth
autofs4                17456  2 

Feedback? Questions? Drop me a line!

Tom's Computer Info / tom@mmto.org