Raspberry Pi boards have 40 pins (26 in the first models) that can be programmed using a Memory-Mapped Input-Output (MMIO) mechanism. MMIO allows developers to query or set the state of pins by reading or writing specific addresses in the physical memory of the system.
In the Using specialized memory recipe in Chapter 6, Memory Management, we learned how to access MMIO registers. In this recipe, we are going to offload the MMIO address's manipulations to the specialized library, wiringPi. It hides all the complexities of memory mapping and finding proper offsets under the hood, exposing a clean API instead.
This library is pre-installed on Raspberry Pi boards, so to simplify the build process, we are going to build the code directly on the board instead of using cross-compilation. Unlike other recipes, our build rules do not mention a cross compiler—we are going to use the native ARM compiler on the board. We only add a dependency to the wiringPi library:
target_link_libraries(gpio wiringPi)
The code of this example is a modification of the wiringPi example for blinking an LED. Firstly, we initialize the wiringPi library:
if (wiringPiSetup () < 0) {
throw std::runtime_error("Failed to initialize wiringPi");
}
Next, we enter the endless loop. On each iteration, we set the pin to the HIGH state:
digitalWrite (kLedPin, HIGH);
After the 500 ms delay, we set the same pit to the LOW state and add another delay:
digitalWrite (kLedPin, LOW);
std::cout << "LED off" << std::endl;
std::this_thread::sleep_for(500ms) ;
We configured our program to use pin 0, which corresponds to GPIO.0 or pin 17 of the BCM2835 chip of Raspberry Pi:
const int kLedPin = 0;
If an LED is connected to this pin, it will blink, turning on for 0.5 seconds and then off for another 0.5 seconds. By tweaking the delays in the loop, you can change the blinking pattern.
Since the program enters an endless loop, we can terminate it at any time by pressing Ctrl + C in the SSH console; otherwise, it will run forever.
When we run the application, we only see the following output:
We log when we turn the LED on or off, but to check that the program actually works, we need to look at the LED connected to the pin. If we follow the wiring instructions, we can see how it works. While the program is running, the LED on the boards blinks synchronously with the program output:
We are able to control simple devices connected directly to the CPU pins without writing complicated device drivers.