GPIO with sysfs on a Raspberry Pi


The Raspberry Pi (in case you’ve been living under a rock for the last six-months) is a cheap ($25) ARM Linux computer, primarily designed to be used to help teach kids to learn programming & computer science.

It’s also makes a pretty nice alternative to something like a BeagleBone, if you’re looking to play with some embedded computing technology. Whilst it’s less powerful than BeagleBone (and has less GPIO connectivity), Raspberry Pi does have a few advantages. It’s cheap, and it has an HDMI output – meaning that you can interact with it directly, without the need to ssh in from another computer.

The whole ethos of the Raspberry Pi foundation is to make the device as easy to use as possible: to encourage children (and adults!) to play with it, and learn to program. As with Arduino though, this user-friendly layer doesn’t mean that you can’t get your hands a little dirty and see what’s going on underneath.

If you’re going to play with GPIO on Raspberry Pi, then I suggest that you pick-up an Adafruit Raspberry Cobbler. Whilst the cobbler doesn’t provide any kind of over-voltage protection, it does provide a neat way to link from the Raspberry Pi’s header, to a breadboard: and it the labels PCB make it very easy to see which pin is which (without the need to have to refer to a diagram, and count pins).

There are a dozen and one tutorials on the web about how to use GPIO from your Raspberry Pi – but most of them (at least all the ones I’ve found) do so from a point of view of using a pre-written library (usually the RPi.GPIO Python library). Whilst these are a good place to start (especially if you just want to make something that works – and you aren’t too worried about all of the low-level details): they don’t explain what’s going on, at a low-level.

So in this piece, I’m going to have a quick look at one way to access the hardware at a much lower level: using Linux sysfs. Sysfs provides a way in Linux for users (or code in the user-space) to interact with devices at the system (kernel) level. Dr. Derek Molloy at Dublin City University, has an excellent video demonstrating using sysfs on a BeagleBone on his YouTube channel: and that is the inspiration for this piece. However, things are a little different on the Raspberry Pi, so let’s go through the process of setting GPIO pins on a Pi.

Firstly we’ll need a circuit. In this example, we’ll drive a couple of LEDs from the GPIO. Since we want to keep the current drawn through the GPIO pins as low as possible, we’ll use a transistor to switch – and actually power the LED from the board’s 5v pin.


Raspberry Pi GPIO Schematic
Raspberry Pi GPIO Schematic

Here’s what that looks like when built on a breadboard, using the Adafruit cobbler.

Raspberry Pi GPIO Breadboard
Raspberry Pi GPIO Circuit on a breadboard
Raspberry Pi GPIO Circuit – close-up

Note that I’ve picked the two GPIO pins that I’m using, more or less at random. Any of the pins (apart from the power rails, the ground, and the DNC pins) can be used – though you’ll want to avoid using the reserved pins (such as UART TXD & RXD) if you plan on using them for their main purpose (like serial I/O).

Unlike on the beaglebone we don’t need to worry about multiplexing modes for the pins – and we can skip ahead to using sysfs to get at the pins. Note that we need root privileges to use sysfs: and because we’ll be piping the output from one command into a sysfs file the easiest way to do this is to invoke a root shell – using the su command. (If you’re new to Linux – a good tip is that a root shell has a # prompt, instead of the usual $ prompt).

pi@raspberrypi ~ $ su
root@raspberrypi: /home/pi #

Next we need to go to the sysfs directory pertaining to the GPIO pins – /sys/class/gpio

root@raspberrypi: /home/pi # cd /sys/class/gpio

Now we’re ready to start, by creating the sysfs alias for the pin we want to use – by exporting that pin. We do this by adding the pin we want to work with to the export list: export isn’t a normal file though – it’s part of the mechanism of sysfs. Closer inspection will show us that this is an unusual file…

root@raspberrypi: /sys/class/gpio/ # ls -l
total 0
--w------- 1 root root 4096 Jul 19 19:41 export
lrwxrwxrwx 1 root root 0 Jul 19 19:41 gpiochip0 -> ../../devices/virtual/gpio/gpiochip0
--w------- 1 root root 4096 Jul 19 19:41 inexpert

Both export (and it’s counterpart unexport) are write-only files! Of course, what actually happens is that sysfs monitors these files, and updates the links between user-space and kernel-space when they’re updated (a more thorough description of which, is beyond the scope of this tutorial).

On the Raspberry Pi the pin identifier is just the GPIO pin number: note that this doesn’t directly correspond to the physical number of the physical pin in the P1 header – GPIO4 which we’re using, is physically pin 7 in P1. (For more information, see the GPIO section on the Raspberry Pi wiki).

We add GPIO4 to the export list – by simply appending 4 to export. There’s no output from doing this – but if we do an ls -l

root@raspberrypi: /sys/class/gpio/ # echo 4 > export
root@raspberrypi: /sys/class/gpio/ # ls -l
total 0
--w------- 1 root root 4096 Jul 19 19:41 export
lrwxrwxrwx 1 root root 0 Jul 19 19:41 gpiochip0 -> ../../devices/virtual/gpio/gpiochip0
lrwxrwxrwx 1 root root 0 Jul 19 19:41 gpio4 -> ../../devices/virtual/gpio/gpio4
--w------- 1 root root 4096 Jul 19 19:41 unexport

Sysfs has created a direction which is a symbolic link corresponding to GPIO4. If we look inside that directory we’ll see a number of files.

root@raspberrypi: /sys/class/gpio/ # cd gpio4
root@raspberrypi: /sys/class/gpio/gpio4 # ls
active_low direction edge power subsystem uevent value

For our purposes we’re interested in only two of these: direction and value.

If we look at the value of these files, we can see how they’re set:

root@raspberrypi: /sys/class/gpio/gpio4 # cat direction
root@raspberrypi: /sys/class/gpio/gpio4 # cat value

To turn on GPIO4 – we need to set it to be an output pin, and then set it’s value to high.

root@raspberrypi: /sys/class/gpio/gpio4 # echo out > direction
root@raspberrypi: /sys/class/gpio/gpio4 # echo 1 > value

If everything is correct, we should now see our LED illuminate. To turn in off again, we simply write a 0 to the value.

root@raspberrypi: /sys/class/gpio/gpio4 # echo 0 > value

Finally when we’ve finished: it’s good practice to unexport the pins we were using (to free them up for anything that might want to use them).

root@raspberrypi: /sys/class/gpio/gpio4 # cd /sys/class/gpio
root@raspberrypi: /sys/class/gpio # echo 4 > inexpert

We could, of course, also do all of this programmatically: and that’ll be the subject of part two.

Leave a Reply

Your email address will not be published. Required fields are marked *