How to control a GPIO in userspace

来自百问网嵌入式Linux wiki

Purpose

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

  • using libgpiod
  • by writing an application

GPIO control through libgpiod

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:
Board $> gpiodetect
gpiochip11 [GPIOZ] (16 lines)

<securetransclude src="ProtectedTemplate:ReviewsComments" params="W846.4 , JeromeB : gpiochip12 [stmfx-gpio] (24 lines) is also present"></securetransclude>{{#set:Has reviews comments=true}}

...
gpiochip0 [GPIOA] (16 lines)
  • gpioinfo
    • list all lines of specified gpiochips, their names, consumers, and their settings
    • Usage:
Board $>gpioinfo
gpiochip11 - 16 lines:
       line   0:      unnamed       unused   input  active-high 
       line   1:      unnamed       unused   input  active-high
       ...

or

                                Comments

Board $>gpioinfo gpiochip0    -->to only print gpiochip0 lines
  • gpioget
    • Read the values of the specified GPIO lines (not valid if the line is already requested)

<securetransclude src="ProtectedTemplate:ReviewsComments" params="W847.2 , JeromeB : Add a comment to inform that gpioget is set the line in Input - It cannot read the information after gpioset which set the line in Output"></securetransclude>{{#set:Has reviews comments=true}}

                                Comments

Board $>gpioget gpiochip0 5   -->to get value of GPIOA5
0                             -->means the line is driven low

<securetransclude src="ProtectedTemplate:ReviewsComments" params="W846.4 , JeromeB : As discuss with Gerald B., use GPIO PA5 instead of GPIOA5"></securetransclude>{{#set:Has reviews comments=true}}

  • gpioset
    • Set the values of the specified GPIO lines, potentially keeping the lines exported, and wait until timeout, user input or signal.
Board $>gpioset gpiochip3 8=1  -->to set GPIOD8 high

<securetransclude src="ProtectedTemplate:ReviewsComments" params="W846.4 , JeromeB : As discuss with Gerald B., use GPIO PD8 instead of GPIOD8"></securetransclude>{{#set:Has reviews comments=true}} <securetransclude src="ProtectedTemplate:ReviewsComments" params="W846.4 , JeromeB : As discuss please add a comment on gpioset which cannot be used when it used by pin-controller"></securetransclude>{{#set:Has reviews comments=true}} <securetransclude src="ProtectedTemplate:ReviewsComments" params="W846.4 , JeromeB : As discuss with Gerald B., add a link to 'green LED'. The customer can try 'gpioset' command with one LED"></securetransclude>{{#set:Has reviews comments=true}}

GPIO control through your own application

Purpose

This application toggles GPIO_A_14 (GPIO bank A, line 14). On STM32MP15_Evaluation_boards or STM32MP15_Discovery_kits GPIO_A_14 is connected to the green LED. <securetransclude src="ProtectedTemplate:ReviewsComments" params="W846.4 , JeromeB : As discuss with Gerald B., use GPIO PA14 instead of GPIO_A_14"></securetransclude>{{#set:Has reviews comments=true}} This application must be cross compiled with same toolchain as the Kernel.

Code

<securetransclude src="ProtectedTemplate:ReviewsComments" params="W915.5 , OlivierG : Code was not compiling. Fix done below"></securetransclude>{{#set:Has reviews comments=true}}

#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;
}

Build application

See Adding_Linux_user_space_applications to build this application.

References

<securetransclude src="ProtectedTemplate:PublicationRequestId" params="8795 | 2018-09-18 | PhilipS"></securetransclude>