GPIO Sysfs Interface
The GPIO sysfs interface has been deprecated since 2016 and was expected to have been removed from the kernel by now. It should not be used for new projects, but it has been so extensively used in the past that you might need some knowledge of how it works for some time to come. This appendix is a brief overview.
Note: Only GPIO sysfs was has been deprecated, the rest of sysfs is perfectly usable.
Working With Sysfs
Sysfs is a virtual file system that provides all sorts of access to hardware and the operation of the Linux kernel. You can spend a lot of time exploring sysfs, but the part we are interested in here is the gpio folder. Sysfs is usually mounted in the sys folder and the folder that corresponds to the GPIO device is usually:
/sys/class/gpio
To see what is in the folder, simply list it:
ls /sys/class/gpio
The list includes the GPIO lines that are already in use by some process or other. Notice that the gpio numbers are not external pin numbers, but internal gpio numbers. So, for example, to use the GPIO line that is on physical pin 7 on the connector you need to refer to GPIO4.
The steps in using a line are always the same:
- Reserve or "export" the GPIO line so that no other process can use it
- Set its direction and read or write it
- Unreserve it or unexport it
You can do these steps from any language that supports file operations, including the shell.
You might ask why you have to "export" or reserve a GPIO line rather than just use it? The answer is that the export operation will only work if the OS, or some other process, hasn't claimed the GPIO line for its own use. You can think of the export/unexport process as making sure that you don't misuse GPIO lines and that you don't share them with other processes.
To reserve a GPIO line you have to write its number to the export folder and you can do this using the shell command. For example, assuming we want to work with GPIO 4:
echo 4 > /sys/class/gpio/export
You can of course change 4 to any valid gpio number.
You can do the same job in C:
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
int gpio = 4;
FILE* fd = fopen("/sys/class/gpio/export", "w");
fprintf(fd, "%d", gpio);
fclose(fd);
return 0;
}
The fopen function opens export for write, the fprintf string prints the number of the gpio line and then the file is closed with fclose. If you are not familiar with C file operations, see Fundamental C: Getting Closer To The Machine, ISBN:9781871962604 or, at a more advanced level, Applying C For The IoT With Linux, ISBN:9781871962611.
Once you have the pin reserved, you will see a gpio4 folder corresponding to it in /sys/class/gpio. Now you can set its direction and read or write it. To do this you have to read from or write to the appropriate subfolder of the gpio folder just created.
If you list all of the folders in gpio4 you will see:
Each of these folders controls some aspect of the GPIO line’s functioning. The most important are direction, in which the line can be set to in or out, and value, which can be set to 0 or 1 for output and 0 or 1 for input. There is also active_low, which determines which way the logic operates and whether the line low corresponds to a 1 or a 0.
For example, to read GPIO 4 from the command line use:
echo "in" > /sys/class/gpio/gpio4/direction
cat /sys/class/gpio/gpio4/value
and to set it as output and to go high and then low use:
echo "out" > /sys/class/gpio/gpio4/direction
echo 1 > /sys/class/gpio/gpio4/value
echo 0 > /sys/class/gpio/gpio4/value
You can do the same using C, but it is slightly more verbose due to the need to open and close files and build the appropriate strings.
Toggling A Line
As an example, consider the following C program which sets GPIO 4 to output and then toggles it high and low as fast as possible:
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
int gpio = 4;
char buf[100];
FILE* fd = fopen("/sys/class/gpio/export", "w");
fprintf(fd, "%d", gpio);
fclose(fd);
sprintf(buf, "/sys/class/gpio/gpio%d/direction", gpio);
fd = fopen(buf, "w"); fprintf(fd, "out");
fclose(fd);
sprintf(buf, "/sys/class/gpio/gpio%d/value", gpio);
fd = fopen(buf, "w");
for (;;) {
fd = fopen(buf, "w");
fprintf(fd, "1"); fclose(fd);
fd = fopen(buf, "w");
fprintf(fd, "0");
fclose(fd);
}
return 0;
}
The program first exports gpio4 and then writes out to its direction folder to set the line to output. After this the value file is open for writing and 1 and 0 are written to the file repeatedly. Notice the use of sprintf to create strings which incorporate the number of the gpio line you are using so that you can open the correct folder.
You might be puzzled by the loop that opens the file, writes a value and then closes it. Why not just keep the file open? The reason is that the file buffer isn't flushed unless the file is closed. This is the usual way of dealing with the problem, but it is not very fast and it is part of the reason that sysfs has a bad reputation.
If you try the program you will discover that the pulse train has a frequency of around 4kHz and a pulse width of 100µs on a Pi Zero and 18Khz and 28µs respectively on a Pi 4.
We can, however, do much better by not closing the file every time we write to it. Instead we can use fflush to flush the file buffer by changing the for loop to:
for (;;) {
fprintf(fd, "1");
fflush(fd);
fprintf(fd, "0");
fflush(fd);
}
The difference is quite amazing. Now, on a Pi Zero, the frequency is 130Khz and the pulse width is 3.6µs and, on a Pi 4, 450Khz and 1.1µs. This is still about 10 times slower than using the library, but useful for some applications.
Sysfs GPIO may be obsolete, but it was simple and logical.
Components
Click on the pictures to go to your local Amazon. The default is Amazon.com
Sensors
DHT22/AM2302 Digital Temperature and Humidity Sensor
DS18B20 1-Wire Temperature Sensor
MCP3008 AtoD Convertor
Pack of 2 8-Channel 10-Bit A/D Converters with SPI Serial Interface 2.7V
Serial Wireless WLAN WiFi Transceiver Module 1MB
Amazon.co.uk
Motors
775 Motor
Stepper Motor
Bipolar Junction Transitor
2N2222
TIP120 Darlington Transistor
(Pack of 20)
MOSFET
IRFZ44N
2N7000 Mosfet Transistor
MOSFET Button IRF520
Servo
SG90 9g Micro Servos
Pack of 4
H-Bridge
L298N Motor Dual H-Bridge
Pack of 4
SN754410
Electric Speed Controller
40A RC Brushless Motor Electric Speed Controller
SD Card Reader
Micro SD Card Module
5 pcs plus 40 female to male Dupont wires
Useful tools
The changes may be small, but we still need to keep up-to-date. How does moving to version 10 change C#? A look at three features that make it really worthwhile.
Raspberry Pi Pico
All you need to get started on your own projects are a few low-cost Picos plus some prototyping boards and jumper wires.
Luckily all of these items are readily available from Amazon.com and if you make a purchase via these links you won't pay any extra and we'll get a few cents.
The current models of the Pico are the second generation Pico 2 and the first generation Pico W. Due to there being a bug in the Pico 2 you might prefer to stick with the original Pico for the time being.
Unless you are happy to use a soldering iron choosing a Pico with pre-built headers is a good idea.
If your project is based on the Pico 2 or Pico W, an original Pico can be used as the debugging probe, although now you will find Pico Debugging probes commercially available.
The other tools you will need for the projects outlined in this book are some breadboards and some jumper wires and you'll also find a logic analyzer handy. Jump to the Tools page for the items we recommend.
The book refers to some specific sensors, servos and motors. For these go to Components.
Just click on the product pictures or text links to go direct to the product in your local Amazon region.
Raspberry Pi Pico 2
Freenove Basic Starter Kit for Raspberry Pi Pico 2
Raspberry Pi Pico W
Freenove Basic Starter Kit for Raspberry Pi Pico W
Raspberry Pi Pico
Freenove Basic Starter Kit for Raspberry Pi Pico
PicoProbe 
