March 9, 2020
The Orange Pi PC 2, which is slightly bigger than the Raspberry Pi model B, has a similar 40 pin general purpose input output header in approximately the same location. The absence of a UART on physical pins 8 and 10 is one notable difference which is easily overlooked because the dedicated 3 pin UART header on the OPiPC2. There are other differences. We have already seen that the I2C controllers connected to the I2C pins are not assigned the same bus number.
Table of Contents
- H5 SoC General Purpose Input/Output
- GPIO Header
- Access Through the sysfs Interface
- Access Through the GPIO Character Device
There are 106 I/0 pins on the Allwinner H5 arranged in 7 banks called GPIOA, GPIOC to GPIOG and GPIOL (what happened to B, H, I, J, K?). Thankfully, the numbering of pins within a bank is consecutive and starts at 0.
| Bank | First Pin | Last Pin | Pin Count |
| Name | Number | Name | Number |
| GPIOA | PA0 | 0 | PA21 | 21 | 22 |
| GPIOC | PC0 | 64 | PC16 | 80 | 17 |
| GPIOD | PD0 | 96 | PD17 | 113 | 18 |
| GPIOE | PE0 | 128 | PE15 | 143 | 16 |
| GPIOF | PF0 | 160 | PF6 | 166 | 7 |
| GPIOG | PG0 | 192 | PG13 | 205 | 14 |
| GPIOL | PL0 | 352 | PL11 | 363 | 12 |
| total | 106 |
Pin numbers are calculated from the pin name. As an example, here is the calculation to obtain the pin number of pin 12 in GPIO bank D.

The ordinal number of a letter is it's position in the latin alphabet: ord(A) = 1, ord(B) = 2 and so on. Pin numbers (or GPIO numbers) are not consecutive but they do give a unique number to each pin which simplifies access to them as will be seen below.
Descriptions of all these pins can be found in Chapter 4 Pin Description of the Allwinner H5 Datasheet V1.0. SUNXI provides a succint description of the pins and their functions for the H3 SoC which is bacically the same as the H5 SoC except for the ARM cores. The kernel debug interface also lists the available I/O pins, including their pin number, their name, function, drive capabilities and so on.
opipc@orangepipc2:~$ sudo -i
root@orangepipc2:~# cd /sys/kernel/debug/pinctrl
root@orangepipc2:/sys/kernel/debug/pinctrl# ls -l
total 0
drwxr-xr-x 2 root root 0 Dec 31 1969 1c20800.pinctrl
drwxr-xr-x 2 root root 0 Dec 31 1969 1f02c00.pinctrl
-r--r--r-- 1 root root 0 Dec 31 1969 pinctrl-devices
-r--r--r-- 1 root root 0 Dec 31 1969 pinctrl-handles
-r--r--r-- 1 root root 0 Dec 31 1969 pinctrl-maps
Have a look at the content of the three pinctrl-* files, it is instructive but not quite essential for the purpose at hand. Also look at the content of the two controllers. It's worthwhile to look at all the files that describe the I/O pins from differnt point of views. Here is a partial listing.
root@orangepipc2:/sys/kernel/debug/pinctrl# ls -l 1c20800.pinctrl/
total 0
-r--r--r-- 1 root root 0 Dec 31 1969 gpio-ranges
-r--r--r-- 1 root root 0 Dec 31 1969 pinconf-groups
-r--r--r-- 1 root root 0 Dec 31 1969 pinconf-pins
-r--r--r-- 1 root root 0 Dec 31 1969 pingroups
-r--r--r-- 1 root root 0 Dec 31 1969 pinmux-functions
-r--r--r-- 1 root root 0 Dec 31 1969 pinmux-pins
-r--r--r-- 1 root root 0 Dec 31 1969 pins
root@orangepipc2:/sys/kernel/debug/pinctrl# cat 1c20800.pinctrl/pinconf-pins
Pin config settings per pin
Format: pin (name): configs
pin 0 (PA0): input bias disabled, output drive strength (20 mA)
pin 1 (PA1): input bias disabled, output drive strength (20 mA)
pin 2 (PA2): input bias disabled, output drive strength (20 mA)
...
pin 5 (PA5): input bias pull up, output drive strength (20 mA)
...
pin 67 (PC3): input bias pull up, output drive strength (20 mA)
pin 68 (PC4): input bias pull up, output drive strength (20 mA)
...
pin 204 (PG12): input bias disabled, output drive strength (20 mA)
pin 205 (PG13): input bias disabled, output drive strength (20 mA)
root@orangepipc2:/sys/kernel/debug/pinctrl# cat 1c20800.pinctrl/pinmux-functions
function: gpio_in, groups = [ PA0 PA1 PA2 PA3 PA4 PA5 PA6 PA7 PA8 PA9 PA10 PA11 PA12 PA13 PA14 PA15 PA16 PA17 PA18 PA19 PA20 PA21 PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PC8 PC9 PC10 PC11 PC12 PC13 PC14 PC15 PC16 PD0 PD1 PD2 PD3 PD4 PD5 PD6 PD7 PD8 PD9 PD10 PD11 PD12 PD13 PD14 PD15 PD16 PD17 PE0 PE1 PE2 PE3 PE4 PE5 PE6 PE7 PE8 PE9 PE10 PE11 PE12 PE13 PE14 PE15 PF0 PF1 PF2 PF3 PF4 PF5 PF6 PG0 PG1 PG2 PG3 PG4 PG5 PG6 PG7 PG8 PG9 PG10 PG11 PG12 PG13 ]
function: gpio_out, groups = [ PA0 PA1 PA2 PA3 PA4 PA5 PA6 PA7 PA8 PA9 PA10 PA11 PA12 PA13 PA14 PA15 PA16 PA17 PA18 PA19 PA20 PA21 PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PC8 PC9 PC10 PC11 PC12 PC13 PC14 PC15 PC16 PD0 PD1 PD2 PD3 PD4 PD5 PD6 PD7 PD8 PD9 PD10 PD11 PD12 PD13 PD14 PD15 PD16 PD17 PE0 PE1 PE2 PE3 PE4 PE5 PE6 PE7 PE8 PE9 PE10 PE11 PE12 PE13 PE14 PE15 PF0 PF1 PF2 PF3 PF4 PF5 PF6 PG0 PG1 PG2 PG3 PG4 PG5 PG6 PG7 PG8 PG9 PG10 PG11 PG12 PG13 ]
function: uart2, groups = [ PA0 PA1 PA2 PA3 ]
function: jtag, groups = [ PA0 PA1 PA2 PA3 PF0 PF1 PF3 PF5 ]
function: irq, groups = [ PA0 PA1 PA2 PA3 PA4 PA5 PA6 PA7 PA8 PA9 PA10 PA11 PA12 PA13 PA14 PA15 PA16 PA17 PA18 PA19 PA20 PA21 PF0 PF1 PF2 PF3 PF4 PF5 PF6 PG0 PG1 PG2 PG3 PG4 PG5 PG6 PG7 PG8 PG9 PG10 PG11 PG12 PG13 ]
function: uart0, groups = [ PA4 PA5 PF2 PF4 ]
function: pwm0, groups = [ PA5 ]
function: sim, groups = [ PA6 PA7 PA8 PA9 PA10 PA20 PA21 PD12 PD13 PD14 PD15 PD16 PE14 PE15 ]
function: i2c0, groups = [ PA11 PA12 ]
function: di, groups = [ PA11 PA12 PD0 PD1 ]
function: spi1, groups = [ PA13 PA14 PA15 PA16 ]
function: uart3, groups = [ PA13 PA14 PA15 PA16 ]
function: spdif, groups = [ PA17 ]
function: i2s0, groups = [ PA18 PA19 PA20 PA21 ]
function: i2c1, groups = [ PA18 PA19 ]
function: nand0, groups = [ PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PC8 PC9 PC10 PC11 PC12 PC13 PC14 PC15 PC16 ]
function: spi0, groups = [ PC0 PC1 PC2 PC3 PC4 ]
function: mmc2, groups = [ PC1 PC5 PC6 PC8 PC9 PC10 PC11 PC12 PC13 PC14 PC15 PC16 ]
function: emac, groups = [ PD0 PD1 PD2 PD3 PD4 PD5 PD6 PD7 PD8 PD9 PD10 PD11 PD12 PD13 PD14 PD15 PD16 PD17 ]
function: ts2, groups = [ PD0 PD1 PD2 PD3 PD4 PD5 PD6 PD7 PD8 PD9 PD10 PD11 ]
function: ts3, groups = [ PD7 PD8 PD9 PD10 PD11 ]
function: csi, groups = [ PE0 PE1 PE2 PE3 PE4 PE5 PE6 PE7 PE8 PE9 PE10 PE11 PE12 PE13 ]
function: ts0, groups = [ PE0 PE1 PE2 PE3 PE4 PE5 PE6 PE7 PE8 PE9 PE10 ]
function: ts1, groups = [ PE7 PE8 PE9 PE10 PE11 ]
function: ts, groups = [ PE11 ]
function: i2c2, groups = [ PE12 PE13 ]
function: mmc0, groups = [ PF0 PF1 PF2 PF3 PF4 PF5 ]
function: mmc1, groups = [ PG0 PG1 PG2 PG3 PG4 PG5 ]
function: uart1, groups = [ PG6 PG7 PG8 PG9 ]
function: i2s1, groups = [ PG10 PG11 PG12 PG13 ]
root@orangepipc2:/sys/kernel/debug/pinctrl# cat 1c20800.pinctrl/pinmux-pins
Pinmux settings per pin
Format: pin (name): mux_owner gpio_owner hog?
pin 0 (PA0): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 1 (PA1): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 2 (PA2): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 3 (PA3): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 4 (PA4): 1c28000.serial (GPIO UNCLAIMED) function uart0 group PA4
pin 5 (PA5): 1c28000.serial (GPIO UNCLAIMED) function uart0 group PA5
pin 6 (PA6): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 7 (PA7): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 8 (PA8): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 9 (PA9): (MUX UNCLAIMED) (GPIO UNCLAIMED)
...
pin 203 (PG11): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 204 (PG12): (MUX UNCLAIMED) 1c20800.pinctrl:204
pin 205 (PG13): (MUX UNCLAIMED) (GPIO UNCLAIMED)
root@orangepipc2:/sys/kernel/debug/pinctrl# exit
logout
opipc@orangepipc2:~$ cd ~
opipc@orangepipc2:~$
Only 28 of the I/O pins are brought out to the 40 pin header of the OPiPC2. Here is the map of the 40 pin header on the Orange Pi PC 2. The pin numbers, calculated as shown above, are in the GPIO columns.
| Orange Pi PC 2 GPIO Header |
| GPIO | Function | Pin | Function | GPIO |
| 3.3V | 1 | 2 | 5V | |
| 12 | PA12 (TWI0_SDA/DI_RX/PA_EINT12) | 3 | 4 | 5V | |
| 11 | PA11 (TWI0_SCK/DI_TX/PA_EINT11) | 5 | 6 | GND | |
| 6 | PA6 (SIM_PWREN/PWM1/PA_EINT6) | 7 | 8 | PC5 (NAND_RE/SDC2_CLK) | 69 |
| GND | 9 | 10 | PC6 (NAND_RB0/SDC2_CMD) | 70 |
| 1 | PA1 (UART2_RX/JTAG_CK0/PA_EINT1) | 11 | 12 | PD14 (RGMII_NULL/MII_TXERR/RMII_NULL) | 110 |
| 0 | PA0 (UART2_TX/JTAG_MS0/PA_EINT0) | 13 | 14 | GND | |
| 3 | PA3 (UART2_CTS/JTAG_DI0/PA_EINT3) | 15 | 16 | PC4 (NAND_CE0) | 68 |
| 3.3V | 17 | 18 | PC7 (NAND_RB1) | 71 |
| 15 | PA15 (SPI1_MOSI/UART3_RTS/PA_EINT15) | 19 | 20 | GND | |
| 16 | PA16 (SPI1_MISO/UART3_CTS/PA_EINT16) | 21 | 22 | PA2 (UART2_RTS/JTAG_DO0/PA_EINT2) | 2 |
| 14 | PA14 (SPI1_CLK/UART3_RX/PA_EINT14) | 23 | 24 | PA13 (SPI1_CS/UART3_TX/PA_EINT13) | 13 |
| GND | 25 | 26 | PA21 (PCM0_DIN/SIM_VPPPP/PA_EINT21) | 21 |
| 19 | PA19 (PCM0_CLK/TWI1_SDA/PA_EINT19) | 27 | 28 | PA18 (PCM0_SYNC/TWI1_SCK/PA_EINT18) | 18 |
| 7 | PA7 (SIM_CLK/PA_EINT7) | 29 | 30 | GND | |
| 8 | PA8 (SIM_DATA/PA_EINT8) | 31 | 32 | PG8 (UART1_RTS/PG_EINT8) | 200 |
| 9 | PA9 (SIM_RST/PA_EINT9) | 33 | 34 | GND | |
| 10 | PA10 (SIM_DET/PA_EINT10) | 35 | 36 | PG9 (UART1_CTS/PG_EINT9) | 201 |
| 107 | PD11 (RGMII_NULL/MII_CRS/RMII_NULL) | 37 | 38 | PG6 (UART1_TX/PG_EINT6) | 198 |
| GND | 39 | 40 | PG7 (UART1_RX/PG_EINT7) | 199 |
These pins are there for us to play with, but access to them is not quite as simple as on an ESP or an AVR device in the Arduino framework. For one thing, pin numbering is slightly more complicated as seen above and, for another thing, adminitrator privileges are needed because I/O pins belong to root. Just to complicate things, thre are more than one way to access the I/0 pins as shown below.
The old way of accessing I/O pins in Linux is through the sysfs interface. The interface is a "filesystem for exporting kernel objects", as is often the case is Linux. This approach, now deprecated, still works. SUNXI has a page entitled GPIO that provides detailed instructions on this topic. There's also a reference to a well written article, Access GPIO from Linux user space by Fabio Falsini, which goes into greater detail.
It's a simple matter to verify that the GPIO pins are available in sysfs.
opipc@orangepipc2:~$ ls -l /sys/class/gpio
total 0
--w------- 1 root root 4096 Dec 31 1969 export
lrwxrwxrwx 1 root root 0 Dec 31 1969 gpiochip0 -> ../../devices/platform/soc/1c20800.pinctrl/gpio/gpiochip0
lrwxrwxrwx 1 root root 0 Dec 31 1969 gpiochip352 -> ../../devices/platform/soc/1f02c00.pinctrl/gpio/gpiochip352
--w------- 1 root root 4096 Dec 31 1969 unexport
The following text by Linus Walleij succinctly documents the interface.
What: /sys/class/gpio/
Date: July 2008
KernelVersion: 2.6.27
Contact: Linus Walleij
Description:
As a Kconfig option, individual GPIO signals may be accessed from
userspace. GPIOs are only made available to userspace by an explicit
"export" operation. If a given GPIO is not claimed for use by
kernel code, it may be exported by userspace (and unexported later).
Kernel code may export it for complete or partial access.
GPIOs are identified as they are inside the kernel, using integers in
the range 0..INT_MAX. See Documentation/admin-guide/gpio for more information.
/sys/class/gpio
/export ... asks the kernel to export a GPIO to userspace
/unexport ... to return a GPIO to the kernel
/gpioN ... for each exported GPIO #N OR
/<LINE-NAME> ... for a properly named GPIO line
/value ... always readable, writes fail for input GPIOs
/direction ... r/w as: in, out (default low); write: high, low
/edge ... r/w as: none, falling, rising, both
/gpiochipN ... for each gpiochip; #N is its first GPIO
/base ... (r/o) same as N
/label ... (r/o) descriptive, not necessarily unique
/ngpio ... (r/o) number of GPIOs; numbered N to N + (ngpio - 1)
This ABI is deprecated and will be removed after 2020. It is
replaced with the GPIO character device.
Let's toggle pin PA11 (GPIO pin number 11, physical pin 5) high and low using the sysfs interface. First access to the pin must be gained which is done by writting the pin number to the export file in the gpio sysfs directory. Once that is done, a new directory, called gpio11 is created.
root@orangepipc2:/home/opipc# echo 11 > /sys/class/gpio/export
root@orangepipc2:/home/opipc# ls -l /sys/class/gpio
total 0
--w------- 1 root root 4096 Mar 10 19:15 export
lrwxrwxrwx 1 root root 0 Mar 10 19:15 gpio11 -> ../../devices/platform/soc/1c20800.pinctrl/gpiochip1/gpio/gpio11
lrwxrwxrwx 1 root root 0 Mar 10 19:05 gpiochip0 -> ../../devices/platform/soc/1c20800.pinctrl/gpio/gpiochip0
lrwxrwxrwx 1 root root 0 Mar 10 19:05 gpiochip352 -> ../../devices/platform/soc/1f02c00.pinctrl/gpio/gpiochip352
--w------- 1 root root 4096 Mar 10 19:05 unexport
root@orangepipc2:/home/opipc# ls -l /sys/class/gpio/gpio11/
total 0
-rw-r--r-- 1 root root 4096 Mar 10 19:15 active_low
lrwxrwxrwx 1 root root 0 Mar 10 19:15 device -> ../../../gpiochip1
-rw-r--r-- 1 root root 4096 Mar 10 19:15 direction
-rw-r--r-- 1 root root 4096 Mar 10 19:15 edge
drwxr-xr-x 2 root root 0 Mar 10 19:15 power
lrwxrwxrwx 1 root root 0 Mar 10 19:15 subsystem -> ../../../../../../../class/gpio
-rw-r--r-- 1 root root 4096 Mar 10 19:15 uevent
-rw-r--r-- 1 root root 4096 Mar 10 19:15 value
Two files are of importance for us right now (details about files). The pin mode is changed to input or output by writing in or out respectively to the direction file. When in input mode, reading the value file will return a "0" or "1" (a single ASCII character) depending on the signal present on the pin. If the pin is in output mode, writing "0" or "1" to the value file sets the pin's voltage to 0 or, nominally 3.3 volts respectively.
root@orangepipc2:/home/opipc# cd /sys/class/gpio/gpio11
...
root@orangepipc2:/sys/class/gpio/gpio11# echo "out" > direction
root@orangepipc2:/sys/class/gpio/gpio11# cat value
0
root@orangepipc2:/sys/class/gpio/gpio11# echo "1" > value
root@orangepipc2:/sys/class/gpio/gpio11# cat value
1
root@orangepipc2:/sys/class/gpio/gpio11# echo "0" > value
root@orangepipc2:/sys/class/gpio/gpio11# cat value
0
Since it is hard to show the transition from off to on or vice versa of a LED on a static page, here is what was recorded by PulseView used with a clone of Salea logic analyzer connected to pin PA11. There is some additional annotation on screen captures shown below.

To release the pin, unexport its number. The gpio11 tree will be deleted by the system.
root@orangepipc2:/sys/class/gpio/gpio11# cd ..
root@orangepipc2:/sys/class/gpio# echo 11 > unexport
root@orangepipc2:/sys/class/gpio# ls -l
total 0
--w------- 1 root root 4096 Mar 10 19:15 export
lrwxrwxrwx 1 root root 0 Mar 10 19:05 gpiochip0 -> ../../devices/platform/soc/1c20800.pinctrl/gpio/gpiochip0
lrwxrwxrwx 1 root root 0 Mar 10 19:05 gpiochip352 -> ../../devices/platform/soc/1f02c00.pinctrl/gpio/gpiochip352
--w------- 1 root root 4096 Mar 10 21:28 unexport
Here is a short Bash script to toggle the pin on and off as quickly as possible.
#!/bin/bash
# Toggle GPIO pin PA11 on and off for 5 000 cycles
#
# Must run as root
#
gpio=11
echo $gpio > /sys/class/gpio/export
cd /sys/class/gpio/gpio$gpio
echo "out" > direction
x=1
while [ $x -le 5000 ]
do
echo "1" > value
echo "0" > value
x=$(( $x + 1 ))
done
As can be seen below, a frequency of 7.8 kHz was achieved.

As one would expect because Linux is not a real-time OS, the toggling was not done at a constant rate. Even though the script ran for a short time (about 767 milliseconds), there were visible "gaps", one lasting 4 ms, while background tasks were being performed. With a compiled C program, it was possible to achieve a rather more impressive frequency of 166 kHz. Still, for a system running at 1.2 GHz, this is not all that fast.
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#define MAX_BUF 256
int gpio = 11;
void openGpioOutput(void) {
int fd;
char buf[MAX_BUF];
fd = open("/sys/class/gpio/export", O_WRONLY);
sprintf(buf, "%d", gpio);
write(fd, buf, strlen(buf));
close(fd);
printf("Exported %d to /sys/class/gpio\n", gpio);
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);
printf("Set pin %d to output mode\n", gpio);
}
void toggle(void) {
int fd;
char buf[MAX_BUF];
printf("Starting to toggle pin %d\n", gpio);
sprintf(buf, "/sys/class/gpio/gpio%d/value", gpio);
fd = open(buf, O_WRONLY);
for (int i=0; i < 5000; i++) {
// Set GPIO high status
write(fd, "1", 1);
// Set GPIO low status
write(fd, "0", 1);
}
close(fd);
printf("Finished\n");
}
void closeGpio(void) {
int fd;
char buf[MAX_BUF];
fd = open("/sys/class/gpio/unexport", O_WRONLY);
sprintf(buf, "%d", gpio);
write(fd, buf, strlen(buf));
close(fd);
printf("GPIO pin %d released", gpio);
}
int main() {
openGpioOutput();
toggle();
closeGpio();
}
Compile and run this program borrowed from Fabio Falsini's article
opipc@orangepipc2:~$ cc -o toggle toggle.c
opipc@orangepipc2:~$ sudo ./toggle
Exported 11 to /sys/class/gpio
Set pin 11 to output mode
Starting to toggle pin 11
Finished
GPIO pin 11 released
opipc@orangepipc2:~$ sudo -i
root@orangepipc2:~# echo 11 > /sys/class/gpio/export
root@orangepipc2:~# cd /sys/class/gpio/gpio11
root@orangepipc2:/sys/class/gpio/gpio11# echo "in" > direction
physical pin 5 grounded:
root@orangepipc2:/sys/class/gpio/gpio11# cat value
0
physical pin 5 connected to 3.3 volts:
root@orangepipc2:/sys/class/gpio/gpio11# cat value
1
root@orangepipc2:/sys/class/gpio/gpio11# cd ..
root@orangepipc2:/sys/class/gpio# echo 11 > unexport
root@orangepipc2:/sys/class/gpio# exit
logout
opipc@orangepipc2:~$ cd ~
Quite a bit more could be done
After setting up a switch between an I/0 pin and ground, it quickly became apparent that there is no obvious way to enable any internal pull up resistor with the sysfs interface. it worked
GPIO access using the sysfs interface has been deprecated since version 4.8 of the Linux kernel. So, in Armbian Bionic with a 5.4.20 Linux kernel, we should be using the "new" method to access the I/O pins, the character based GPIO device gpiod.
references
An Introduction to chardev GPIO and Libgpiod on the Raspberry PI by Craig Peacock in BeyondLogic (October 16, 2018)
Pilotage de GPIO avec l’API Libgpiod (partie 1)
Pilotage de GPIO avec l’API Libgpiod (partie 2)
Pilotage de GPIO avec l’API Libgpiod (partie 3)
de Christophe Blaess datant d'octobre 2018.
https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/about/
In typical Debian fashion, the six command-line tools included with the gpiod library are in a seperate package.
Manpages of gpiod in Debian experimental
opipc@orangepipc2:~$ sudo apt install gpiod
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
libgpiod1
The following NEW packages will be installed:
gpiod libgpiod1
0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
Need to get 24.4 kB of archives.
After this operation, 124 kB of additional disk space will be used.
Do you want to continue? [Y/n] y
Get:1 http://ports.ubuntu.com bionic/universe arm64 libgpiod1 arm64 1.0-1 [10.9 kB]
Get:2 http://ports.ubuntu.com bionic/universe arm64 gpiod arm64 1.0-1 [13.5 kB]
Fetched 24.4 kB in 2s (12.9 kB/s)
Selecting previously unselected package libgpiod1:arm64.
(Reading database ... 32119 files and directories currently installed.)
Preparing to unpack .../libgpiod1_1.0-1_arm64.deb ...
Unpacking libgpiod1:arm64 (1.0-1) ...
Selecting previously unselected package gpiod.
Preparing to unpack .../archives/gpiod_1.0-1_arm64.deb ...
Unpacking gpiod (1.0-1) ...
Setting up libgpiod1:arm64 (1.0-1) ...
Setting up gpiod (1.0-1) ...
Processing triggers for libc-bin (2.27-3ubuntu1) ...
opipc@orangepipc2:~$ which gpioget
/usr/bin/gpioget
opipc@orangepipc2:~$ sudo gpiodetect
gpiochip0 [1f02c00.pinctrl] (32 lines)
gpiochip1 [1c20800.pinctrl] (224 lines)
opipc@orangepipc2:~$ sudo apt-cache policy libgpiod*
libgpiod0:
Installed: (none)
Candidate: (none)
Version table:
libgpiod1:
Installed: (none)
Candidate: 1.0-1
Version table:
1.0-1 500
500 http://ports.ubuntu.com bionic/universe arm64 Packages
libgpiod-dev:
Installed: (none)
Candidate: 1.0-1
Version table:
1.0-1 500
500 http://ports.ubuntu.com bionic/universe arm64 Packages
libgpiod-doc:
Installed: (none)
Candidate: 1.0-1
Version table:
1.0-1 500
500 http://ports.ubuntu.com bionic/universe arm64 Packages
500 http://ports.ubuntu.com bionic/universe armhf Packages
opipc@orangepipc2:~$ sudo apt install libgpiod1:
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
libgpiod1
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 10.9 kB of archives.
After this operation, 39.9 kB of additional disk space will be used.
Get:1 http://ports.ubuntu.com bionic/universe arm64 libgpiod1 arm64 1.0-1 [10.9 kB]
Fetched 10.9 kB in 0s (25.5 kB/s)
Selecting previously unselected package libgpiod1:arm64.
(Reading database ... 32119 files and directories currently installed.)
Preparing to unpack .../libgpiod1_1.0-1_arm64.deb ...
Unpacking libgpiod1:arm64 (1.0-1) ...
Setting up libgpiod1:arm64 (1.0-1) ...
Processing triggers for libc-bin (2.27-3ubuntu1) ...
Using ioctl
opipc@orangepipc2:~/gpio$ nano gpio.c
// Applications - Pin Control and GPIO
// https://microchipdeveloper.com/32mpu:apps-gpio
//
#include
#include
#include
#include
#include
#include
#define DEV_GPIO "/dev/gpiochip1"
#define GPIO_PIN 11 // GPIO PA11
int main(int argc, char *argv[])
{
int fd;
int ret;
struct gpiochip_info cinfo;
struct gpioline_info linfo;
struct gpiohandle_request req;
struct gpiohandle_data data;
// open gpio
fd = open(DEV_GPIO, 0);
if (fd < 0) {
printf("ERROR: open %s ret=%d\n", DEV_GPIO, fd);
return -1;
}
/*
// get gpio chip info
ret = ioctl(fd, GPIO_GET_CHIPINFO_IOCTL, &cinfo);
if (ret < 0) {
printf("ERROR get chip info ret=%d\n", ret);
return -1;
}
printf("GPIO chip: %s, \"%s\", %u GPIO lines\n",
cinfo.name, cinfo.label, cinfo.lines);
// this does not work in Armbian for Allwinner H5
ret = ioctl(fd, GPIO_GET_LINEINFO_IOCTL, &linfo);
if (ret < 0) {
printf("WARNING get line info returned=%d\n", ret);
} else {
printf("line %2d: %s\n", linfo.line_offset, linfo.name);
}
*/
req.lineoffsets[0] = GPIO_PIN;
req.lines = 1;
req.flags = GPIOHANDLE_REQUEST_OUTPUT;
//strcpy(req.consumer_label, "RST_mBUS1");
int lhfd = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
if (lhfd < 0) {
printf("ERROR get line handle lhdf=%d\n", lhfd);
return -1;
}
data.values[0] = 1;
ret = ioctl(req.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data);
if (ret < 0) {
printf("ERROR set line value ret=%d\n", ret);
return -1;
} else {
printf("Square wave generated on line %d, ^C to exit.\n", GPIO_PIN);
}
while (1) {
// set GPIO_PIN low
data.values[0] = 0;
ioctl(req.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data);
//usleep(5*1000);
// set GPIO_PIN high
data.values[0] = 1;
ioctl(req.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data);
//usleep(5*1000);
}
/* close gpio */
close(fd);
return 0;
}
opipc@orangepipc2:~/gpio$ cc -o gpio-test gpio.c
opipc@orangepipc2:~/gpio$ sudo ./gpio-test
Square wave generated on line 11, ^C to exit.
^C

Python
opipc@orangepipc2:~$ sudo apt install pkg-config
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
pkg-config
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 42.8 kB of archives.
After this operation, 169 kB of additional disk space will be used.
Get:1 http://ports.ubuntu.com bionic/main arm64 pkg-config arm64 0.29.1-0ubuntu2 [42.8 kB]
Fetched 42.8 kB in 1s (41.7 kB/s)
Selecting previously unselected package pkg-config.
(Reading database ... 32203 files and directories currently installed.)
Preparing to unpack .../pkg-config_0.29.1-0ubuntu2_arm64.deb ...
Unpacking pkg-config (0.29.1-0ubuntu2) ...
Setting up pkg-config (0.29.1-0ubuntu2) ...
Processing triggers for man-db (2.8.3-2ubuntu0.1) ...
opipc@orangepipc2:~$ mkvenv gpiod
creating virtual environment /home/opipc/gpiod
updating virtual environment /home/opipc/gpiod
Cache entry deserialization failed, entry ignored
opipc@orangepipc2:~$ ve gpiod
(gpiod) opipc@orangepipc2:~$ pip install libgpiod
https://stackoverflow.com/questions/46463724/accessing-gpio-on-orangepi-pc-plus-h3-on-armbian-3-4-113-and-newer#46464496
https://github.com/brgl/libgpiod
https://diyprojects.io/orange-pi-onelite-tutorial-use-gpio-python-pinouts/
Orange Pi One/Lite (Tutorial): use the GPIO in Python, pinouts
https://diyprojects.io/orange-pi-review-opi-gpio-package-node-red-node-red-contrib-opi-gpio/
Orange Pi: test of the OPI.GPIO package for Node-Red (node-red-contrib-opi-gpio)
UART: yes probably!
Orange Pi Zero 2+ H5 can't communicate on UART1
https://forum.armbian.com/topic/5938-orange-pi-zero-2-h5-cant-communicate-on-uart1/?tab=comments#comment-46116
https://opi-gpio.readthedocs.io/en/latest/
OPi-GPIO is a drop-in replacement library for RPi.GPIO for the Orange Pi Zero. Only the basic GPIO functions are replicated, using sysfs: this allows the GPIO pins to be accessed from user space.
RPi.GPIO replacement for Orange Pi Zero and Nano Pi Duo
By sgjava, January 1, 2018
https://forum.armbian.com/topic/6069-rpigpio-replacement-for-orange-pi-zero-and-nano-pi-duo/
however sysfs is depricated
https://github.com/bitbank2/ArmbianIO
ArmbianIO is a C library for accessing I2C, SPI and GPIO ports in a consistent way across all of the SBCs that Armbian supports.
https://github.com/bitbank2/armbian_oled
A C library for SSD1306 displays (I2C+SPI) which uses my ArmbianIO library
https://forum.armbian.com/topic/7980-wiringpi-cant-work-for-h5-cpu-orangepi-pc-2/
WiringPi can't work for H5 CPU (OrangePi PC 2)
https://github.com/bitbank2/ir_receiver
C code to receive NEC codes from a GPIO connected to a IR demodulator
https://forum.armbian.com/topic/5655-armbianio-api-proposal/
ArmbianIO API proposal
https://forum.armbian.com/topic/5662-pygpio-a-more-general-python-gpio-library/
pyGPIO - A 'more general' python GPIO library
Allwinner H5 & A64
https://forum.armbian.com/forum/27-allwinner-h5-a64/page/18/
https://forum.armbian.com/profile/1032-lopau/
RPi Low-level peripherals
https://elinux.org/RPi_Low-level_peripherals#General_Purpose_Input.2FOutput_.28GPIO.29
CEC (Consumer Electronics Control) over HDMI
https://elinux.org/CEC_(Consumer_Electronics_Control)_over_HDMI
Bootable SPI flash
https://linux-sunxi.org/Bootable_SPI_flash#Macronix_MX25L1606E
WiringPI / WiringOP
http://wiringpi.com/
Wiring Pi
GPIO Interface library for the Raspberry Pi
http://www.orangepi.org/Docs/WiringPi.html
https://github.com/zhaolei/WiringOP
https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md
SPI
https://elinux.org/RPi_SPI
RPi SPI
http://abyz.me.uk/rpi/pigpio/index.html
The pigpio library