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.
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):
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:
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.
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.
No comments:
Post a Comment