The GPIO driver in Linux used to be GPIO sysfs but no longer now its the GPIO character driver. Find out how to do GPIO control the modern way.
This content comes from our newly published book:
Raspberry Pi IoT In Python Using Linux Drivers
By Harry Fairhead & Mike James
Buy from Amazon.
As far as IoT goes, the fundamental Linux driver is the GPIO driver, which gives you access to the individual GPIO lines. This is another built-in driver and so is like the LED driver introduced in the previous chapter, but it is a character driver and used in a slightly different way.
In most cases, when a device is connected via a set of GPIO lines, you usually use a specific device driver. In this way you can almost ignore the GPIO lines and what they are doing. However, there are still simple situations where a full driver would be overkill. If you want to interface a button or an LED, then direct control over the GPIO lines is the most direct way to do the job even if there are Linux LED drivers – see the previous chapter – and even an input driver.
Until recently, the standard way to work with GPIO in Linux was to use the sysfs interface. You will see a lot of articles advocating its use and you will encounter many programs making use of it. However, GPIO sysfs was deprecated in Linux 4.8 at the end of 2016 and is due for removal from the kernel in 2020. Of course, it takes time for Linux distributions to make use of the latest kernels. At the time of writing Pi OS is using Linux 4.19, released two years earlier. Nevertheless, sysfs GPIO will soon be removed and while you still need to know about it to cope with legacy software, you shouldn’t use it for new projects.
Its replacement is the GPIO character device and, while this looks superficially like the old sysfs interface, it has many major differences. While it has some advantages, it also is slightly more complex and can no longer be used from the command line – it is a program-only interface. This said, there are some simple utility programs that are fairly standard and allow GPIO control from the command line. These are covered in the first part of the chapter, even though they are unlikely to be the main way that you work with the new interface. There is also a wrapper library called libgpiod (Library General Purpose Input/Output device) Although it isn’t necessary for simple access to the GPIO lines, it is described in this chapter.
The new approach to working with GPIO comes pre-installed in the latest version of Pi OS, but it isn’t supported in earlier versions. If you look in the /dev directory you will find files corresponding to each GPIO controller installed. You will see at least:
This represents the main GPIO controller and all of the GPIO lines it provides. If you know how sysfs works you might well be expecting instructions on how to read and write to the file from the console. In this case, reading and writing to the file will do you little good as most of the work is carried out using the input/output control system call, ioctl() which cannot be used from the command line. The use of ioctl is typical of a character driver, but it does mean that using the GPIO driver is very different from other file-oriented drivers described later. The next chapter looks at the use of ioctl to directly control the GPIO character device.
If you want to explore the GPIO from the command line, you need to install some tools that have been created mainly as examples of using the new device interface. To do this you need to first install them and the C libgpiod library that you will use later with a Python binding:
Notice that, if you don’t want to use the library to access the driver, you don’t have to install it – the GPIO driver is loaded as part of the Linux kernel and is ready to use.
The standalone applications that are installed are:
Lists all of the GPIO controllers that are installed:
Lists all of the GPIO lines provided by the named GPIO controller:
You can give particular lines names by editing the device tree. If you do give them appropriate fixed names then:
will return the number of the GPIO line.
You can use this to set any number of GPIO lines in one operation. The command has the form:
gpioset options chip name/number <offset1>=<value1>
where the options are:
-l, –active-low sets the line’s active state to low
-m, –mode= tells the program what to do after setting values
exit: exit immediately, the default
wait: wait for user to press ENTER
time: sleep for a specified amount of time
signal: wait for SIGINT or SIGTERM
-s, –sec=SEC number of seconds to wait
-u, –usec=USEC number of microseconds to wait
-b, –background detaches from the controlling terminal
Notice that the change in the line’s state only persists while the command is executing. This means that to see the effect, you have to use wait or time. For example:
sets gpiochip 0 GPIO4 to 0 and GPIO17 to 1 and waits until the user presses enter.
The gpioget command returns the state of the lines specified as text:
gpioget 0 4 17
will display the current state of GPIO4 and GPIO17 on gpiochip0.
The gpiomon command lets you monitor changes in input lines using a poll system call:
The options are:
For example, to monitor GPIO4 and GPIO17 for any changes:
These utilities are useful and they can be used in scripts to control GPIO lines. For example, if you save:
in a text file called binky.sh and set its execution permission to owner then you can run it in a console and flash a pair of LEDs connected to GPIO4 and GPIO17. Notice that if any of the GPIO lines are in use, the script will return an error message. You also need to keep in mind that the GPIO line is only in use while the gpioset command is running – that is, the line is opened at the start of the command and closed when it ends, so returning the line to input.
You can get a long way with shell scripts and the GPIO utilities, but sooner or later you are going to want to work with Python.