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:

/sys/class/gpio/

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:

/sys/class/gpio/gpioXX/

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

or

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

or

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));

close(fd);

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); 

close(fd);

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); 

close(fd);

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
}
else
{
     // Current GPIO status high
}

close(fd);

Once finished free (unexport) the GPIO:

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

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

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

close(fd);

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.

21 Comments:

Awesome :)

Anonymous
June 27, 2013 at 11:24 PM comment-delete

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

Jagdish
July 19, 2013 at 3:23 AM comment-delete

really good .. thanks

Anonymous
July 21, 2013 at 7:33 AM comment-delete

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

Anonymous
August 15, 2013 at 5:55 AM comment-delete

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

September 12, 2013 at 4:10 AM comment-delete

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

September 12, 2013 at 12:47 PM comment-delete

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

Anonymous
November 6, 2013 at 7:58 AM comment-delete

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.

November 6, 2013 at 9:22 AM comment-delete

Great, Thanks...

February 7, 2014 at 3:27 AM comment-delete

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

Anonymous
February 20, 2014 at 2:24 AM comment-delete

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

February 20, 2014 at 3:13 AM comment-delete

Ok, thanks!

Anonymous
February 20, 2014 at 3:50 AM comment-delete

Super-helpful article--thanks!

Anonymous
March 16, 2014 at 11:13 AM comment-delete

Greattt!!!!!!!!! THNKS!!

Anonymous
May 15, 2014 at 11:34 AM comment-delete

useful information. Thanks

Anonymous
May 29, 2014 at 2:01 AM comment-delete

thanks. very helpful to all.:)

June 8, 2014 at 10:37 PM comment-delete

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

uzair
June 12, 2014 at 10:01 PM comment-delete

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...

June 12, 2014 at 11:56 PM comment-delete

Nice!

Anonymous
October 10, 2014 at 2:55 AM comment-delete

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.

Anonymous
October 11, 2014 at 3:24 AM comment-delete

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

October 11, 2014 at 8:49 AM comment-delete

Post a Comment