This will delete the page "GPIO"
. Please be certain.
The currently shipping u-boot+kernel boots up with the microcontroller (RDA8810) in a strange state, with some GPIO pins set to operate in special-function mode, and some set into GPIO mode, and the mix doesn't seem to match the intended functions described in the i96 spec.
This table describes the state of the 40 pin bus. Column 'mode' is the mode setting of the pin after boot; some of these agree with the i96 spec, some do not. The '(rda)' column is the pin name according to the RDA data sheet. The 'kernel' column is the GPIO numbering system used by the Linux kernel. And the 'verified' column indicates that I verified(measured) the function of the pin in gpio mode. The 'alt' column indicates the special function available on this pin, using the Linux naming scheme.
If there are 'special function' groups that you don't need for your project, you may use these pins as GPIO pins. For example, if you're not using sound on the PCM group, you can recover pins 15, 17, 19 & 21 for use as general purpose pins.
verified | gpio(kernel) | gpio(rda) | alt | mode° | i96 name | pin | pin | i96 name | mode° | alt | gpio (rda) | gpio (kernel) | verified |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
GND | 1 | 2 | GND | ||||||||||
yes | gpio40 | gpio_b8 | ttyS0 | gpio | UART0_CTS | 3 | 4 | PWR_BTN_N | note 2 | ||||
yes | gpio104 | gpio_c8 | ttyS0 | ttyS0 | UART0_TX | 5 | 6 | v_rtc | 1.4V | ||||
yes | gpio103 | gpio_c7 | ttyS0 | ttyS0 | UART0_RX | 7 | 8 | SPI0_CLK | gpio | spi2 | gpio_a2 | gpio2 | yes |
yes | gpio41 | gpio_b9 | ttyS0 | gpio | UART0_RTS | 9 | 10 | SPI0_DI | gpio | spi2 | gpio_a4 | gpio4 | yes |
yes | gpio14 | gpio_a14 | ttyS1 | ttyS1 | UART1_TX | 11 | 12 | SPI0_CS | gpio | spi2 | gpio_a6 | gpio6 | yes |
yes | gpio102 | gpio_c6 | ttyS1 | ttyS1 | UART1_RX | 13 | 14 | SPI0_DO | gpio | spi2 | gpio_a3 | gpio3 | yes |
yes | gpio0 | gpio_a0 | i2c-1 | i2c-1 | I2C0_SCL | 15 | 16 | PCM_FS | pcm | pcm | gpio_a10 | gpio10 | yes |
yes | gpio1 | gpio_a1 | i2c-1 | i2c-1 | I2C0_SDA | 17 | 18 | PCM_CLK | pcm | pcm | gpio_a9 | gpio9 | yes |
yes | gpio38 | gpio_b6 | i2c-2 | i2c-2 | I2C1_SCL | 19 | 20 | PCM_D0 | pcm | pcm | gpio_a13 | gpio13 | yes |
yes | gpio39 | gpio_b7 | i2c-2 | i2c-2 | I2C1_SDA | 21 | 22 | PCM_DI | pcm | pcm | gpio_a11 | gpio11 | yes |
yes | gpio15 | gpio_a15 | ttyS1 | ttyS1 | GPIO_A | 23 | 24 | GPIO_B | lcd | lcd | gpio_a20 | gpio20 | yes |
yes | gpio56 | gpio_b24 | gpio | GPIO_C | 25 | 26 | GPIO_D | ttyS2 | ttyS2 | gpio_d2 | gpio66 | yes | |
yes | gpio67 | gpio_d3 | ttyS2 | ttyS2 | GPIO_E | 27 | 28 | GPIO_F | lcd | lcd | gpio_a22 | gpio22 | yes |
yes | gpio30 | gpio_a30 | lcd | lcd | GPIO_G | 29 | 30 | GPIO_H | lcd | lcd | gpio_a29 | gpio29 | yes |
yes | gpio28 | gpio_a28 | lcd | lcd | GPIO_I | 31 | 32 | GPIO_J | lcd | lcd | gpio_a27 | gpio27 | yes |
yes | gpio26 | gpio_a26 | lcd | lcd | GPIO_K | 33 | 34 | GPIO_L | lcd | lcd | gpio_a25 | gpio25 | yes |
2.9V | v_pad | +1v8 | 35 | 36 | SYS_DCIN | n/c | |||||||
5V(usb) | +5v | 37 | 38 | SYS_DCIN | n/c | ||||||||
GND | 39 | 40 | GND |
° NOTE: these are the default modes with this software:
function | version |
---|---|
u-boot | U-Boot 2012.04.442-rel5.0.2-g5ee06c1-dirty (Mar 18 2020 - 18:51:54) |
kernel | Linux version 3.10.62-rel5.0.2+ (Linaro) |
distribution | Ubuntu 16.04 |
NOTE 2: this pin measures 0v normally, rises to 3.8V when the power button is pushed; this appears to be the opposite of the i96 spec. The schematic indicates that it's used as an interrupt, so this inversion probably doesn't matter.
In order to align the bus pins with the intended function of the i96 bus, we need to make some changes. The UART1, I2C and I2S/PCM pins are configured correctly. Pins 3, 9 (uart), 8, 10,12 and 14 (spi) need to be set to 'special-function'. And all the pins between 23 and 34 need to be set to 'gpio' mode. At the bottom of this file you can find a Python3 utility to restore the pins of the microproccesor to the states intended by the i96 bus.
The existing linux kernel does not give access to the pin-function control registers, but there are a couple of ways to access those registers from the linux environment:
devmem2
utility written by Jan-Derk Bakker; use apt install devmem2
This document was written using devmem2
to locate and test the control registers.
Here are the relevant registers:
Register Name | Register Address | Usage | Existing State | Desired State |
---|---|---|---|---|
IOMUX | 0x11a0.9008 | special-function/gpio select for group C | 0x7fe0.003f | 0x7fe0.003f |
IOMUX-A | 0x11a0.900c | ibid, group A | 0x0002.10fc | 0x7e52.90a0 |
IOMUX-B | 0x11a0.9010 | ibid, group B | 0x3f00.033f | 0x3f00.003f |
IOMUX-D | 0x11a0.9014 | ibid, group D | 0x0000.0010 | 0x0000.001c |
GPIO-DIR | 0x11a0.8000 | direction register for group C | ||
GPIO-DATA | 0x11a0.800c | data register for group C | ||
GPIO-A-DIR | 0x2093.0000 | direction register for group A | ||
GPIO-A-DATA | 0x2093.000c | data register for group A | ||
GPIO-B-DIR | 0x2093.1000 | direction register for group B | ||
GPIO-B-DATA | 0x2093.100c | data register for group B | ||
GPIO-D-DIR | 0x2093.2000 | direction register for group D | ||
GPIO-D-DATA | 0x2093.200c | data register for group D |
The patterns shown on the first 4 lines of this table will set the GPIO pins to align with the i96 bus specifications. And give you access to 12 general purpose GPIO pins (23-34). Note: a '1' written into this register will select a pin for GPIO; a '0' selects the special-function mode.
The last 8 entries are for information only. The Linux GPIO device driver /sys/class/gpio
works perfectly; there's no need to bypass it. (The linux /dev/gpiochip does not exist in this kernel, since it's 3.10)
For example, after the GPIO correction, to toggle pin 26 (i96-name: GPIO-D, linux-name: gpio66), simply:
cd /sys/class/gpio
echo 66 > export
cd gpio66
echo out > direction
echo 1 > value
echo 0 > value
## alternatively, use gpio or opio
opio mode 66 out
# this will also do the 'export' function and create /sys/class/gpio/gpio66
opio write 66 1
opio write 66 0
The code to restore the GPIO pins to the i96 standard is in the file gpio_fixup.py
. I recommend you install it at /usr/local/bin/gpio_fixup.py
and add it to /etc/rc.local
near the end of the boot sequence.
Be aware that if you connect 'output' hardware to the 40pin connector, the GPIO's may not be set properly in the 5-20 seconds between U-Boot and running the gpio-correction code. This time can stretch even longer if the Wifi module takes time to stabilize.
If you want to be sure about the state of an output, use one of these:
Prior to setting the gpio pin as an output, these pin will be hi-impedance. Design your hardware that it operates properly in the absence of a drive-voltage.
Once the system has booted, you can set the GPIO mode on pins 3 and 9 using the opio
program: opio mode 40 out
and opio mode 41 out
.
Of course, all of the above comments apply to the current uboot. A modified version could set the other i96 pins properly, but modifying uboot is beyond my skill level.
The 2G-IOT board is very similar, except that the GPIO bits are mostly set correctly. Here is the state of the pins at power-on (using the currently shipping uboot/kernel)
opio -2 status
+-----+-----+----------+------+-+ OrgPi 2G-iot +-+------+----------+-----+-----+
| gpio| alt | i96 Name | Mode | V | Physical | V | Mode | i96 Name | alt | gpio|
+-----+-----+----------+------+---+----++----+---+------+----------+-----+-----+
| | 2.8v| V_PAD | | | 1 || 2 | | | VDD_IN | 5V | |
| 63 | SDA | I2C1.SDA | alt | ? | 3 || 4 | | | VDD_IN | 5V | |
| 62 | SCL | I2C1.SCL | alt | ? | 5 || 6 | | | GND | | |
| 56 | | GPIO.B24 | out | 0 | 7 || 8 | ? | alt | UART2.TX | | 104 |
| | | GND | | | 9 || 10 | ? | alt | UART2.RX | | 103 |
| 102 | RX | UART1.RX | alt | ? | 11 || 12 | 1 | out* | GPIO.B5 | | 37 |
| 14 | TX | UART1.TX | alt | ? | 13 || 14 | | | GND | | |
| 15 | CTS | UART1.CT | alt | ? | 15 || 16 | 0 | in* | GPIO.C5 | | 101 |
| | 2.8v| V_PAD | | | 17 || 18 | 0 | in* | GPIO.C25 | SIM | 121 |
| 4 | DI | SPI2.DI | in* | 0 | 19 || 20 | | | GND | | |
| 3 | DIO | SPI2.DIO | in* | 0 | 21 || 22 | ? | alt | UART1.RT | RTS | 16 |
| 2 | CLK | SPI2.CLK | in* | 0 | 23 || 24 | 1 | in* | SPI2.CS0 | CS0 | 5 |
| | | GND | | | 25 || 26 | 0 | in* | SPI2.CS1 | CS1 | 6 |
| 1 | | I2C2.SDA | alt | ? | 27 || 28 | ? | alt | I2C2.SCL | SCL | 0 |
| 122 | SIM | GPIO.C26 | in* | 0 | 29 || 30 | | | GND | | |
| 123 | SIM | GPIO.C27 | in* | 1 | 31 || 32 | 0 | out* | UART2.RT | RTS | 41 |
| 124 | LCD | GPIO.C28 | in* | 0 | 33 || 34 | | | GND | | |
| 125 | LCD | GPIO.C29 | in* | 0 | 35 || 36 | 0 | out* | UART2.CT | CTS | 40 |
| 126 | LCD | GPIO.C30 | in* | 0 | 37 || 38 | ? | alt | I2C3.SCL | SCL | 38 |
| | | GND | | | 39 || 40 | ? | alt | I2C3.SDA | SDA | 39 |
+-----+-----+----------+------+---+----++----+---+------+----------+-----+-----+
Note: *these pins are set to GPIO mode but do NOT have exports in /sys/class/gpioNote: *these pins are set to GPIO mode but do NOT have exports in /sys/class/gpio
If you wish to use SPI2, you will have to set the mode pins to 'alt'; if not, you have 5 extra gpio pins already set up as inputs. Gpio pins 40 and 41 are set to outputs. I2C1, UART1, I2C2 and UART2 (tx+rx) are already set up and ready to use.
You can control the state of the pins using the opio
command line tool, documented here in this file, or here if you want to download it.
This will delete the page "GPIO"
. Please be certain.