Last edited one month ago

How to control a GPIO in userspace

Applicable for STM32MP13x lines, STM32MP15x lines

1. Purpose[edit | edit source]

This article shows two ways to control a GPIO in userspace:

  • using libgpiod
  • by writing an application

2. GPIO control through libgpiod[edit | edit source]

libgpiod provides a C library and tools for interacting with the linux GPIO character device (gpiod stands for GPIO device). See the libgpiod repository[1] for further explanation.

  • gpiodetect
    • List all gpiochips present on the system
    • Usage:
 gpiodetect
gpiochip11 [GPIOZ] (16 lines)
...
gpiochip0 [GPIOA] (16 lines)
  • gpioinfo
    • list all lines of specified gpiochips, their names, consumers, and their settings
    • Usage:
gpioinfo
gpiochip11 - 16 lines:
       line   0:      unnamed       unused   input  active-high 
       line   1:      unnamed       unused   input  active-high
       ...

or

                                Comments

gpioinfo gpiochip0    -->to only print gpiochip0 lines
  • gpioget
    • Read the values of the specified GPIO lines (not valid if the line is already requested). The line will be then configured as input.
                                Comments

gpioget gpiochip0 5   -->to get value of GPIO PA5
0                             -->means the line is driven low
  • gpioset
    • Set the values of the specified GPIO lines, potentially keeping the lines exported, and wait until timeout, user input or signal (not valid if the line is already requested).
gpioset gpiochip0 14=0  -->to set GPIO PA14 low // green led on
gpioset gpiochip0 14=1  -->to set GPIO PA14 high // green led off

3. GPIO control through your own application[edit | edit source]

3.1. Purpose[edit | edit source]

This application toggles GPIO PA14 (GPIO bank A, line 14). On STM32MP15_Evaluation_boards or STM32MP15_Discovery_kits GPIO PA14 is connected to the green LED.

This application must be cross compiled with same toolchain as the Kernel.

3.2. Code[edit | edit source]

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>

#include <linux/gpio.h>

int main(int argc, char **argv)
{
	struct gpiohandle_request req;
	struct gpiohandle_data data;
	char chrdev_name[20];
	int fd, ret;

	strcpy(chrdev_name, "/dev/gpiochip0");

	/*  Open device: gpiochip0 for GPIO bank A */
	fd = open(chrdev_name, 0);
	if (fd == -1) {
		ret = -errno;
		fprintf(stderr, "Failed to open %s\n", chrdev_name);

		return ret;
	}

	/* request GPIO line: GPIO_A_14 */
	req.lineoffsets[0] = 14;
	req.flags = GPIOHANDLE_REQUEST_OUTPUT;
	memcpy(req.default_values, &data, sizeof(req.default_values));
	strcpy(req.consumer_label, "led_gpio_a_14");
	req.lines  = 1;

	ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
	if (ret == -1) {
		ret = -errno;
		fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n",
			ret);
	}
	if (close(fd) == -1)
		perror("Failed to close GPIO character device file");

	/*  Start led blinking */
	while(1) {

		data.values[0] = !data.values[0];
		ret = ioctl(req.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data);
		if (ret == -1) {
			ret = -errno;
			fprintf(stderr, "Failed to issue %s (%d)\n",
					"GPIOHANDLE_SET_LINE_VALUES_IOCTL", ret);
		}
		sleep(1);
	}

	/*  release line */
	ret = close(req.fd);
	if (ret == -1) {
		perror("Failed to close GPIO LINEHANDLE device file");
		ret = -errno;
	}
	return ret;
}

3.3. Build application[edit | edit source]

See Adding_Linux_user_space_applications to build this application.

4. References[edit | edit source]