Using BeagleBone Black GPIOs

To control digital input / outputs for the BeagleBone Black, you can use the facilities exposed by the kernel in the /sys/class/gpio directory. Note that the BeagleBone White pinouts are different from the BeagleBone Black. Also note that the GPIOs available on the BBW have changed between revisions, so be certain to get the proper technical reference manual for your actual board revision.

After boot, nothing is exported for use, but we do see the four GPIO controllers (gpio0, gpio1, gpio2, and gpio3):

# ls -al /sys/class/gpio
total 0
drwxr-xr-x  2 root root    0 May 26 15:40 .
drwxr-xr-x 45 root root    0 Jan  1  2000 ..
--w-------  1 root root 4096 May 26 15:48 export
lrwxrwxrwx  1 root root    0 May 26 15:45 gpiochip0 -> ../../devices/virtual/gpio/gpiochip0
lrwxrwxrwx  1 root root    0 May 26 15:45 gpiochip32 -> ../../devices/virtual/gpio/gpiochip32
lrwxrwxrwx  1 root root    0 May 26 15:45 gpiochip64 -> ../../devices/virtual/gpio/gpiochip64
lrwxrwxrwx  1 root root    0 May 26 15:45 gpiochip96 -> ../../devices/virtual/gpio/gpiochip96
--w-------  1 root root 4096 May 26 15:45 unexport

Note that each GPIO controller is offset by 32 from the previous (0, 32, 64, 96) — more on this later.

Not all GPIO pins are available by default. A lot of frustration may come from not knowing this — sometimes when it appears that all should be working, it does not. The microcontroller needs to be reconfigured to enable some of the pin modes. To understand what may be available, you need to study table 10 on page 70 for the P8 header and table 11 on page 72 for the P9 header in the BeagleBone Black System Reference Manual. Pay close attention to which header is P8 and which is P9 (page 68) because they feel backwards to me.

In this example, I will export P9 header GPIO pins 12, 14, 15, 16. Referencing page 72 mode 7 column, it shows pin 12 to be gpio1[28], pin 14 to be gpio1[18], pin 15 to be gpio1[16], pin 16 to be gpio1[19]. All of these pins are on the gpio1 controller (gpiochip32). To get to the GPIO number that should be exported from the kernel, we must add on 32 to each GPIO (64 for gpio2, and 96 for gpio3). Therefore gpio1[28] = 32 + 28 = 60. I will just do all the math here and we will refer to them by the kernel nomenclature and stop with the gpio1[x] business as it gets confusing.

pin 12 --> gpio60
pin 14 --> gpio50
pin 15 --> gpio48
pin 16 --> gpio51

Now that we have a relationship between the P9 header physical pins and what the kernel is calling them, we can begin configuration. To make this example easy to follow, I am just going to use bash scripts, but all of the same principles apply to the file manipulation APIs in your favorite language.

In this example, we will be configuring all four pins to be digital outputs. To do so, we need to copy the gpio number we want to export into the kernel gpiolib /sys/class/gpio/export file.

echo 48 > /sys/class/gpio/export
echo 50 > /sys/class/gpio/export
echo 51 > /sys/class/gpio/export
echo 60 > /sys/class/gpio/export

Afterward we can see there are four new subdirectories for each of the gpios:

# ls -al /sys/class/gpio
total 0
drwxr-xr-x 2 root root    0 May 26 15:40 ./
drwxr-xr-x 45 root root   0 Jan  1  2000 ../
--w------- 1 root root 4096 May 26 16:25 export
lrwxrwxrwx 1 root root    0 May 26 16:25 gpio48 -> ../../devices/virtual/gpio/gpio48/
lrwxrwxrwx 1 root root    0 May 26 16:25 gpio50 -> ../../devices/virtual/gpio/gpio50/
lrwxrwxrwx 1 root root    0 May 26 16:25 gpio51 -> ../../devices/virtual/gpio/gpio51/
lrwxrwxrwx 1 root root    0 May 26 16:25 gpio60 -> ../../devices/virtual/gpio/gpio60/
lrwxrwxrwx 1 root root    0 May 26 15:45 gpiochip0 -> ../../devices/virtual/gpio/gpiochip0/
lrwxrwxrwx 1 root root    0 May 26 15:45 gpiochip32 -> ../../devices/virtual/gpio/gpiochip32/
lrwxrwxrwx 1 root root    0 May 26 15:45 gpiochip64 -> ../../devices/virtual/gpio/gpiochip64/
lrwxrwxrwx 1 root root    0 May 26 15:45 gpiochip96 -> ../../devices/virtual/gpio/gpiochip96/
--w------- 1 root root 4096 May 26 15:45 unexport

And the contents of one of the gpio subdirectories:

# ls -alH /sys/class/gpio/gpio48
total 0
drwxr-xr-x  3 root root    0 May 26 16:25 .
drwxr-xr-x 10 root root    0 May 26 15:45 ..
-rw-r--r--  1 root root 4096 May 26 16:29 active_low
-rw-r--r--  1 root root 4096 May 26 16:29 direction
-rw-r--r--  1 root root 4096 May 26 16:29 edge
drwxr-xr-x  2 root root    0 May 26 16:29 power
lrwxrwxrwx  1 root root    0 May 26 16:25 subsystem -> ../../../../class/gpio
-rw-r--r--  1 root root 4096 May 26 16:25 uevent
-rw-r--r--  1 root root 4096 May 26 16:29 value

There are several configuration options available to each gpio. I suggest you read the Linux GPIO Interfaces manual for all of the details. I am only covering the basics here, and the Linux GPIO Interfaces manual is a very important read to understanding Linux gpio control.

Next we must specify if the exported gpio is input or output. It does not make sense to configure anything else ahead of this and as far as I know, the kernel doesn’t let you do anything else with it until you set the gpio as input or output.

To set a gpio as output, we set its direction as in or out. For outputs there is an alternative nomenclature where output direction can be set instead as high or low to help with glitch free operation. I’ll use this nomenclature:

echo high > /sys/class/gpio/gpio48/direction
echo high > /sys/class/gpio/gpio50/direction
echo high > /sys/class/gpio/gpio51/direction
echo high > /sys/class/gpio/gpio60/direction

Pins 12, 14, 15, 16 are now configured as outputs and are currently high — these pins will now be reading 3.3v. Do not use 5v TTL logic parts or you will damage the board.

Finally, we will set the pins low which will depower them:

echo 0 > /sys/class/gpio/gpio48/value
echo 0 > /sys/class/gpio/gpio50/value
echo 0 > /sys/class/gpio/gpio51/value
echo 0 > /sys/class/gpio/gpio60/value

Putting this all together, this script will configure and run a binary counter that will overflow and start at zero again. It is kind of cool to watch if you hook relays up to the board.

#!/bin/bash -e

if [ ! -d /sys/class/gpio/gpio48 ]; then echo 48 > /sys/class/gpio/export; fi
if [ ! -d /sys/class/gpio/gpio50 ]; then echo 50 > /sys/class/gpio/export; fi
if [ ! -d /sys/class/gpio/gpio51 ]; then echo 51 > /sys/class/gpio/export; fi
if [ ! -d /sys/class/gpio/gpio60 ]; then echo 60 > /sys/class/gpio/export; fi

echo low > /sys/class/gpio/gpio48/direction
echo low > /sys/class/gpio/gpio50/direction
echo low > /sys/class/gpio/gpio51/direction
echo low > /sys/class/gpio/gpio60/direction

for (( i=0 ; ; ++i ))
   if (( i > 0x0f )); then
      printf '\n[press  + c to stop]\n\n'

   bit0=$(( (i & 0x01) > 0 ))
   bit1=$(( (i & 0x02) > 0 ))
   bit2=$(( (i & 0x04) > 0 ))
   bit3=$(( (i & 0x08) > 0 ))
   echo $bit3 $bit2 $bit1 $bit0

   echo $bit0 > /sys/class/gpio/gpio60/value
   echo $bit1 > /sys/class/gpio/gpio50/value
   echo $bit2 > /sys/class/gpio/gpio48/value
   echo $bit3 > /sys/class/gpio/gpio51/value

   sleep .2


The Script in Action

Posted in BeagleBone Black, HowTo
  • Simon Bella

    hi John

    You are marvelous with your adept knowledge and have been most helpful shedding some light on these issues. Thank you so much for taking the time to provide these tutorials and insightful details – I am sure you have helped many beginners like me from pulling their hair out?
    I have pgio access now and will experiment with the other classes to see what’s available – I still cannot see what class to use to read the analog inputs, but I am sure they are there?

    Also since I am using the ubuntu 13.04 minimal image and not using hdmi – I assume I can use the available gpio for my own applications? I notice that some gpio don’t seem to work at all – maybe because some other hardware is using them – e.g. cannot read gpio117 [gpio_21] as a high level even when applying 3.3V to its pin – but gpio115 [gpio_19] is OK? – I will confirm what is used from a schematic of the BBB?

    Thanks again – Simon Bella

  • armhf

    How many GPIOs are you wanting to use? I have also confirmed that the P8 header pins 7, 8, 9, and 10 are free. I’ll write an article on using the analog inputs. Here is a script that will read the value of analog input A5 (pin 36) and print it to the console. Be careful you don’t supply more than 1.8v to the input (I use a rheostat tied across pins 32 and 34 with the analog input on the wiper).

    #!/bin/bash -e
    if [ ! -d /sys/devices/ocp.2/helper.14 ]; then echo cape-bone-iio > /sys/devices/bone_capemgr.9/slots; fi
    for (( i=0 ; ; ++i ))
    if (( i > 0x0f )); then
    printf 'n[press + c to stop]nn'
    cat /sys/devices/ocp.2/helper.14/AIN5
    sleep .2

  • Simon Bella

    Thanks John,
    I am looking at about 10 GPIO’s if possible, 4 inputs which I would like to use as counters if possible? Not sure how fast Linux will allow polling inputs for counting pulses – but I would like a response time of at about 20mS if possible? For protecting the analog inputs from exceeding 1.8V would it be OK to tie a reversed biased diode between the input and VADC (pin 32) ?

  • armhf

    The P8 header GPIO pins 7, 8, 9, and 10 happen to be counters. I haven’t used them as such, so I’d have to do some googling to figure out what is involved.

    For the diode question, are you thinking something like:

    pin ---////----+-------input
    4.7K |
    - 1.8v
    ^ zener

  • armhf

    I ran across a well written GPIO example for the PI that has a lot of applicability to this article:

  • Simon Bella

    The zener idea is great! – I was thinking of simply connecting a diode from VADC to the input (like your example) so that if the input signal try’s to exceeds VADC it would clamp itself to VADC – but then again this may do some damage?

    I had a brief look at the cpu data sheet and I can see a reference to 8 timers (not counters) although I am not sure these will act as counters with clock inputs from GPIO pins 7,8,9 & 10 or whether I can access this from linux code. It would be great if this is the case and I can configure and read these hardware counters from c++ code running under linux?
    Obviously I need to do a heap more work to figure all this out?

  • Andy Bushnell

    Putting a red LED on the output without a resistor is a bad idea. I would put a 330 ohm resistor in series.

  • disqus_0dWLuTFGtk

    Hi, thanks for the tutorial. I do have a few questions for you. You mention to check tables 10 and 11 in the System Reference Manual to understand what pins may be available, but I’m don’t see how to determine this. I see this list of pins with modes 0 – 7. Once it is determined that a certain pin is available, how do I put it into the correct mode from this table?

  • armhf

    Functions of column MODE7 look to be the most prevalent, but if the kernel is configured to use a UART, then those pins wont be configured as the MODE7 feature. If you snap on an LCD cape, then the kernel will reconfigure to take the LCD pins.

    In general, look at the MODE7 features, look at what else they could be used for, try to determine if they would already be in use for that feature, then empirically determine if they are available. Some pins like the analog inputs have to be explicitly configured as such (see the comments with Simon below).

  • Pingback: การใช้ GPIO ใน Linux ของ BeagleBone Black | BeagleBone Lover in Thailand()

  • Pingback: How to control the GPIO in the BeagleBone Black | Robotics, python and more!()

  • Pingback: google()

  • davidkelso

    Thanks for a great rundown! That gpio0/1/2 thing with the 0/32/64 offset was doing my head in.

  • armhf

    The easiest (and the way I often do it) is to put it into a script from /etc/rc.local. I guess the other two (potentially better) options would be using uEnv.txt to do it with uboot, or modify /boot/dtbs/am335x-boneblack.dtb.

  • Pingback: Using GPIO on the Beagle Bone Black - Hackalizer()

  • Ran Talbott

    Thanks, John, that was very helpful.

    There appears to be some delay between the writing to /sys/devices/bone_capemgr.9/slots and the creation of the analog pin directory tree: I’ve noticed that the first time I run your example after a reboot, it can fail to find the pin files, but the second time works. After I finish my already-late project for my customer, I’ll figure out how long a “sleep” one should add after the write.

    Also, I did some testing and discovered that reading the ADCs in C requires that you fclose and re-fopen the file every time. At least, it does using the Ubuntu 12.04 image. Not a problem for me, since I’m just polling a temperature sensor once a second, and not something I’m asking you to do anything about. This is just a warning to others who might also assume that the ADC files are “streams of readings” you can read from repeatedly.

    Someone else has figured out how to do repeated ADC reading using the PRU, but it was much too complicated for my current prroject, and I neglected to bookmark it. A google search for BBB analog with “PRU” in quotes should bring it near the top of the results.

  • Kishor

    Caught the issue with 112 & 15. This pins are used by LCD4 cape.

  • armhf

    I don’t recall exactly — I do remember waiting a couple of weeks for them to come all the way from China. I think this may be very similar:

    The board I have is really annoying since the logic is inverted (in my opinion) and the relays glitch at boot to get the logic state to 1 to open the contacts.

    I just got a prototype in last week of a relay cape I designed and will sell on this site — it works like a champ but that is probably going to be 3 or 4 weeks from now. It has 4 relay outs, 4 opto isolated digital inputs, and 4 analog inputs — stay tuned.

  • Allen Chen

    Hi John,
    How to set pinmux for pin12 on the expansion header H9? However set the output value to be 0 or 1, the measured voltage of the pin will always be 3.17v.

  • armhf

    It sounds like you would have to find out what it is being used for and disable that feature to get control of it. I took a quick look and it appears that it is probably being used for the external MMC card but I can’t be sure without digging-in deeper.

  • Rama Krishna Katta


    In my BBB I did not find bone_capemgr.9 in /.sys/devices directory. In my board only bone_capemgr.8 is there in /sys/devices folder I want to work with Analog input pins, Please tell how can I get bone_capemgr.9 folder.


  • armhf

    I suspect it will work the same way with the .8 directory of your device — I guess it must be some sort of versioning technique? Did you just try that?

  • luky luky

    Hi, has anyone tried Adafruit_BBIO library with Ubuntu image?

  • Worms

    Just something I don’t understand… The BBB’ s GPIOs are designed to source or sink only 4-5 mA.
    How can you directly plug the relay board on the BBB ?

    Your relay board seem to have one optocoupler and one transistor per relay. the optocoupler need something like 20mA to works properly.

    It’s a special relay board who can works on 3.3v and only 4 mA or you have just pluged the relay board without taken care of current used on the GPIOs ?

  • armhf

    The relay board has opto-isolated input. The 3.3v BBB GPIO outputs only light the opto LED. The relay board itself is powered by the 5v VDD_5V (pin 5) supply from the barrel connector. I have also powered this relay board successfully using the SYS_5V (pin 7 USB based) source for short signaling clicks of the relays.

  • Matthew Whited

    Does anyone have an easy to understand list of what GPIOs are available without the overlay trees or disabling the onboard capes. That tech manual is a mess.

  • German

    Hi John,

    I am using the Ubuntu image.
    Can you please tell me if this image actually has HDMI functionality disabled and the GPIO’s and UART pins associated with the LCD can be used or if I need to specifically disable the LCD and if so how is this done?
    I also cannot seem to get I2C1 functionality to work but I2C2 seems to work OK. looking at the decompiled am335x-armhf-boneblack.dts file shows that there is no definition for I2C1 ? do you know why this is the case?

  • armhf

    Since the hdmi cape is built-in on the BBB, I do believe it is on by default. Since many pins have conflicting functions, many things are turned off. A quick search of the /lib/firmware directory seems to indicate that there may already be support already there or at least enough to get going:
    grep -ri I2C1 /lib/firmware/*dtbo
    Binary file /lib/firmware/BB-I2C1-00A0.dtbo matches
    Binary file /lib/firmware/BB-I2C1A1-00A0.dtbo matches
    Binary file /lib/firmware/cape-bone-tester-00A0.dtbo matches

  • German

    Thanks for that John, yes I confirmed the HDMI is enable at boot. Disabling it allows the extra IO.

  • B Brad

    Anyone else try this? I’d hate to kill the BBB or a GPIO pin because I’m abusing it.

  • Brent Singleton


  • Eric Rini

    Hey John this is a great article. Any idea how sysfs performanceportability compares to a memory mapped io approach?

  • armhf

    There are defiantly pros and cons to accessing GPIOs from /dev/mem.

    Sven Andersson’s UIO blog entry summarizes these considerations pretty well:

    Userspace access via /dev/mem

  • Pingback: priligy cialis()

  • Matthew Teetshorn

    The Adafruit Python library handles pin export and direction setting through the file system on any call to GPIO.setup(). It then uses a file write to “value” when you set the pin with GPIO.output(PIN, GPIO.HIGH) etc. It then unexports the pins on GPIO.cleanup().

  • Pingback: Gregory Smith()

  • John

    Excellent video. Thanks.

  • Pingback: max()

  • Julian Gold

    These links to gpio48 (etc) are all still owned by root, and so executing “echo blah > sys/class/gpio/gpio48/value” from a normal user account gives me “permission denied” (debian wheezy v7)

  • Pingback: Vanessa Smith()

  • Rajan

    Try this it will work
    sudo sh -c “echo 48 > /sys/class/gpio/export”

  • John Hobart

    Great article! What relay board did you use?

  • armhf
  • gourneau

    Hey y’all. I made a short little video showing how to do this with the rev c bbb, running the stock Debian Image, and the saint smart relay board.

  • John Hobart


  • ikki Power

    Thanks, You’ve saved a lot of time!

  • Culero Connor

    By chance do you get a brief [less than a second] ON state on your
    relays and outlets when you boot your system up? I get this
    behavior with mine and I’m looking for a workaround. Maybe some component that accumulates charge and suppresses the initial burst or altering the default GPIO state [no longer an overlay] loaded on start.