Embedded systems running Linux can use the gpiod library to read and write hardware GPIO values. The gpiod library has a header file and shared object library that user applications can include to add GPIO functionality. It works by interacting with the GPIO character devices in the /dev folder. These devices control the Linux kernel GPIO drivers which do the actual hardware reading and writing. User applications can also use the ioctl interface to these devices directly, but the gpiod interface is designed to be more straightforward to use. The gpiod library also has command line tools that may be installed to test GPIOs and control them through scripting.
The gpiod library organizes GPIO pins into lines and chips. A line is a single GPIO pin, and a chip is a hardware entity that may have multiple lines. There are object types that represent chips (struct gpiod_chip) and lines (struct gpiod_line). A program using the gpiod library will first obtain a pointer to a chip object using one of the ‘chip_open’ functions. Next, it will get lines from the chip using either the ‘get_line’ or ‘find_line’ method. The ‘get_line’ method takes an index, and the ‘find_line’ method takes the name of a line. The name is usually defined in the Linux device tree. Once the program has a pointer to a line object, it must request the line to use it. This step configures the line as an input or output, and ensures that only one process is using a GPIO line at a time. If the request function succeeds, then the program can call the ‘get_value’ and ‘set_value’ functions to read and write the GPIO value. The value is always either 0 or 1, corresponding to the voltage on the pin which is either low or high.
The following is an example program using the gpiod library:
File 1: hellogpiod.c
#include <stdio.h> #include <gpiod.h>
int main (int argc, char *argv[]) { // Chip is a GPIO expander on I2C bus 1 with address 0x34 struct gpiod_chip *chip = gpiod_chip_open_by_label(“1-0034”);
// Using indexes. The schematic tells which pin is connected to which // peripheral. struct gpiod_line *button = gpiod_chip_get_line(chip, 4); struct gpiod_line *led = gpiod_chip_get_line(chip, 2);
gpiod_line_request_input(button, “hellogpiod”); gpiod_line_request_output(led, “hellogpiod”, 0);
// Using a menu-driven interface printf(“1. Read Button\n”); printf(“2. LED On\n”); printf(“3. LED Off\n”); printf(“*: Quit\n”); while (1) { char line[16]; fgets(line, sizeof(line), stdin); if (line[0] == ‘1’) { int val = gpiod_line_get_value(button); printf(“Button is %s\n”, (val) ? “pressed” : “released”); } else if (line[0] == ‘2’) { gpiod_line_set_value(led, 1); } else if (line[0] == ‘3’) { gpiod_line_set_value(led, 0); } else { break; } }
// Close the chip before returning gpiod_chip_close(chip);
return 0; } |