Difference between revisions of "How to control a GPIO in userspace"

[checked revision] [quality revision]
m
m
 

1 Purpose[edit]

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

  • using libgpiod
  • by writing an application

2 GPIO control through libgpiod[edit]

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]

3.1 Purpose[edit]

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]

#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]

See Adding_Linux_user_space_applications to build this application.

4 References[edit]


==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<ref>[https://github.com/brgl/libgpiod libgpiod repository]</ref> for further explanation.

*'''gpiodetect'''
**List all gpiochips present on the system
**Usage:
 {{Board$}} gpiodetect
 gpiochip11 [GPIOZ] (16 lines){{ReviewsComments| W846.4 , JeromeB : gpiochip12 [stmfx-gpio] (24 lines) is also present }} 
{{ReviewsComments| W2024.3 , AlexT : Not present on all boards. I'll keep it as it is }} 

 ... ...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
                                 {{Highlight|Comments}}

 {{Board$}}gpioinfo gpiochip0    {{Highlight|-->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.{{ReviewsComments| 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}}
{{ReviewsComments| W2024.3 , AlexT : ok done }} 
                                 {{Highlight|Comments}}

 {{Board$}}gpioget gpiochip0 5   {{Highlight|-->to get value of GPIO PA5}}
 0                             {{Highlight|-->means the line is driven low}}{{ReviewsComments| W846.4 , JeromeB : As discuss with Gerald B., use GPIO PA5 instead of GPIOA5}}
{{ReviewsComments| W2024.3 , AlexT : ok done }} 

*'''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).
 {{Board$}}gpioset gpiochip0 14=0  {{Highlight|-->to set GPIO PA14 low // green led on}}
 {{Board$}}gpioset gpiochip0 14=1  {{Highlight|-->to set GPIO PA14 high // green led off}}{{ReviewsComments| W846.4 , JeromeB : As discuss with Gerald B., use GPIO PD8 instead of GPIOD8}}
{{ReviewsComments| W2024.3 , AlexT : ok done }} 
{{ReviewsComments| W846.4 , JeromeB : As discuss please add a comment on gpioset which cannot be used when it used by pin-controller}}
{{ReviewsComments| W2024.3 , AlexT : ok done }} 
{{ReviewsComments| W846.4 , JeromeB : As discuss with Gerald B., add a link to 'green LED'. The customer can try 'gpioset' command with one LED}}
{{ReviewsComments| W2024.3 , AlexT : ok done }} 

==GPIO control through your own application==
===Purpose===
This application toggles GPIO PA14 (GPIO bank A, line 14). On [[STM32MP15_Evaluation_boards_-_getting_started | STM32MP15_Evaluation_boards]] or [[STM32MP15_Discovery_kits_-_getting_started | STM32MP15_Discovery_kits]] GPIO PA14 is connected to the green LED.{{ReviewsComments| W846.4 , JeromeB : As discuss with Gerald B., use GPIO PA14 instead of GPIO_A_14}}
{{ReviewsComments| W2024.3 , AlexT : ok done }} 

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

===Code===
<syntaxhighlight lang="c">

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


===Build application===
See [[STM32MP1_Developer_Package#Adding_Linux_user_space_applications|Adding_Linux_user_space_applications]] to build this application.

==References==<references/>

<noinclude>

[[Category:IOs pin management|5]]
{{PublicationRequestId | 8795 | 2018-09-18 | PhilipS}}</noinclude>
Line 12: Line 12:
 
  {{Board$}} gpiodetect
 
  {{Board$}} gpiodetect
 
  gpiochip11 [GPIOZ] (16 lines)
 
  gpiochip11 [GPIOZ] (16 lines)
{{ReviewsComments| W846.4 , JeromeB : gpiochip12 [stmfx-gpio] (24 lines) is also present }}
 
{{ReviewsComments| W2024.3 , AlexT : Not present on all boards. I'll keep it as it is }}
 
 
 
  ...
 
  ...
 
  gpiochip0 [GPIOA] (16 lines)
 
  gpiochip0 [GPIOA] (16 lines)
Line 34: Line 31:
 
*'''gpioget'''
 
*'''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.
 
**Read the values of the specified GPIO lines (not valid if the line is already requested). The line will be then configured as input.
{{ReviewsComments| 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}}
 
{{ReviewsComments| W2024.3 , AlexT : ok done }}
 
 
 
                                 {{Highlight|Comments}}
 
                                 {{Highlight|Comments}}
 
   
 
   
 
  {{Board$}}gpioget gpiochip0 5  {{Highlight|-->to get value of GPIO PA5}}
 
  {{Board$}}gpioget gpiochip0 5  {{Highlight|-->to get value of GPIO PA5}}
 
  0                            {{Highlight|-->means the line is driven low}}
 
  0                            {{Highlight|-->means the line is driven low}}
{{ReviewsComments| W846.4 , JeromeB : As discuss with Gerald B., use GPIO PA5 instead of GPIOA5}}
 
{{ReviewsComments| W2024.3 , AlexT : ok done }}
 
   
 
*'''gpioset'''
 
*'''gpioset'''
Line 48: Line 40:
 
  {{Board$}}gpioset gpiochip0 14=0  {{Highlight|-->to set GPIO PA14 low // green led on}}
 
  {{Board$}}gpioset gpiochip0 14=0  {{Highlight|-->to set GPIO PA14 low // green led on}}
 
  {{Board$}}gpioset gpiochip0 14=1  {{Highlight|-->to set GPIO PA14 high // green led off}}
 
  {{Board$}}gpioset gpiochip0 14=1  {{Highlight|-->to set GPIO PA14 high // green led off}}
{{ReviewsComments| W846.4 , JeromeB : As discuss with Gerald B., use GPIO PD8 instead of GPIOD8}}
 
{{ReviewsComments| W2024.3 , AlexT : ok done }}
 
{{ReviewsComments| W846.4 , JeromeB : As discuss please add a comment on gpioset which cannot be used when it used by pin-controller}}
 
{{ReviewsComments| W2024.3 , AlexT : ok done }}
 
{{ReviewsComments| W846.4 , JeromeB : As discuss with Gerald B., add a link to 'green LED'. The customer can try 'gpioset' command with one LED}}
 
{{ReviewsComments| W2024.3 , AlexT : ok done }}
 
   
 
==GPIO control through your own application==
 
==GPIO control through your own application==
 
===Purpose===
 
===Purpose===
 
This application toggles GPIO PA14 (GPIO bank A, line 14). On [[STM32MP15_Evaluation_boards_-_getting_started | STM32MP15_Evaluation_boards]] or [[STM32MP15_Discovery_kits_-_getting_started | STM32MP15_Discovery_kits]] GPIO PA14 is connected to the green LED.
 
This application toggles GPIO PA14 (GPIO bank A, line 14). On [[STM32MP15_Evaluation_boards_-_getting_started | STM32MP15_Evaluation_boards]] or [[STM32MP15_Discovery_kits_-_getting_started | STM32MP15_Discovery_kits]] GPIO PA14 is connected to the green LED.
{{ReviewsComments| W846.4 , JeromeB : As discuss with Gerald B., use GPIO PA14 instead of GPIO_A_14}}
 
{{ReviewsComments| W2024.3 , AlexT : ok done }}
 
   
 
This application must be cross compiled with same toolchain as the Kernel.
 
This application must be cross compiled with same toolchain as the Kernel.