How to control a GPIO in userspace

Revision as of 13:38, 7 June 2023 by Registered User (Update article with libgpiod v2)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Applicable for STM32MP13x lines, STM32MP15x lines

1. Purpose[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 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
gpiochip0 [GPIOA] (16 lines)
...
gpiochip9 [GPIOZ] (8 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 -c 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 -c gpiochip0 13  -->to get value of GPIO PA5
"13"=inactive                     -->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).
                                                     Comments

gpioset -c gpiochip0 14=0                -->get GPIO PA14 and set it low (green led on)
Ctrl + C
gpioset -c gpiochip0 14=1                -->get GPIO PA14 and set it high (green led off)
Ctrl + C
gpioset -t 500ms -c gpiochip0 14=active  -->get GPIO PA14 and toogle it every 500ms (green led blink) 
Ctrl + C

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

3.1. Purpose[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 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 source]

See Adding_Linux_user_space_applications to build this application.

4. References[edit source]