Beaglebone Coding 101: Blinking an LED

[Updated Jan 22 – various improvements to the Python sample code at the end of the article]

In November, Texas Instruments, Digi-Key and the other members of, the Beaglebone.  This is a simpler, more hobbyist-friendly little brother to the Beagleboard (which I’ve written about in past articles).

Compared to the Beagleboards, the Beaglebone is considerably less expensive ($90), provides access to all of its pins, is pin-compatible with 3.3V sensors and devices (aside from analog in, which is still 1.8V), and provides a more friendly “out of the box” experience.  As with the Arduino, the only thing you need to get started is a USB cable.

As a developer, my most pleasant surprise with the Beaglebone was the inclusion of an entry-level IDE and scripting language: the Cloud9 IDE configured to run node.js and bonescript.

With the Beagleboards, there was no “out of the box” IDE.  There were plenty of options for developing with the Beagleboard – Texas Instrument’s Code Composer Studio, Eclipse, or the command-line GCC tools being the most prominent – but all had a fairly steep learning curve just to do something basic, like blink an LED.

One of the most slippery patches on that learning curve is figuring out how to convince the Linux kernel to let your code access the pins.  It’s nowhere near as simple as Arduino’s “digitalwrite(13, HIGH)” – or, at least, it wasn’t until bonescript came along.  Although bonescript is still in its very early stages, there is enough meat on it to give the embedded Linux newbie a friendly introduction to coding.

The Circuit

The circuit is your garden-variety LED configuration:

  • an LED
  • a resistor (680R or thereabouts) connected to the negative pin of the LED
  • a jumper from the positive pin of the LED to the digital pin
  • a jumper from the resistor to ground

The Beaglebone actually has 65 GPIO pins to choose from, but we’ll go with the one used by the blinkled.js program that is included with bonescript.  This is Pin 3 on Header 8, referred to by the Beaglebone System Reference Manual as  GPIO1_6 on Expansion B, but known to Linux as gpmc_ad6.

Say what?

Well, the “Pin 3 on Header 8″ part is simple enough. If you look at the Beaglebone, Port 8 is one of the 2 double-rows of female headers,  labeled P8 on the circuit board.  (In the figure below, taken from the System Reference Manual, Port 8 is labeled “Expansion B).

Beaglebone, showing pin P8_3 and Ground
Beaglebone, showing pin P8_3 and Ground

At either end of the headers you’ll find the rows marked 1 and 2, and 45 and 46.  So, Pin 3 is the 2nd row from the top, left column, as indicated in the figure.

The other names for the pin, along with the locations of the ground pins, can be found in the System Reference Manual.  If you look at Table 8 – “Expansion Header P8 Pinout” (a portion of which is shown below), you’ll find the pins labeled with their default usages in the Angstrom Linux demo image (the one that comes packaged with the beaglebone on a microSD card).

Default pin settings in Anstrom Linux
Default pin settings in Anstrom Linux

Clearly, Ground is the top row of Port 8, so that’s the last bit of information we need to know to hook up the circuit.  But we’ll need to understand that part about pins having “default usages” – more on that later.

Cloud9 IDE and bonescript

When you boot up the Beaglebone with the microSD card from the box, the Cloud9 IDE is automatically started.  Once you have an  IP address assigned to the Beaglebone (either through its Ethernet port connection or through USB networking), you can load the Cloud9 IDE on your PC browser at http:<beaglebone address>:3000

(I haven’t tried to use USB networking myself, but the procedure for doing so is explained in Getting started with your new BeagleBone.)

The Cloud9 IDE interface is pretty intuitive.  You select a source code file in the left pane, edit it in a tab in the right pane, and select Debug or Run from the toolbar to execute the code.

Cloud9 IDE
Cloud9 IDE

If you are coming at this from the Arduino, you will notice 3 significant differences from the Arduino IDE:

  • You don’t upload your code to the board.  The Beaglebone is more like a PC than an Arduino – the code is stored on its file system, and you just run it.
  • You can debug your code.  Not Arduino’s form of debugging – print statements to the console (though you can do that too) — but real debugging, as in breakpoints, watch variables, step-by-step execution.
  • The coding language is Javascript, not C.  Specifically, it’s node.js, which is Javascript optimized for running on a server, rather than in a browser, by way of some extra libraries.  The “server” in this case is the little old Beaglebone.  As you might imagine, node.js is not the fastest environment for running code on the Beaglebone, but for LED blinking and many other types of prototyping, it’s fast enough.

Despite the differences, Arduino coders should find the transition to Cloud9 and bonescript to be quite easy.  The blinkled.js code looks very much like Arduino code.  That’s no coincidence: the README for the bonescript project, which you can find on its github page here,  says that the goal is “to have something that provides most of the Arduino functions and is generally usable by Summer 2012″.

var ledPin = bone.P8_3;
var ledPin2 = bone.USR3;

setup = function() {
    pinMode(ledPin, OUTPUT);
    pinMode(ledPin2, OUTPUT);

loop = function() {
    digitalWrite(ledPin, HIGH);
    digitalWrite(ledPin2, HIGH);
    digitalWrite(ledPin, LOW);
    digitalWrite(ledPin2, LOW);

This code from blinkled.js does the following:

  • defines 2 pins, P8_3 (Port 8, pin 3) and USR3 (which is one of the built-in LEDS on the board, next to the Ethernet port)
  • sets these pins for Output
  • loops, turning these 2 LEDs on and off, once per second, ad infinitum

If you’ve attached an LED to pin 3, and you run blinkled.js in Cloud9, you should find it blinking happily away. (There is a dropdown button next to the Run and Debug toolbar icons in Cloud9 to let you choose the file).

It’s that simple.

I lie.

There is actually considerable complexity behind the code which creates those 2 pin objects, bone.P8_3 and bone.USR3.  The complicated code is in one of the 2 “library” files in the bonescript folder, index.js.

Pins and Muxing

Before we dive into the index.js code, let’s return to the Beaglebone System Reference Manual.  As you’ll recall, I earlier referred to the “default usage” on Port 8 Pin 3.  It has other usages, and the process of telling the board how you want to use that pin is called muxing (short for multiplexing).

The available usages of the pin, and all of the others on the Port 8, are listed in Tables 9 (the first part of which is shown below) and 10 of the System Reference Manual.  Each pin can have up to 8 uses, “mux mode” 0 through 7.  The default setting in the Angstrom Image is generally, but not always, mode 7.  Table 8 is the definitive guide to Angstrom’s default mux setting for each pin.

Pin Mux settings from the System Reference Manual
Pin Mux settings from the System Reference Manual

(Incidentally, other Linux distributions for the Beaglebone, such as Ubuntu, will have their own default mux settings.  The board doesn’t control the mux settings, the software does.  The developers of the Angstrom Linux image on the SD card selected their defaults to be the most commonly used ones by hobbyists, providing a good out-of-the-box experience.)

If you Google “Beagleboard mux”, you’ll find lots of pages explaining the various ways in which you can change the mux setting.  Many of them refer to U-Boot configuration and kernel modules, which are complicated and, fortunately, no longer necessary.  There has been a lot of work done recently at making the mux settings accessible to “userland” code by way of the Linux file system.  If you (or your code) wants to read or change the mux setting, it just needs to read or write to a file.

Great.  So which file?

This information used to be hard to come by, scattering amongst various forum and blog posts, or hidden inside code in U-Boot or the linux kernel.  However, if you’re learning to code with the Beaglebone, I think the best way to learn the mux file system is to look at how bonescript handles it.

Muxing the bonescript way

So, back to the Cloud9 IDE.  This time, open up the index.js file in the bonescript directory.  (Note that this part of bonescript is in active development and is likely to change by the time you read this, but the underlying file system will still be the same)

A little ways into the code (line 39 in the current release, bonescript 1.0-r10), you’ll find the following:

var gpio0 = 0;
var gpio1 = gpio0+32;
var gpio2 = gpio1+32;
var gpio3 = gpio2+32;

bone = exports.bone =
    P8_1: { name: "DGND" },
    P8_2: { name: "DGND" },
    P8_3: { name: "GPIO1_6", gpio: gpio1+6, mux: "gpmc_ad6" },
    P8_4: { name: "GPIO1_7", gpio: gpio1+7, mux: "gpmc_ad7" },
    P8_5: { name: "GPIO1_2", gpio: gpio1+2, mux: "gpmc_ad2" },
    P8_6: { name: "GPIO1_3", gpio: gpio1+3, mux: "gpmc_ad3" },
    P8_7: { name: "TIMER4", gpio: gpio2+2, mux: "gpmc_advn_ale" },
    P8_8: { name: "TIMER7", gpio: gpio2+3, mux: "gpmc_oen_ren" },
. . .
    USR0: { name: "USR0", gpio: gpio1+21, led: "usr0", mux: "gpmc_a5" },
    USR1: { name: "USR1", gpio: gpio1+22, led: "usr1", mux: "gpmc_a6" },
    USR2: { name: "USR2", gpio: gpio1+23, led: "usr2", mux: "gpmc_a7" },
    USR3: { name: "USR3", gpio: gpio1+24, led: "usr3", mux: "gpmc_a8" }

This table contains 3 important pieces of information:

  1. the label that bonescript uses to identify the pins (P8_1, P8_2, etc)
  2. the GPIO pin number (P8_3 is gpio1+6, or 38)
  3. the mux label (P8_3 is gpmc_ad6)

The GPIO pin number tells you the directory name you will use to read from or write to the pin.  The mux label tells you the filename you will use to read or write the mux setting.

Let’s start with the mux setting.  This is handled by some code just below the exports.bone table:

if(pin.mux) {
 try {
    var muxfile = fs.openSync(
      "/sys/kernel/debug/omap_mux/" + pin.mux, "w"
    fs.writeSync(muxfile, "7", null);
 } catch(ex3) {
    console.log("" + ex3);
    console.log("Unable to configure pinmux for: " + +
      " (" + pin.mux + ")");
. . .

There is more to the error handling, but the important part is the reference to “/sys/kernel/debug/omap_mux/” + pin.mux.  This is the file used to read and write the mux setting.  In the case of Port 8 Pin 3, the full path is /sys/kernel/debug/omap_mux/gpmc_ad6.

This is the part that is newcomers to pin muxing often trip over: if you want to set a pin to be a GPIO pin, your code needs to reference a filename that appears to be intended for a different usage of the pin (gpmc_ad6).  The mux filename isn’t taken from its intended usage, it’s taken from its mode 0 usage.  The mode 0 usage for Port 8 Pin 3 is gpmc_ad6 – we know this from the table in the bonescript code, but the definitive reference for the Beaglebone pin mux modes are Tables 9 and 11 of the Beaglebone System Reference Manual.

Having opened the file (fs.openSync), the bonescript code writes a 7 to it (fs.writeSync).  This, as you probably guessed, sets the mux mode to 7, the GPIO mode for that pin.  The process of setting mux modes isn’t quite as simple as “write the  mode to a file”:  the mux mode setting also affects other aspects of the pin, such as whether it can be used for input.  The bonescript code shown above is actually correct only for setting pins to be GPIO Output pins.  The bonescript project will soon support other mux mode settings.

Blinking LEDs the bonescript way

Having set the pin to be in digital output mode, the next task is to set it high or low.  You’ll recall that this was handled in blinkled.js by calling a function called digitalWrite, same as the Arduino does.

The source code for digitalWrite can be found further down in index.js:

digitalWrite = exports.digitalWrite = function(pin, value)
    fs.writeFileSync(gpio[pin.gpio].path, "" + value);

OK, so it’s writing a value to a file, either HIGH (defined as 1) or LOW (0).  But which file?

The code to set that “path” property also in index.js, just below where the pin mux setting was done:

try {
    try {
        fs.writeFileSync("/sys/class/gpio/export", "" + n);
    } catch(ex2) {
        // TODO: If the file is already exported, can we know who did
        // did it so that we aren't opening it twice?  In general, this
        // shouldn't be an error until we have some better resource
        // management.
        //console.log("Unable to export gpio: " + n);
    fs.writeFileSync("/sys/class/gpio/gpio" + n + "/direction",
    gpio[n].path = "/sys/class/gpio/gpio" + n + "/value";
} catch(ex) {
    // Perhaps we couldn't open it because it was allocated as an LED
    if(pin.led) {
            "/sys/class/leds/beaglebone::" + pin.led + "/trigger",
        if(mode == OUTPUT) {
            gpio[n].path =
                "/sys/class/leds/beaglebone::" + pin.led +
        } else {
            gpio[n].path =
                "/sys/class/leds/beaglebone::" + pin.led +

The first thing it does is try to write to a file named “export”, specifically , “/sys/class/gpio/export”.  The value written is the GPIO pin number, which you’ll recall was specified in the table earlier in index.js.  For Port 8 Pin 3, it was defined as gpio1+6, or 38.

The export file is a funky weird-ass file: when you write a pin number to it, it (well, the kernel process which monitors that file) creates a directory and a bunch of files that provide interfaces for accessing the pin.  The directory is created at /sys/class/gpio/export/gpioNN. In the case of Port 8 Pin 3, that’s /sys/class/gpio/export/gpio38.

For the purpose of using a GPIO pin, the two most important files in the gpioNN directory are named direction and value.

The direction file determines whether the pin is going to be used for reading or writing.  As mentioned earlier, you can’t use a pin for reading without setting flipping a bit in the mux mode setting, so our only choice at this point is output.   The bonescript code writes the value “out” to the direction file (i.e. to /sys/class/gpio/export/gpio38/direction).

The code then saves the path to the value file (i.e. /sys/class/gpio/export/gpio38/) in the pin’s path property.  This, then, explains what the code in the digitalWrite function is doing:

fs.writeFileSync(gpio[pin.gpio].path, "" + value);

It writes a 1 to the value file (i.e. /sys/class/gpio/export/gpio38/value) to set the pin high (and the turn the LED on) and a 0 to set it low (and the LED off).

But wait, there’s more!

The bonescript code shown above also has an error handler.

Writing to the export file also tells the kernel that you intend to use that pin.  If the pin is already being used by something more important than your dinky userland application (i.e. the kernel or one of its pals), it will helpfully toss an error at you.

Generally, when your attempt to export a pin fails, you have no option but to go away and sulk.  Something is using that pin, and it might be a hardware driver that won’t be giving it up any time soon (such as the SD card socket, or an LCD).  There are ways of tracking down what’s using it, but I won’t cover them in this post.

One possibility is that the GPIO pin is being used by one of the built-in “user LEDs”, USR0 – USR3.  As you can see from the final entries in the bonescript mux table, those LEDs are connected to GPIOs 53-56.  So, the bonescript code checks to see if you’re trying to write to those GPIOs – if so, it assumes you want to access the user LEDs, and redirects you to their address.

These user LEDs are accessed through a different part of the file system than the GPIOs – technically, they are part of the Beaglebone board, not part of the CPU.  So, they are accessed through the /sys/class/leds/beaglebone directory, not /sys/class/gpio.

The Beagleboard (the ‘bone’s big brother) also has user LEDs, and they are accessed in basically the same way there, so you can find a good explanation of how to write to them in some of the articles written for the Beagleboard.  The command line interface is explained in this article on eLinux.  For C language code that interfaces to the user LEDs, see this sample from Jan Axelson’s USB Embedded Hosts: The Developer’s Guide.  (This, by the way, is one of the few books currently available that specifically covers Beagleboard programming).

Blinking LEDs the Python Way

The directories and paths used by the bonescript code can also be used from other programming languages: pretty much anything that runs on Linux can read and write from the file system.

Here is my own humble contribution, a snippet of Python code which blinks the USR2, USR3 and Port 8 Pin 3 ten times.  It has the advantage of distilling the bonescript code down to the bare bones needed to access that particular pin.

[Updated Jan 22 – added support for User LEDs 2 and 3, handle case where pin already exported, and simplified  the file I/O syntax:]

import time

# put Port 8 Pin 3 into mode 7 (GPIO)
open('/sys/kernel/debug/omap_mux/gpmc_ad6', 'wb').write("%X" % 7)

   # check to see if the pin is already exported
   # it isn't, so export it
   print("exporting GPIO 38")
   open('/sys/class/gpio/export', 'w').write('38')

# set Port 8 Pin 3 for output
open('/sys/class/gpio/gpio38/direction', 'w').write('out')
# we will assume that USR1 and USR 2 are already configured as LEDs

for i in range(10):
   # turn on USR1 and external LED
   open('/sys/class/gpio/gpio38/value', 'w').write("1")
   open("/sys/devices/platform/leds-gpio/leds/beaglebone::usr1/brightness", 'w').write("1")
   # turn off USR2
   open("/sys/devices/platform/leds-gpio/leds/beaglebone::usr2/brightness", 'w').write("0")


   # turn off USR1 and external LED
   open('/sys/class/gpio/gpio38/value', 'w').write("0")
   open("/sys/devices/platform/leds-gpio/leds/beaglebone::usr1/brightness", 'w').write("0")
   # turn on USR2
   open("/sys/devices/platform/leds-gpio/leds/beaglebone::usr2/brightness", 'w').write("1")


# cleanup - remove GPIO38 folder from file system
open('/sys/class/gpio/unexport', 'w').write('38')

The Python code also demonstrates something that the bonescript code doesn’t handle.  To be a nice little userland app and clean up after yourself, you can write the GPIO pin number to /sys/class/gpio/unexport.  This doesn’t “release” the GPIO to other apps – you never had it locked for your exclusive use in the first place – so unexport’ing is just a convention to make the gpio file system is a little more manageable.

Since python is already installed on the Angstrom image, you can download the file and run it as follows:


Wrapping Up

If you think that’s a lot of work in order to blink an LED, you should have tried it a few years ago, when the Beagleboard was first released.

Back in the day, to do anything with a GPIO pin you pretty much had to be an embedded Linux guru, or beg for crumbs of knowledge from the guru’s table.  (Oh, and good luck getting your LED to light up on 1.8V.  You kids have it easy these days!)

The Beaglebone arrives at a time when the embedded Linux device market is growing by leaps and bounds, both in terms or hardware and development tools.  As a hobbyist (or a budding professional), this is a good time to hop on board the platform.

Incidentally, while the Beaglebone platform is geared for hobbyists and prototypers, the chip it uses is very much targeted at professionals.  The Texas Instruments Sitara AM3359 is a descendent of (and largely code compatible with) the storied OMAP chip family, which powers a lot of consumer gadgets: many of Nokia’s high-end smartphones like the E90, Motorola’s Droid line of Android smartphones, the Nook Color and the Kindle Fire.

If you can get to a root command line on one of those devices, you can probably set a GPIO high and low using the same code as above (and if you’re lucky, cause an inglorious crash).  How cool is that?

This entry was posted in Electronics, Gadgets, Programming and tagged , , , , . Bookmark the permalink.

50 Responses to Beaglebone Coding 101: Blinking an LED

  1. Georg Wassen says:

    Hi Dan,
    great article, thanks a lot!
    I still wonder, how much current the pins support. I have not found any (understandable) information in the data sheets or other documentation. You described how to use a LED, but did you use low-current LEDs?
    Best regards, Georg.

    • dwatts says:

      Hi Georg,

      Yes, I was using a low current LED. I can’t find where the max current is documented either – I think it’s somewhere in the 4500 page Technical Reference for the AM335x processor, but most of that stuff is over my head. On the Beagleboard XM’s DM3730, the max current is different for different pins, and depends on how many pins are driving or sinking current at the same time, but the absolute maximum was quite low, 8 mA.


  2. Denbo68 says:

    Thanks for the intro. I received a BB but only played with it slightly. There doesn’t seem to be much info out there compared to the Arduino so hope to see more such as PWM, etc…

  3. RCA says:

    At last! I’ve been searching for this kind of practical information for 2 weeks! Now to get busy.

    Any recommended forums for BeagleBone related info? I’ve found the Google Groups Beagle Board forum–that’s how I got here.

  4. Pingback: Beaglebone Coding 101: Using the Serial and Analog Pins | GigaMegaBlog

  5. Xenland says:

    You wouldnt happen to know how to read a poteneiemeter or a transistors tempurature sensor… Im still straching my head on this one thanks alot!

    • Alan says:

      You mean, use the built-in ADC? Depending on what you are measuring, the first step is a suitably isolated input circuit…

  6. Bryan says:

    Thank you so much for the great article!

    Question, I am able to get P8_3 working as you describe in the tutorial, but I cannot seem to get the GPIO to work on any other pins. For gpmc_ad6 it shows gpio1_6 which matches the BeagleBone manual. For P8_4, however, gpmc_ad7 should have gpio1_7, but instead shows “NA” as shown below.

    cat /sys/kernel/debug/omap_mux/gpmc_ad6
    name: gpmc_ad6.gpio1_6 (0x44e10818/0x818 = 0x0037), b NA, t NA
    signals: gpmc_ad6 | mmc1_dat6 | NA | NA | NA | NA | NA | gpio1_6

    name: gpmc_ad7.(null) (0x44e1081c/0x81c = 0x0037), b NA, t NA
    signals: gpmc_ad7 | mmc1_dat7 | NA | NA | NA | NA | NA | NA

    Is there something special I need to do to make this pin accessible as GPIO, or can it not be configured that way? Any help would be greatly appreciated. Thanks.

    • dwatts says:


      I get the same results if I set gpmc_ad7 to mode 7: the signals line seems to indicate it isn’t supported.

      However, most of the GPIO pins indicate “NA” for Mode 7, but most work correctly in this mode. This post in the Beagleboard Google Groups forum indicates that it’s a known problem which (I think) only affects the output of the signals line, not the behaviour of the pin:

      However, gpmc_ad7 (Pin 4 on Port 8 ) has another problem: if you try to interact with it through the file system, you’ll likely get an error…

      root@gigamegabone:/sys/class/gpio# echo 39 > export
      sh: write error: Device or resource busy

      I haven’t found an explanation for this. I can only assume that the pin really is in use by some other software.

      I’ve found that the next 2 pins on Port 8 (5 and 6) work as expected as GPIO pins, when put in mode 7 (they are in mode 0 by default). These are gpmc_ad2 (GPIO 34) and gpmc_ad3 (GPIO 35).



  7. Pingback: Beaglebone Linux 101: Configuring Angstrom Linux | GigaMegaBlog

  8. Great series on Beaglebone coding. How applicable is this to the original BeagleBoard? You’ve added some links for LED control with a CLI or in C for the BeagleBoard, but is it possible to use the Cloud9 IDE and bonescript? (the name would suggest otherwise)

  9. hanan says:

    Thank you for putting the work in and posting this! This is awesome awesome awesome.

  10. Pingback: beaglebone ubuntu user led gpio « Lost Ferry

  11. felita says:


    You mentioned that Jan Axelson book is one the few books that covers Beagleboard. May I know which other books that also discussing beagleboard.

    I know “Practical Beagleboard” is supposed to be one of them, but seems like the publication was cancelled.

    Thank you

    • dwatts says:

      Well, I was admittedly being optimistic when I said “few”. Hopefully others will appear, but the only other one that I know about is “Embedded Linux Primer: A Practical, Real-World Approach” by Christopher Hallinan. I’ve started to read this, and it’s relatively easy to understand for non-engineers, but not a project-oriented book like Practical Beaglebone would have been.


  12. felita says:


    It’s an excellent tutorial. But as a beginner to embedded linux, I dont’ really get the “big picture” . For example, if we want to stick with bonescript, do we write the whole application with bonescritpt or can we combine it with c for example ? and how to make the board to automatically load our written application upon botting-up? And how can we make use of watchdog timer as on microcontroller world ?

    I’m trying to compare the development process on beagleboard/beaglebone with PIC microcontrolelr for example…

    Thank you

    • dwatts says:

      I’m new to this type of development too, so I’m afraid that I don’t know the answers to your questions. You might want to post the questions to the Beagleboard Google Group, where the expert developers hang out.

      In general, there are 2 types of development you can do with the Beaglebone: Linux or “native”.

      Native development is similar to what you do with a PIC or AVR microcontroller — there is no Linux involved. You’d be dealing directly with the AM335X processor. I haven’t looked into this, but Texas Instruments has a lot of info and sample code for this, such as their StarterWare page:

      If you go with embedded Linux development, then you have 2 options: develop kernel modules (drivers) which have relatively low-level access to hardware, or “userland” code which can only do what Linux allows it to do. Bonescript and Python code are userland code. This type of code is easiest to learn, and there is relatively good documentation and example code on the web for this. For example, the answer to your question about invoking C code from bonescript can probably be found by reading or Googling info about “node.js”.

      Personally, I plan to stick with userland code, mostly in Python, and wait for more advanced developers to write the low-level code in the form of drivers and kernel modules. There are a lot of new hardware features built into the new 3.2+ kernel, such as PWM support, and lots more new stuff is in development.


  13. felita says:

    And for example, if I want to communicate with external peripheral like USB keyboard, how can I do that ?

    Thank you

    • dwatts says:

      From a coding standpoint, you can read from a USB keyboard using the /dev/input/event file system. When you plug in a USB keyboard, you should find that a new directories named /dev/input/event0 and event1 appears. Each time you press a key on the keyboard, an event is raised. You can see the contents of these events by running the evtest utility (i.e. evtest /dev/input/event0 ), and you can write your own code to read them — Google for examples.

      This event system can actually be implemented for any GPIO pin, but requires configuration in the kernel. I looked into this, but it’s over my head right now. You can read more about this by Googling “gpio-keys”.


  14. felita says:

    Ok, Now it makes more sense to me … everything is file in linux ….
    By the way, how about the watchdog or such in embedded linux ? Do I need external supervisory IC (watchdog timer IC) ?

    And I imagine Linux as an RTOS with all the drivers on microcontroller systems. Is that basically what Linux is doing ?

    Do I need to write a Linux script to automate the loading of my application when it’s powered up?

    Thank you.

    • dwatts says:

      Sorry, I don’t know about watchdog timers, or how (if) they are supported in Angstrom. This post might be useful to you:

      I don’t know much about RTOS either. If you are looking for an RTOS to run on the Beaglebone, Angstrom Linux probably isn’t the best choice. Maybe QNX?

      Linux offers a few different ways to automatically run a program at boot time. Typically, you add a shell script to the /etc/init.d file system for this — you can find tons of examples by Googling.

      If you are using Angstrom Linux, then the best choice is probably systemctl, which simplifies the process considerably. Take a look at the scripts in /lib/systemd/system for examples of how to do this.

      For example, to run a Python script at startup I created the following file:

      bigdog:/lib/systemd/system$ cat gm_sensorrelay.service
      Description=GigaMega Sensor Relay

      ExecStart=/usr/bin/python /media/sda1/python/



      • Matt says:


        I’d love to see more detail on how you got your systemctl script to work. I’m having no luck with mine.

        Do you have to do anything special with your *.py file? I have mine in the /home/root folder.



        • dwatts says:


          Mine is in a user subdirectory. I actually didn’t have to troubleshoot systemctl much, since it (surprisingly) worked with the first configuration.

          My .service file is as follows:

          root@gigamegabone:/lib/systemd/system# ls -l gm*
          -rw-r–r– 1 root root 239 Mar 24 18:43 gm_lightcontroller.service

          root@gigamegabone:/lib/systemd/system# cat gm_lightcontroller.service
          Description=GigaMega Light Controller

          ExecStart=/usr/bin/python /home/dwatts/python/


          The python file’s settings are:

          root@gigamegabone:/home/dwatts/python# ls -l LightC*
          -rwxr–r– 1 dwatts dwatts 18633 Apr 17 21:26

          All I did to configure the service is:

          1. Created the Python file, and made sure it ran OK from the command line.
          2. (As root), created the .service file in /lib/systemd/system
          3. Tested it with:

          root@gigamegabone:~# systemctl start gm_lightcontroller.service
          root@gigamegabone:~# systemctl status gm_lightcontroller.service
          gm_lightcontroller.service – GigaMega Light Controller
          Loaded: loaded (/lib/systemd/system/gm_lightcontroller.service; enabled)
          Active: active (running) since Tue, 17 Apr 2012 21:28:15 -0400; 5 days ago
          Main PID: 1710 (python)
          CGroup: name=systemd:/system/gm_lightcontroller.service
          â 1710 /usr/bin/python /home/dwatts/python/LightControlle…

          4. Set it to start automatically at bootup with:

          root@gigamegabone:~# systemctl enable gm_lightcontroller.service

          If none of that sheds any light on your problem, then a couple of general troubleshooting suggestions:

          1. Update the kernel if you are running an old one (I’m on 3.2.13), and update the packages (i.e. “opkg update”, “opkg upgrade”). There were some patches to systemctl awhile back, December-ish.
          2. Use “systemctl status” and “systemctl list-units” to see if an error message is reported for your service.



  15. Pingback: » BeagleBone tutorial: Blinking LEDs using bash Wunderkammer

  16. Pingback: Beaglebone Coding 101: Buttons and PWM | GigaMegaBlog

  17. Hi
    I’m new with the beaglebone, thank’s to your explanations about GPIO it really helped me. But i still have problems to resolv:
    – Pin muxing is ok, i have to treat 6 interrupts (issued from 6 opto encoders mounted on stepper motors) so i have to make some treatments under interruption. are you able to tell me how to manage interrupts with Angstrom Linux.
    – How can i configure the kernel to take into account my needs. I think specially at the real time clock. I want to use the DS1307 RTC chip instead of the default time managing. Any idea about thats ?

    Thank’s for your answers

    • dwatts says:


      Sorry, I haven’t tried to do those things, so I can’t give you very good advice. Here is some not-so-good advice: :-)

      For interrupts, you can look at this page in the Beagleboard Embedded Linux Course: The sample C code for handling interrupts should also work on the Beaglebone.

      For interfacing with the DS1307, there is the hwclock command that allows you to directly read or write to it. I haven’t played around with it myself. You can find more information on this page in the Gumstix wiki (Gumstix uses a similar hardware platform to the Beagleboard/Beaglebone):

      # hwclock –help
      BusyBox v1.19.3 (2012-03-03 09:26:58 CET) multi-call binary.

      Usage: hwclock [-r|–show] [-s|–hctosys] [-w|–systohc] [-t|–systz] [-l|–localtime] [-u|–utc] [-f|–rtc FILE]

      I hope that helps,


  18. Pingback: Puppy’s First Month « bwgz57

  19. Amir says:

    Great article. Thank you

    Is it possible to control a pin remotely using a webserver running on BB ?

    I have done this with arduino. A webserver runs on the board that depending on what page user requests pulls a pin high or low. Can this be done using BeagleBone? or is it too much to ask at this point.

    • dwatts says:


      Yes, it’s definitely possible to do that (but I haven’t done it myself yet). Assuming you are OK with running your webserver on an embedded Linux platform (as opposed to writing native code for the Beaglebone’s AM335x processor), you have a lot of coding options.

      One popular option is node.js. Here is a project that uses a node.js to serve a web page that controls the serial port. It would be pretty easy to modify the code to control a GPIO pin instead.

      Another widely used platform for the Beaglebone is Python. Here is a project that runs a custom webserver in Python Again, it would be pretty easy to modify the code to control a GPIO pin.

      The Beaglebone is also capable of running web servers with CGI support, like Lighttpd or Apache. That would allow you to invoke C code, or just a shell script, that interfaces with the GPIO pins.


  20. Jeshwanth Kumar N K says:

    Very nice article, thank you very much :).
    I have one doubt in index.js.
    if(mode == OUTPUT) fs.writeSync(muxfile, “7”, null);
    else fs.writeSync(muxfile, “27”, null);
    in above condition why 27 for input ??

    • dwatts says:


      The pin mux settings are shown in this table, and I explained them a little better in this article

      The 27 is a hex value (i.e. x27). The “2” turns on bit 5 in that table, which is the “input enabled” bit. Note that the other bits that affect GPIO input are set to 0, so a pulldown resistor has been enabled. The 7 is, of course, the mux mode for GPIO.


  21. Pingback: Beaglebone and ExtJs Web App « Isola Software

  22. Steve Wilson says:

    Very good article – thanks for the C code. I’ve just got my BB up on Ubuntu today. Kind of exciting actually. My question – how do you access the GPMC? Is the Ubuntu kernel already set up for this out of the box? You seem to imply that this would be Mode 0/i.e. the default.

    I’ve seen some discussions of the GPMC using /dev/mem to access it – is that the way to go? I’m interested in talking to an external FPGA – and even a 4K window within a page would be okay.

    • dwatts says:

      Sorry, GPMC is way over my head. If you haven’t already, you should search the Beagleboard Google Groups posts on “GPMC” or post a new question there.


  23. Pingback: running code on BeagleBone using Cloud9 IDE | PHP Developer Resource

  24. Pingback: BeagleBone Coding 101 « adafruit industries blog

  25. Ashok says:


    I have tried loading the Ubuntu 12.04 OS in my beaglebone, it is not bootingup properly.
    Can you please help me in this?

    Thanks and Regards,
    Ashok Kumar P

    • dwatts says:


      I was able to load Ubuntu 12.04 by following the instructions at

      If you have a Linux computer, then the steps are:

      1. Open a command prompt
      2. Enter the following commands to download the image file unpack it, and open the directory:
      tar xJf ubuntu-12.04-r1-minimal-armhf.tar.xz
      cd ubuntu-12.04-r1-minimal-armhf.tar.xz
      3. Insert the mini SD card. If Ubuntu automatically mounts it, you’ll need to unmount it.
      4. Determine the /dev ID of the miniSD card. You can do this by entering “dmesg” and looking at the output at the bottom of the log, or by running the following command and looking at the output:
      sudo ./ –probe-mmc
      5. Run the following command to copy the image to the miniSD card. In my case, the miniSD card is at /dev/sde:

      sudo ./ –mmc /dev/sde –uboot bone

      This script will display output, and usually takes 10-20 minutes to finish. If the script hangs, or displays error messages, then you need to figure out what is wrong, since the card won’t work if the script doesn’t complete.

      If you don’t have a Linux PC, then the process is much more difficult. I haven’t had any success loading Ubuntu onto a miniSD card from Windows — it seems to work, but the Beaglebone gets read errors. I’d highly recommend installing virtual machine software, like VMWare Player, so that you can run Linux.

      If you’ve created the mini SD card, booted it in the Beaglebone, and it’s just not booting up, then you need to look at the output on the boot console to get more information on what is going wrong. Connect a USB cable to the Beaglebone, run terminal software (e.g. minicom on Linux, or WinPutty on Windows) to connect to the USB COM port, then reboot the Beaglebone.

      Good luck,


      • Ashok says:

        Hi Dan,

        Now ubuntu is working properly. procedure followed earlier is also same. This time after loading the image into SD card, i notice a comment saying, it will take minimum 2 mins to bootup if Ethernet is not connected. so i connect the sd connect and usb cable. open the serial port and leave it for 15 mins. when i return back, boot has been been completed successfully.

        Thanks for your input.

        Thanks and Regards,
        Ashok Kumar P

  26. Ashok says:


    I have a ZTE USB 3G modem. How to connect to internet using this 3G modem. how to update required drivers, as i don’t have internet connection in my beaglebone.

    i need for either angstrom or Ubuntu 12.04

    Please help me in this regard.

    Which is best one for Beaglebone, Angstrom or Ubuntu. I am planning to use it for Home automation (try to use most of the peripherals) and act as small web server in home.

    Thanks and Regards,
    Ashok Kumar P

    • dwatts says:


      For your project, Ubuntu is probably a better choice than Angstrom. Ubuntu has more packages available and is more stable. Angstrom supports some Beaglebone features that Ubuntu doesn’t, like PWM and analog input, if you need those features.

      Unfortunately, I can’t help you with the 3G modem. You’ll need ARM-based drivers, and if Googling doesn’t find any, then they probably don’t exist. You should ask in Google Groups — perhaps somebody there has built the drivers. Another option is running Android instead of Ubuntu, since Android presumably has better support for 3G modems.


  27. Thibault says:


    I would like to program my beagle bone map in C language cross-compilation in eclipse.
    I managed to do a very simple program to display “hello, world”.
    But now, I’d order the inputs / outputs and play with I2C and PWM.
    How can I do this in C? Are there libraries already made ​​or should I use write (echo> GPIO etc …)?

    Thank you!

    • dwatts says:


      I haven’t done any cross-compiled C coding on the Beaglebone myself, but there is an excellent series of YouTube videos by Derek Molloy that covers this, including GPIO and I2C. He’s a professor, so his teaching style is quite good.

      The code he shows for using the file system to handle GPIO is the same approach that you would take with PWM, though I don’t know what the best way to activate the PWM timer through C code is.

      I2C I/O is different: it uses a function called ioctl to directly read and write to the I2C device driver (e.g. /dev/i2c-1).


  28. Alan says:

    The blinking LED can actually be useful and practical – provided you can blink fast enough. Fortunately, apparently, there’s some extras up the beaglebone sleeves…

    Would you consider returning to the blinking LED – with its output from the McASP device? In other words – build a S/PDIF optical transmitter for hookup to an audio system.

  29. SAM_Malaysia says:

    Hi, does anyone has the UDP and TCP sample code running on BeagleBone embedded board to be shared,…. possibly the sample code just turn on /off the on board LEDs?
    How many RS232 ports can be made thru the available pinouts on the BeagleBone board?

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>