GPIO
General Purpose Input/Output (GPIO) is a generic pin on a integrated circuit chip whose behavior (including whether it is an input or output pin) can be controlled / programmed by the user at run time.
Overview
GPIO pins have no special purpose defined, and usually go unused by default. The idea is that sometimes the system integrator building a full system that uses the chip might find it useful to have a handful of additional digital control lines, and having these available from the chip can save the hassle of having to arrange additional circuitry to provide them.
A GPIO port is a group of GPIO pins (typically 8 GPIO pins) arranged in a group, and treated as a single port.
Accessing the GPIO pins through sysfs with mainline kernel
The GPIO pins can be accessed from user space using sysfs. To enabled this you need the following kernel option enabled: CONFIG_GPIO_SYSFS
Device Drivers ---> GPIO Support ---> /sys/class/gpio/... (sysfs interface)
To access a GPIO pin you first need to export it with
echo XX > /sys/class/gpio/export
with XX being the number of the desired pin. To obtain the correct number you have to calculate it from the pin name (like PH18)[1]:
(position of letter in alphabet - 1) * 32 + pin number
E.g for PH18 this would be ( 8 - 1) * 32 + 18 = 224 + 18 = 242 (since 'h' is the 8th letter).
Alternatively, you can read the mapping from debugfs with
cat /sys/kernel/debug/pinctrl/*/pinmux-pins
After you have successfully exported the pin you can access it through /sys/class/gpio/gpio*NUMBER* (in case of PH18 it's /sys/class/gpio/gpio242).
With /sys/class/gpio/gpio*NUMBER*/direction you must set the pin to out or in using
echo "out" > /sys/class/gpio/gpio*NUMBER*/direction
and only then you can read/write the value with /sys/class/gpio/gpio*NUMBER*/value.
When you are done unexport the pin with
echo XX > /sys/class/gpio/unexport
Accessing the GPIO pins through character device with mainline kernel
The sysfs GPIO interface is now deprecated in favor of character devices /dev/gpiochipX
Verify that your system supports it with
ls /dev/gpiochip*
The easiest way to access the pins is with libgpiod and the set of tools it includes. https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/
You can read a pin with
sudo gpioget gpiochip0 XX
where XX is the pin number, calculated the same way as in the sysfs method (see section above).
Set a pin value with
sudo gpioset gpiochip0 XX=value
where value is 0 or 1. Note the value will return to default after gpioset exits. Consult gpioset --help for further options.
Monitor the state of a pin with
sudo gpiomon gpiochip0 XX
You can use gpioinfo to see how the pins are configured, but
cat /sys/kernel/debug/pinctrl/*/pinmux-pins
give you also the pin mapping (see section above).
Accessing the GPIO pins through sysfs on sunxi-3.4
This is subject to changing without notice :( Anyway I found this to hold true on 3.4.103:
First you need to make sure that script.bin has some pins designated for gpio or when you load the appropriate module it will complain that no gpio pins are configured in script.bin.
[gpio_para] gpio_used= 1 gpio_num=12 gpio_pin_1= port:PE00 gpio_pin_2= port:PE01 gpio_pin_3= port:PE02 gpio_pin_4= port:PE03 gpio_pin_5= port:PE04 gpio_pin_6= port:PE05 gpio_pin_7= port:PE06 gpio_pin_8= port:PE07 gpio_pin_9= port:PE08 gpio_pin_10= port:PE09 gpio_pin_11= port:PE10 gpio_pin_12= port:PE11
Reading the FEX tutorial in the section concerning the Port Definitions would allow you to set pull up/down on the input ports.
Next you need to load the appropriate module:
modprobe gpio-sunxi
Now export the pins
for A in 1 2 3 4 5 6 7 8 9 10 11 12; do echo "$A" > /sys/class/gpio/export ; done
This should make some links appear in sys/class/gpio/:
root@headless2:/sys/class/gpio# ls -l total 0 --w------- 1 root root 4096 Jan 10 00:12 export lrwxrwxrwx 1 root root 0 Jan 10 00:12 gpio10_pe9 -> ../../devices/platform/gpio-sunxi/gpio/gpio10_pe9/ lrwxrwxrwx 1 root root 0 Jan 10 00:12 gpio11_pe10 -> ../../devices/platform/gpio-sunxi/gpio/gpio11_pe10/ lrwxrwxrwx 1 root root 0 Jan 10 00:12 gpio12_pe11 -> ../../devices/platform/gpio-sunxi/gpio/gpio12_pe11/ lrwxrwxrwx 1 root root 0 Jan 10 00:11 gpio1_pe0 -> ../../devices/platform/gpio-sunxi/gpio/gpio1_pe0/ lrwxrwxrwx 1 root root 0 Jan 10 00:12 gpio2_pe1 -> ../../devices/platform/gpio-sunxi/gpio/gpio2_pe1/ lrwxrwxrwx 1 root root 0 Jan 10 00:12 gpio3_pe2 -> ../../devices/platform/gpio-sunxi/gpio/gpio3_pe2/ lrwxrwxrwx 1 root root 0 Jan 10 00:12 gpio4_pe3 -> ../../devices/platform/gpio-sunxi/gpio/gpio4_pe3/ lrwxrwxrwx 1 root root 0 Jan 10 00:12 gpio5_pe4 -> ../../devices/platform/gpio-sunxi/gpio/gpio5_pe4/ lrwxrwxrwx 1 root root 0 Jan 10 00:12 gpio6_pe5 -> ../../devices/platform/gpio-sunxi/gpio/gpio6_pe5/ lrwxrwxrwx 1 root root 0 Jan 10 00:12 gpio7_pe6 -> ../../devices/platform/gpio-sunxi/gpio/gpio7_pe6/ lrwxrwxrwx 1 root root 0 Jan 10 00:12 gpio8_pe7 -> ../../devices/platform/gpio-sunxi/gpio/gpio8_pe7/ lrwxrwxrwx 1 root root 0 Jan 10 00:12 gpio9_pe8 -> ../../devices/platform/gpio-sunxi/gpio/gpio9_pe8/ lrwxrwxrwx 1 root root 0 Jan 10 00:10 gpiochip1 -> ../../devices/platform/gpio-sunxi/gpio/gpiochip1/ --w------- 1 root root 4096 Jan 10 00:09 unexport root@headless2:/sys/class/gpio#
Set the desired direction
echo out > /sys/class/gpio/gpio12_pe11/direction
You may now output something
echo 1 > /sys/class/gpio/gpio12_pe11/value
Reading the kernel documentation on sysfs gpio can be a good reading and will give you ideas on how to use the other features available. Documentation/gpio/sysfs.txt
You need root privileges to do this. If you don't want this, you may try the following:
Add a group gpio and add the desired user to this group. Then add a file /etc/udev/rules.d/97-gpio.rules
# /etc/udev/rules.d/97-gpio.rules SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c '\ chown -R root:gpio /sys/class/gpio && chmod -R 0770 /sys/class/gpio &&\ chown -R root:gpio /sys/devices/platform/soc && chmod -R 0770 /sys/devices/platform/soc'"
or /etc/udev/rules.d/96-gpio.rules
# /etc/udev/rules.d/96-gpio.rules SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c '\ chown -R root:gpio /sys/class/gpio && chmod -R 0770 /sys/class/gpio &&\ chown -R root:gpio /sys/devices/platform/sunxi-pinctrl/gpio && chmod -R 0770 /sys/devices/platform/sunxi-pinctrl/gpio'"
Try which rule runs better.
Example: Controlling GPIO on Olimex's A13-OLinuXino (sunxi-3.4)
What do you need:
- Kernel with CONFIG_GPIO_SUNXI=y If you set the option to m you should take care of loading the module. There was previously SUN4I_GPIO_UGLY option which is now deprecated.
- bin2fex and fex2bin tools from sunxi-tools.
The Process
- Open a console and connect to your A13.
- Make a directory in /media: mkdir /media/nanda
- Mount the nanda there: mount /dev/nanda /media/nanda
- Copy the file /media/nanda/script.bin to your PC. This file configures the A13.
- Now we need to make it a text file so we use the bin2fex. On a linux machine go into the directory where you compiled the sunxi-tools and from there type this: ./bin2fex /path/to/script.bin > script.fex This will create a text file named script.fex in your current directory.
- Now we need to edit it with a text editor and define the pins that are going to be used for GPIO. Look for a section named "[gpio_para]" if there is no such section (probably there will not be) go to the bottom of the file and add it like this:
- gpio_used
- Do you want to use any GPIO at all? 1=yes 0=no
- gpio_num
- The number of total gpio ports you want / pins you are using?
- gpio_pin_$Num = PXN<Z>
- Where $Num is the GPIO pin number. starting from 1.
- PXN is the name of the pin you want to use
- Z is pin a output or a input? 0 for input or 1 for output.
- Now we need to make the modified fex file back to bin format so again from the directory where you compiled the sunxi-tools: ./fex2bin script.fex > script.bin
- Now put back the script.bin on the board and overwrite the old script.bin in /media/nanda
- Unmount the /media/nanda: umount /media/nanda
- Reboot the A13
- Log back in and now if you did everything correct in /sys/devices/virtual/misc/sun4i-gpio/pin you will see "pe11"
- If you solder a LED and a resistor to the right pin and ground (for example pin 2) http://linux-sunxi.org/images/e/e7/A13-olinuxino-brd.png and type: "echo 1 > /sys/devices/virtual/misc/sun4i-gpio/pin/pe11" the LED will light and "echo 0 > /sys/devices/virtual/misc/sun4i-gpio/pin/pe11" will turn it off.
[gpio_para] gpio_used = 1 gpio_num = 1 gpio_pin_1 = port:PE11<1>
In this example I used pin PE11 which is pin number 12 on the GPIO-2. The PXN names can be found here: http://linux-sunxi.org/A13-OLinuXino#Expansion_ports. TO CHECK: when I used PE11 this pin is part of the [csi0_para] so I went to [csi0_para] and made csi_used = 0 Not sure if this is needed, but I think it is.
C/C++ program
Lib gpio_lib.h
compiler eclipse c/c++
steps:
1)
#define PNXX SUNXI_GPN(XX)
2)
if(SETUP_OK!=sunxi_gpio_init()){ printf("Failed to initialize GPIO\n"); return -1; }
3)
if(SETUP_OK!=sunxi_gpio_set_cfgpin(PNXX,DIRECTION)){ printf("Failed to config GPIO pin\n"); return -1; }
PNXX: ex.PD01
DIRECTION: OUTPUT,INPUT
4)
if(sunxi_gpio_output(PNXX,LEVEL)){ printf("Failed to set GPIO pin value\n"); return -1; }
LEVEL: HIGH,LOW
5)
sunxi_gpio_cleanup();
Other stuff
Olimex wrote another article on the subject at http://olimex.wordpress.com/2012/10/23/a13-olinuxino-playing-with-gpios/