How to control a GPIO in userspace
目录
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>