Access GPIO from Linux user space

GPIO mean "General Purpose Input/Output" and is a special pin present in some chip that can be set as input or output and used to move a signal high or low (in output mode) or to get the signal current status (in input mode). Usually these pin are directly managed by kernel modules but there are an easy way to manage these pins also from user space.

Standard Linux kernel have inside a special interface allow to access to GPIO pins. Once executed kernel menuconfig you can easily verify is this interface is active in your kernel and, in case, enable them. The kernel tree path is the following:

Device Drivers  ---> GPIO Support  ---> /sys/class/gpio/... (sysfs interface)

If not, enable this feature and recompile the kernel before continue to read. The interface to allow working with GPIO is at the following filesystem path:


Basically if you want to work with a particular GPIO you must first to reserve it, set the input/output direction and start managing it. Once you reserved the GPIO and finished to use you need to free it for allow other modules or process to use them. This rule is valid in both cases you want to use GPIO from kernel level or user level.

Manage GPIO from command line or script

From the user level side this "operation" for reserve the GPIO is called "export" the GPIO. For make this export operation you simply need to echo the GPIO number you are interested to a special path as follow (change XX with the GPIO number you need):

echo XX > /sys/class/gpio/export

If operation successful (the possible case of operation failed is explained below) a new "folder" will show up in the GPIO interface path as example below:


This new "folder" will allow you to work with the GPIO you just reserved. In particular if you want to set the in/out direction you simply need to execute the following echo commands:

echo "out" > /sys/class/gpio/gpioXX/direction


echo "in" > /sys/class/gpio/gpioXX/direction

In case you set out direction you can directly manage the value of GPIO. You can make this operation by executing additional echo commands like:

echo 1 > /sys/class/gpio/gpioXX/value


echo 0 > /sys/class/gpio/gpioXX/value

Since GPIO is a single pin the possible states allowed are high (1) and low (0). In case you set in direction you can read the current pin value by using the following command:

cat /sys/class/gpio/gpioXX/value

Once finished to use your GPIO you can free it by make the same echo command but to different path:

echo XX > /sys/class/gpio/unexport

In case of GPIO folder not showed after export operation is very likely that the GPIO is already reserved by some module. For verify the current reserved GPIO map you must first verify if in your kernel is enabled the following feature:

Kernel configuration ---> Kernel hacking ---> Debug FS

As usual, if not enabled, enable it and recompile the kernel. The next step is to launch the following command line for mount debugfs:

mount -t debugfs none /sys/kernel/debug

and dump the current GPIO configuration by using:

cat /sys/kernel/debug/gpio

The output will show you the current list og reserved GPIO.

Manage GPIO from application

All these same operations can be made using a software application. Follow short lines of C code showing how the reproduce the same steps as above (remember to change XX with the GPIO number you want to use).

Reserve (export) the GPIO:

int fd;
char buf[MAX_BUF]; 
int gpio = XX;

fd = open("/sys/class/gpio/export", O_WRONLY);

sprintf(buf, "%d", gpio); 

write(fd, buf, strlen(buf));


Set the direction in the GPIO folder just created:

sprintf(buf, "/sys/class/gpio/gpio%d/direction", gpio);

fd = open(buf, O_WRONLY);

// Set out direction
write(fd, "out", 3); 
// Set in direction
write(fd, "in", 2); 


In case of out direction set the value of GPIO:

sprintf(buf, "/sys/class/gpio/gpio%d/value", gpio);

fd = open(buf, O_WRONLY);

// Set GPIO high status
write(fd, "1", 1); 
// Set GPIO low status 
write(fd, "0", 1); 


In case of in direction get the current value of GPIO:

char value;

sprintf(buf, "/sys/class/gpio/gpio%d/value", gpio);

fd = open(buf, O_RDONLY);

read(fd, &value, 1);

if(value == '0')
     // Current GPIO status low
     // Current GPIO status high


Once finished free (unexport) the GPIO:

fd = open("/sys/class/gpio/unexport", O_WRONLY);

sprintf(buf, "%d", gpio);

write(fd, buf, strlen(buf));


An important note you have to keep in mind if you plan to set or, more important, get the value of a GPIO through this way in continous mode. If you open the "value" file for get the current GPIO status (1 or 0) remember that, after the fist read operation, the file pointer will move to the next position in the file. Since this interface was made to be read from cat command the returned string will be terminated by the new line character (\n). This mean after the first "valid" read all the next read operation will return always the last character in the file, in this case only the new line '\n'. For obtain a correct status value for each read operation you simply have to set the file pointer at the beginning of the file before read by using the command below:

lseek(fp, 0, SEEK_SET);

You will not have this problem if you open and close GPIO value file every time you need to read but, as you can know, for continuous read introduce a short delay. Since these short lines of codes are only an example if you want to use them in your code remember add the control for error in open GPIO file.


  1. really good article........thanks

  2. really good .. thanks

  3. Okay. I dont see no userland. All operations need root.

  4. Cat /sys/class/gpio/gpioXX/value always prints 0 on my board. But when I use a voltage meter it shows the correct voltage.

  5. These gpio devices are not always automatic generated. You need to configure or "patch" the kernel for allow them to work as expected.

  6. Is there a good way to produce interrupts / or use blocking reads?(fread for example). Cause polling will kill the performance from my application

  7. Surely not at user level. You need to develop your own module running at kernel level for manage interrupt. Regarding the possibilty to have interrupt connected to gpio it depends from your hardware. If the cpu will allow it you'll have to configure it as indicated by datasheet.

  8. If a GPIO is already reserved, how can I control it from userspace?

  9. Sorry, if the GPIO is reserved by someone else you can not use it...

  10. Super-helpful article--thanks!

  11. Greattt!!!!!!!!! THNKS!!

  12. useful information. Thanks

  13. thanks. very helpful to all.:)

  14. Really useful information, Thanks.
    But can you please tell me, How to access GPIO from kernel space?

  15. Hi
    Kernel space have a different set of functions available for manage GPIO. Some of them are:

    int gpio_request(unsigned int gpio, const char *label);
    void gpio_free(unsigned int gpio);
    int gpio_direction_input(unsigned int gpio);
    int gpio_direction_output(unsigned int gpio, int value);
    int gpio_get_value(unsigned int gpio);
    void gpio_set_value(unsigned int gpio, int value);

    You can find more details googling around...

  16. i have a problem: i can correctly use the GPIO using shell scripts, but i can't do it using a software application in C. The problem it that i can't open the */value and */direction files.

  17. Sorry but you need to check the error code generated by the open fail operation.

  18. can you help me?
    i have a raspberry pi b + as a webserver, i can remotely get to it, push the button and i get 2 errors in the apache log files, permissions denied and premature end of script. i dont know if i have a httpd.conf file and i dont know if i need to change something in .htaccess but also please tell me real fast, if this set01.cgi script looks ok

    echo "1" > /sys/class/gpio/gpio4/value

  19. httpd.conf and .htaccess doesn't seem to be connected to the gpio access. The error "permission denied" mean your script is executed under some user that doesn't have enough privileges to access gpio fields. The easiest solution in this case is to "extened" permission of "/sys/class/gpio/gpio4/value" to the user or the group you currently run your script (using chmod command in server side).

  20. Great job! Thanks for article!

  21. Really useful informations, thank you !

  22. How do I set GPIO66 and GPIO68 for PWM use?

  23. Hi all,

    In my kernel it shows like that :

    root@ls2085aqds:/sys/class/gpio# ls
    export gpiochip384 gpiochip416 gpiochip448 gpiochip480 unexport
    root@ls2085aqds:/sys/class/gpio# echo 224 > export
    export_store: invalid GPIO 224
    -sh: echo: write error: Invalid argument

    Actually i need to toggle the GPIO2_24 th pin. I don't know how to access that pin and how to toggle that pin. can you help me please..?


  24. Label GPIO2_24 doesn't not automatically mean the GPIO number is 224. You have to check your hardware datasheet or how your kernel internally manage to number the GPIO you need...

  25. @Russ M: this post explain the standard direct interface for access GPIO from user space. PWM, for what I know, is another type of interface so I guess you need to manage the GPIO internally to kernel if you want to use PWM interface (but I'm not expert in using it than I'm not sure about that).

  26. how to continuously call the show function in sysfs by using c user program

  27. Hi,
    Excellent article. How can I find out which module has reserved a reserved gpio.
    I executed "cat /sys/kernel/debug/gpio". I have posted a portion of the output below.
    GPIOs 148-178, GPH:
    gpio-162 (? ) in lo
    gpio-163 (? ) in lo
    gpio-164 (? ) in lo
    gpio-165 (? ) in lo

    Please help.

  28. Sorry but I don't know if there is a way to know which module reserved GPIO, neved had this problem and currently I don't know how to help you...

  29. Hi all,

    In my kernel gpio directory it shows like that

    sys/class/gpio# ls
    export gpiochip384 gpiochip416 gpiochip448 gpiochip480 unexport

    here wt is the gpiochip384, 416, 448, 480 and how they are enabled here?

  30. Sorry, don't understand the question, what does it mean "how they are enabled here"? Remeber GPIO export operation can be "requested" not only by user space as described in this post but also internally by some kernel module itself...

  31. Hi
    In my kernel gpio directory shows gpiochip384, gpiochip416, gpiochip448, gpiochip480.

    I think
    gpiochip384 - GPIO1
    gpiochip416 - GPIO2
    gpiochip448 - GPIO3
    gpiochip480 - GPIO4

    I need to toggle one gpio pin ex.gpio4_24 (480+24=504)

    for that i need to echo 504 > export right..?

    i dont kw if its correct or wrong.. can u correct me pls..?

  32. Hi

    The problem here is only to know how to "calculate" the correct GPIO number based to your hardware. I don't know if your calculation is correct since it depends by the chipset you are working on. You have to check the datasheet of the chipset for know if the GPIO number is correct. Once got the correct number the export procedure is the same.

  33. For iMX6 to calculate which GPIO you need to export you can refer to :

  34. When i enter the command:
    sudo echo "17" > /sys/class/gpio/export
    i get the message:
    -bash: /sys/class/gpio/export: Permission denied
    Why is that?

  35. You need to have root privileges for make this operation. From the error message it seem you don't have...

  36. hi very useful article.
    i have a question
    in my kernel i have :GPIO 18 --> SDA and GPIO 19--> SCL
    how can i change the GPIOS to be :GPIO 19 --> SDA and GPIO 18--> SCL


  37. Teorically you can't since usually GPIO are physically harware mapped and the kernel report this mapping status. The only way I can see is to patch the kernel GPIO driver to make an "software inversion" but it would not be a good idea in any case. Please note if you want to manage an I2C bus communication from user space using kernel GPIO interface the communication will be really slow...

  38. thanks for your apply.
    how can i make that ?
    have you any information or tutorials ??

  39. The kernel is "customized" to work on your hardware. Maybe it will be possible to find some general tutorial (however I don't know) but the only way you have is to look into your kernel sources for find the module involved in GPIO communication with your hardware. Once found work on it.

  40. thanks for this valuable article
    i used the following commands to access the gpio on SAM9G25 microcontroller:
    #echo 66 > /sys/class/gpio/export
    #echo in > /sys/class/gpio/gpio66/direction
    #cat /sys/class/gpio/gpio66/value
    these commands run successfully on a linux with kernel version 3.6.9
    it doesn't work on the same development kit when I run emdebian with kernel version 3.11.6
    I got
    #echo in > /sys/class/gpio/gpio66/direction
    -bash: /sys/class/gpio/gpio66/direction: No such file or directory

  41. Kernel need to be "configured" to manage correctly specific board GPIO and expose them through gpio module interface. Required configuration can come from kernel board pinmuxing map, gpio module configuration and so on, I can not know the reasons, you have to check and configure correctly the kernel you plan to use for your project based to your hardware...

  42. I hv this GPIO debugging too:
    root@core9g25:~# cat /sys/kernel/debug/gpio
    GPIOs 0-31, platform/fffff400.gpio, fffff400.gpio:
    [w1] GPIOfffff400.gpio21: [gpio] set
    GPIOs 32-50, platform/fffff600.gpio, fffff600.gpio:
    [aria_led] GPIOfffff600.gpio8: [periph A]
    GPIOs 64-95, platform/fffff800.gpio, fffff800.gpio:
    GPIOs 96-117, platform/fffffa00.gpio, fffffa00.gpio:

  43. Great article!!! it helped me a lot!!

    Hey do you have something similar but for i2c?

  44. Thank you for the comment. About i2c didn't write anything because is already possible to found some good aricle around than I thought there was no need. Maybe I'll write something in the future... ^_^

  45. hi

    Great article.... helped me a lot for lemaker board. Recently only i started working on linux on lemaker board. now i am trying for interrupts, but i am not getting ..please guide me for complete interrupt part. led blinking need to do with switch in interrupt method.

    Thank you.

  46. This article explain how to manage with GPIO from user space but infortunately is not possible manage interrupts from user space. The only way is to develop a kernel driver. There is a free book titled "Linux device drivers" that you can read about develop your driver.

  47. Hi

    i found your article very helpful thanks for writing it. I want to blink the leds on the zed board, so when i tried the method the gpioxx folder is not created for me so i tried mount -t debugfs none /sys/kernel/debug but found that there is no debud folder in the kernel....
    any help will be appreciated.

  48. As written in the post have you verified the following feature is enabled on the kernel config?

    Kernel configuration ---> Kernel hacking ---> Debug FS

    Remember if you enable it you have to recompile the entire kernel for get it working.

    1. There is no debug fs in kernel hacking but instead
      Device drivers--> gpio support --> sys/class/gpio... (sys interface)
      Which is selected

  49. so in the kernel hacking there was no Debug FS in the list...

  50. Unfortunately linux kernel continuously change in structure based on distribution and so on. If you don't get your GPIO probably mean some driver reserved it or the use of that GPIO is not configured in your kernel. Kernel for ARM have to be configured through specific configuration files instructing the kernel itself about available devices in specific hardware. I can not help you in this case since variants can be infinite, you have to look into your kernel sources for try to understand why this specific GPIO is not allowed to be exported...

  51. yeah so i found out the debus fs it was in

    kernel configuration-->kernel hacking -->compile time checks and compile options-->debug fs

    but now it seems like the gpio is reserved and i cannot use it.
    i tried to mount it as
    mount -t sysfs sysfs /sys
    but it doesnt let me.

  52. Why "mount -t sysfs sysfs /sys"? The correct path for mount is "mount -t debugfs none /sys/kernel/debug". However keep in mind that you'll probably have to change something in the kernel code to have your GPIO available from user space...

  53. thanks it help me to understand how to switch on of my relay on rt5350f by olimex


Post a Comment

Popular posts from this blog

Launch an app from Android shell terminal

Qt 5 and " Failed to load platform plugin 'windows' " error