GPIO lines are single-bit input/output connections that can interface the CHIP board to external devices.
GPIO "lines" are sometimes referred to as "pins", a reference to the "pins" of an integrated circuit chip. In this article we use the term "line" instead of "pin", except where we forget. :-)
There are multiple classes of GPIO lines:
- CSI - GPIO lines handled directly by CHIP's CPU. Access to CSI lines is relatively fast.
- XIO - Expanded GPIO lines handled by a PCF8574A device, connected to the CPU via I2C bus. Access to XIO is relatively slow.
The pins and their capabilities are defined in the kernel sources in drivers/pinctrl/sunxi/pinctrl-sun5i-a13.c
All GPIO lines are compatible with 3.3V logic only -- they are not 5V tolerant. (The LRADC line is only 2V tolerant.)
Command Line and Shell Script Access
By "low-level" I mean directly accessing the sysfs pseudo files under "/sys/class/gpio". Each GPIO line has a numeric ID value associated with it. Be aware that from CHIP OS 4.3 and CHIP OS 4.4, some of those numeric IDs changed (specifically, the XIOs). NTC has warned the community that those numbers can change again, but that there is a simple algorithm (here and here()) to derive those IDs at run-time.
Some instructional material for low-level access is available [here](https://bbs.nextthing.co/t/compile-hello-world/583/10).
For example: to test gpio on the LCD_CLK line:
$ sudo bash # Become root. # cd /sys/class/gpio # echo "120" > export # This writes the three ascii characters '1', '2', and '0' to "/sys/class/gpio/export" which makes the LCD_CLK line available for use. # cat gpio120/direction # This displays the ascii contents of "/sys/class/gpio/gpio120/direction". in # echo "out" > gpio120/direction # echo "1" > gpio120/value # e.g. an "active-high" LED circuit connected to that line will light up. # echo "0" > gpio120/value # LED off. # echo "120" > unexport # Makes the line unavailable for use. NOTE: leaves the line in output mode with value 0. # exit # Exit root.
The reason for "unexporting" a line is to make it available for some other program to export and use. The convention is that a program should first export, and if the export operation fails, it should assume that line is already being used by some other program.
There is now a simple shell package you can download which provides a higher-level of access to the GPIO lines. It allows symbolic specification of a GPIO (i.e. "LCD_CLK" instead of "120", and it derives the correct numbers at run-time, making your shell scripts portable across different versions of CHIP OS. See this post.
You can find a C library for accessing the GPIO in the Software Libraries page.
For GPIO access by Python programs, see the packages in the Software Libraries page. Note that the Python library encourages the use of symbolic GPIO line names rather than numeric.
An Arduino style methode: https://bbs.nextthing.co/t/i-wrote-a-gpio-library-for-python-you-guys-can-use/3029
A more complex one: (Adafruit Library hack) https://bbs.nextthing.co/t/adafruit-gpio-library-for-chip/2696
GPIO Line Numbers
GPIO lines are generally accessed by software via the Sysfs driver: "/sys/class/gpio". This driver associates a number with each GPIO line according to the following excellent table posted by xtacocorex. Note that CHIP OS 4.3 numbers the XIO lines starting at 408, but CHIP OS 4.4 numbers them starting at 1016. NTC has already warned that the XIO numbers may change again, and recommends deriving the numbers at run-time rather than using absolute numbers. If you want to write programs or shell scripts that access GPIO, it is suggested that you use a package that allows symbolic name access rather than using the line numbers.
|NAME||GPIONUM||NAME||GPIONUM||NAME||GPIONUM||NAME||GPIONUM (on expander)|
|PWM0||34||LCD-D13||109||CSIHSYNC||130||XIO-P0||408 (4.3) or 1016 (4.4)|
|AP-EINT3||35||LCD-D14||110||CSIVSYNC||131||XIO-P1||409 (4.3) or 1017 (4.4)|
|TWI1-SCK||47||LCD-D15||111||CSID0||132||XIO-P2||410 (4.3) or 1018 (4.4)|
|TWI1-SDA||48||LCD-D18||114||CSID1||133||XIO-P3||411 (4.3) or 1019 (4.4)|
|TWI2-SCK||49||LCD-D19||115||CSID2||134||XIO-P4||412 (4.3) or 1020 (4.4)|
|TWI2-SDA||50||LCD-D20||116||CSID3||135||XIO-P5||413 (4.3) or 1021 (4.4)|
|LCD-D2||98||LCD-D21||117||CSID4||136||XIO-P6||414 (4.3) or 1022 (4.4)|
|LCD-D3||99||LCD-D22||118||CSID5||137||XIO-P7||415 (4.3) or 1023 (4.4)|
The numbers in this table are just a conversion from the gpio's P-code. This code can be found in the line overview section of the hardware Information page. You'll find for example that the LCD_CLK line is connected to a line on the processor which also serves gpio PD24. This is always of the form P[letter][number]. Insert these in the following formula:
(place in alphabet of [letter] - 1) * 32 + [number]
So line PD24 becomes
('D' - 'A') * 32 + i = (4 - 1) * 32 + 24 = 120
Note: this doesn't count for the XIO lines in the last column, as these are not directly connected to the R8 processor.
Memory Mapped Access
For those GPIO lines which are handled directly by CHIP's main CPU, it is possible to bypass the Sysfs kernel driver "/sys/class/gpio". Since this avoids system calls into the Linux kernel, it provides much faster access. Information and source code for a user-mode driver can be found in infrapro's message board post.
But that speed comes at a cost. The user-mode driver essentially conflicts with the kernel driver. I.e. the kernel driver will continue to assume that it knows the state of the hardware, which the user-mode driver is changing out from under it. In theory, this could even lead to system crashes, although I think the risk of this is minimal so long as you go with one or the other and never both.
Also, notice that the kernel driver is designed to allow different applications (processes) to access different GPIO lines independently from each other. This user-mode driver basically only lets a single application access a set of 8 lines.
The several access methods above have different speeds.
Using C through the sysfs driver (/sys/class/gpio/...) to generate a square wave:
- 4kHz: The gpio line marked XIO on the terminal block are on an expansion chip, and are really slow. Note that it requires 2 writes to make the square wave, so the number of accesses per second is double the square wave frequency, i.e. 8,000 writes per second.
- 177kHz: The non-XIO gpio lines (like CSI) directly on the CPU are faster.
Using Memory Mapped access:
- 530kHz: Although user Infrapro speaks about way higher speeds (>24MHz!). Note: Somehow this code doesn't run when compiled using optimize flags -Ox..., TBD
Unix "user-mode" processes (i.e. not in the kernel) do not have deterministic timing. See this topic for some empirical measurement of random timing delays.
Not all gpio pins support interrupts. Whether a pin supports interrupts can be seen by the presence of an "edge" file (e.g. /sys/class/gpio/<pin>/edge) after exporting the pin. The following pins support interrupts: XIO-P0 thru XIO-P7, AP-EINT1, AP-EINT3, CSIPCK, CSICK.
The XIO pin interrupts are for state changes only and may miss edges. The PCF8574 I/O extender only provides an interrupt on pin change and the driver then compares the current state of the inputs with the last seen state to determine which pin changed. This means that it can miss short pulses. In addition, the current driver does not respect the direction of change and instead delivers a signal on every change, meaning that setting the edge detection to "rising" or "falling" acts as if it were set to "both".
Maximum input voltage: 3.8V
- input: very high impedance float (no easily detectable conductivity to 3.3v or ground).
- output 1: active 3.26v through equiv 72 ohm internal resistance. 
- output 0: active ground through low internal resistance. 
 - 1K load to ground drops V to 3.05V. Other loads are reasonably consistent with ~72 ohms.
 - 1K load to 3.3v only raises V a few millivolts.
I would expect some variation across CHIPs; don't count on the specific values shown to be precisely replicated.
Note that I would expect most of the other GPIO lines to be the same as the CSI lines, with the notable exception of XIO lines.
Input is 3.3V tolerant only.
TL;DR; The XIO lines use a modified open-drain (sometimes called open-collector) output driver. There is no direction setting for the pins. Instead, outputting a "1" causes a weak pull-up current source to pull the line high while outputting a "0" causes a strong pull-down transistor to pull the line low. Input is achieved by outputting a "1" and letting the external source override the weak pull-up.
The pins use a modified open-drain output in that the pull-up is a weak current source (30uA to 300uA according to the datasheet), and that when outputting a "1" the chip very briefly activates a strong transistor to initially pull the line high (this is an approx 100ns pulse when driving the i2c bus at 10 Mhz).
The PCF8574 chip that implements the XIO lines can generate an interrupt when any of the pins has a value that is different from the last read or written value. See the section on interrupts for details.
Input is 3.3V tolerant only.
The XIO lines do not source any significant amount of current, only about 40-60 uA (by "source" I mean driving an "active-high" circuit). They can, however, *sink* up to 25 mA (i.e. "active-low"). The XIO lines are typically used active-low.
- input: 47 uA (microamp) current source. 3.26 v for open circuit. 
- output 1: same as input.
- output 0: active ground through low internal resistance.
 A current source means that, within the constraints of a 3.3v supply, the line will vary its output voltage to sustain a constant 47 uA through whatever load is placed there. I put a 47K resistor to ground and the output voltage was a bit over 2 volts (E = I * R = 47e-6 * 47e3 = 2.2). I put a 10K resistor to ground and the output voltage was ~.47 volts. Put a 1K resistor to ground an d the output voltage was .048 volts. Note that the actual value of the current source can vary; I have 3 CHIPs and one of them sources 47 uA while the other two source 57 uA. (For this article, I'll stick with the 47 uA CHIP.)
Also note that the current source produces VERY different behavior than a floating line with a constant pullup resistor to 3.3v. If you model the current source as simply an internal pullup resistance, its value varies greatly depending on the load, such that the sum of the two equals about 70K. With the 47K load, I measured the current source's equiv resistance at about 27K. But with a 10K load, the current source's equiv resistance measured at about 59K. (These measurements were indirect; I measured the voltage across the load and calculated the equiv pullup resistance. Also, I made many more measurements; these two were representative.)
Finally note that the electrical characteristic of an XIO line is identical for the line being and input and for the line being an output with value "1". While unusual, this design has some advantages.
- As an input, the current source serves the same purpose as a pullup resistor. No external pullup is needed for a button to ground.
- As an output, the current source serves the same purpose as a high-value pullup resistor to an open-drain output. If it is driving a high-impedence circuit that responds to voltage, no external pullup is needed. For active-low circuits that require a current sink, the XIO can sink up to 25 mA. The only time external circuitry is needed is to drive active-high circuits that require more than ~50 uA of current. In that case, it is recommended that the XIO line drive a FET transistor.