Unlike the Raspberry Pi that hides the I2C bus used internally for recognizing extension boards (HATS), the two buses used internally by the Orange Pi PC 2 for managing on-board resources are visible yet not available for use. Armbian Bionic comes with overlays to enable three additional I2C controllers. The first two correspond to the physical buses available on the 40 pin GPIO header, just as on the Raspberry Pi. The third is used for the camera serial interface (CSI).
Table of Contents
- Default I2C Configuration
- Enabling the
i2c0
Controller
- Enabling the
i2c1
Controller
- The
i2c2
Controller and the Camera Serial Interface (CSI)
- Enabling the DS1307/DS3231 driver on
i2c1
with a Custom Overlay
The Allwinner H5 SoC has up to 4 I2C controllers according to the TWI overview found in the Allwinner H5 Datasheet (page 49).
2.2.9.6. TWI
- Up to 4 TWI(Two Wire Interface) controllers
- Supports Standard mode(up to 100K bps) and Fast mode(up to 400K bps)
- Master/Slave configurable
- Allows 10-bit addressing transactions
- Perform arbitration and clock synchronization
- Allows operation from a wide range of input clock frequencies
Remember that TWI (Two Wire Interface) is the same thing as I2C (Inter-Integrated Circuit). The GPIO map shows that two physical I2C buses are available on the same pins of the 40 pin header as on Raspberry Pi models with a 40 pin header. Physical pins 3 and 27 are the data lines (TWI0_SDA
and TWI1_SDA
respectively) and pins 4 and 28 are the clocks (TWI0_SCK
and TWI1_SCK
respectively).
Orange Pi PC 2 GPIO Header |
Function | Pin | Function |
3.3V | 1 | 2 | 5V |
PA12 (TWI0_SDA/DI_RX/PA_EINT12) | 3 | 4 | 5V |
PA11 (TWI0_SCK/DI_TX/PA_EINT11) | 5 | 6 | GND |
PA6 (SIM_PWREN/PWM1/PA_EINT6) | 7 | 8 | PC5 (NAND_RE/SDC2_CLK) |
GND | 9 | 10 | PC6 (NAND_RB0/SDC2_CMD) |
PA1 (UART2_RX/JTAG_CK0/PA_EINT1) | 11 | 12 | PD14 (RGMII_NULL/MII_TXERR/RMII_NULL) |
PA0 (UART2_TX/JTAG_MS0/PA_EINT0) | 13 | 14 | GND |
PA3 (UART2_CTS/JTAG_DI0/PA_EINT3) | 15 | 16 | PC4 (NAND_CE0) |
3.3V | 17 | 18 | PC7 (NAND_RB1) |
PA15 (SPI1_MOSI/UART3_RTS/PA_EINT15) | 19 | 20 | GND |
PA16 (SPI1_MISO/UART3_CTS/PA_EINT16) | 21 | 22 | PA2 (UART2_RTS/JTAG_DO0/PA_EINT2) |
PA14 (SPI1_CLK/UART3_RX/PA_EINT14) | 23 | 24 | PA13 (SPI1_CS/UART3_TX/PA_EINT13) |
GND | 25 | 26 | PA21 (PCM0_DIN/SIM_VPPPP/PA_EINT21) |
PA19 (PCM0_CLK/TWI1_SDA/PA_EINT19) | 27 | 28 | PA18 (PCM0_SYNC/TWI1_SCK/PA_EINT18) |
PA7 (SIM_CLK/PA_EINT7) | 29 | 30 | GND |
PA8 (SIM_DATA/PA_EINT8) | 31 | 32 | PG8 (UART1_RTS/PG_EINT8) |
PA9 (SIM_RST/PA_EINT9) | 33 | 34 | GND |
PA10 (SIM_DET/PA_EINT10) | 35 | 36 | PG9 (UART1_CTS/PG_EINT9) |
PD11 (RGMII_NULL/MII_CRS/RMII_NULL) | 37 | 38 | PG6 (UART1_TX/PG_EINT6) |
GND | 39 | 40 | PG7 (UART1_RX/PG_EINT7) |
On a fresh install of the Raspbian Bionic there were two i2c
devices present in the /dev
directory. After installing the i2c-tools
package, it was possible to check for connected I2C devices.
opipc@orangepipc2:~$ ls -l /dev/i2*
crw-rw---- 1 root i2c 89, 0 Feb 29 14:59 /dev/i2c-0
crw-rw---- 1 root i2c 89, 1 Feb 29 14:59 /dev/i2c-1
opipc@orangepipc2:~$ sudo apt install i2c-tools -y
...
Need to get 69.9 kB of archives.
After this operation, 289 kB of additional disk space will be used.
...
Processing triggers for man-db (2.8.3-2ubuntu0.1) ...
Processing triggers for libc-bin (2.27-3ubuntu1) ...
opipc@orangepipc2:~$ sudo i2cdetect -y 0
opipc@orangepipc2:~$ sudo i2cdetect -y 0
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: 30 -- 32 -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- 59 -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
opipc@orangepipc2:~$ sudo i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- UU -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
The results were surprising because there were two devices connected to PA12
and PA11
(physical pins 3 and 5), which I thought would be controlled by i2c0
, but the addresses (0x30, 0x32 and 0x59) were wrong. As for bus 1, I had no clue what could be at 0x65, but the address was probably correct since UU
indicates the presence of a driver. A look at loaded modules gave some information
opipc@orangepipc2:~$ lsmod | grep -i i2c
i2c_mv64xxx 20480 0
A Web search led to a 2013 commit in the Linux
repository with a hint of what the module does.
i2c: mv64xxx: Add I2C Transaction Generator support
The I2C Transaction Generator offloads CPU from managing I2C transfer step by step.
The SUNXI wiki Xunlong Orange Pi PC 2, CPU clock speed limit about the OPiPC2 had some information about I2C address 0x65. "The Orange Pi PC 2 board uses the SY8106A voltage regulator (U9) for providing the CPU core voltage (VDD_CPUX, nominally 1.2V at 6A). The default CPU voltage is 1.1V after power-on (selected by the resistors on the PCB) and can be changed at runtime by software via I2C interface (I2C address 0x65)." Looking into the voltabe regulator, the only register that I dared attempt to read was its status register, expecting a value of 0x01
.
Name | Bit | Access | Default | Description |
OTP | 7 | R | 0 | 1 : Die temperature over 160°C, OTP is triggered 0 : OTP is not triggered |
| 6 | R | 0 | Reserved |
| 5 | R | 0 | Reserved |
OC | 4 | R | 0 | 1. OCP is triggered and Vo drops below 1/3 of set point. 0. Current is below current limit |
Temperature Warning | 3 | R | 0 | 1 : Die temperature over 125°C 0 : Die temperature below 125° |
| 2 | R | 0 | Reserved |
| 1 | R | 0 | Reserved |
PGOOD | 0 | R | 0 | 1 : Vout in power good regulation range 0 : Vout not in power good regulation range |
However, I did not get very far.
opipc@orangepipc2:~$ sudo i2cget -y 1 0x65 0x06
Error: Could not set address to 0x65: Device or resource busy
opipc@orangepipc2:~$ lsmod | grep -i sy8106
sy8106a_regulator 16384 1
opipc@orangepipc2:~$ sudo rmmod sy8106a_regulator
rmmod: ERROR: Module sy8106a_regulator is in use
While removing the rtc_ds1307
module in order to read the temperature of the DS3231 real time clock had worked on the Raspberry Pi, I was clearly out of luck here. That's that, time to move on to the other I2C bus. Here's what I found about i2c-0
by listing the I2C bus devices and pertinent startup messages.
opipc@orangepipc2:~$ ls -l /sys/bus/i2c/devices
total 0
lrwxrwxrwx 1 root root 0 Mar 5 12:03 1-0065 -> ../../../devices/platform/soc/1f02400.i2c/i2c-1/1-0065
lrwxrwxrwx 1 root root 0 Mar 5 12:02 i2c-0 -> ../../../devices/platform/soc/1ee0000.hdmi/i2c-0
lrwxrwxrwx 1 root root 0 Mar 5 12:03 i2c-1 -> ../../../devices/platform/soc/1f02400.i2c/i2c-1
opipc@orangepipc2:~$ dmesg | grep hdmi
[ 2.104958] sun8i-dw-hdmi 1ee0000.hdmi: 1ee0000.hdmi supply hvcc not found, using dummy regulator
[ 2.105789] sun8i-dw-hdmi 1ee0000.hdmi: Detected HDMI TX controller v1.32a with HDCP (sun8i_dw_hdmi_phy)
[ 2.106117] sun8i-dw-hdmi 1ee0000.hdmi: registered DesignWare HDMI I2C bus driver
[ 2.106341] sun4i-drm display-engine: bound 1ee0000.hdmi (ops 0xffff800010bdcd30)
According to SUNXI, the Allwinner H3 SoC uses a Synopsys DesignWare HDMI controller. Furthermore, "...H5 is basically an Allwinner H3 with the Cortex-A7 cores replaced with Cortex-A53 cores." Presumably, the OPiPC2 also has a Synopsys DesignWare HDMI controller which the startup messages appear to confirm. What can also be seen is that there is an I2C bus driver connected to the i2c-0
controller. By the way, the drm
in the sun4i-drm
display engine stands for Direct Rendering Manager, a subsystem of the Linux kernel interfacing with the GPU, not for Digital Rights Management. So it certainly looks like i2c-0
controls another internal I2C channel.
It would probably be best to avoid poking both these internal I2C buses given the warning in the i2cdetect
man
page:
Warning
This program can confuse your I2C bus, cause data loss and worse!
Fortunately, no OPiPC2 were harmed in the making of this post.
The system configuration utility, can be used to enable the i2c0
controller.
opipc@orangepipc2:~$ sudo armbian-config
Select System (System and security settings)
then Hardware (Toggle hardware configuration: UART, I2C, etc.
and finally mark i2c0
for installation. Notice that there are 3 I2C device tree overlays that can be enabled. Basically, the utility adds an entry in the configuration file /boot/armbianEnv.txt
. Accordingly, it is possible to activate the wanted device tree overlay by including it in the configuration file (see Device Tree overlays in the Armbian User Guide Documentation).
opipc@orangepipc2:~$ sudo nano /boot/armbianEnv.txt
verbosity=1
console=both
overlay_prefix=sun50i-h5
rootdev=UUID=a948f949-ea06-4a76-9d5d-4c9da81e0efe
rootfstype=ext4
usbstoragequirks=0x2537:0x1066:u,0x2537:0x1068:u
overlays=i2c0
No matter which way is used to activate the I2C controller, it will be necessary to reboot. When that is done, look for connected devices on i2c-0
.
opipc@orangepipc2:~$ ls -l /sys/bus/i2c/devices/i2c*
lrwxrwxrwx 1 root root 0 Mar 5 18:18 /sys/bus/i2c/devices/i2c-0 -> ../../../devices/platform/soc/1c2ac00.i2c/i2c-0
lrwxrwxrwx 1 root root 0 Mar 5 18:18 /sys/bus/i2c/devices/i2c-1 -> ../../../devices/platform/soc/1ee0000.hdmi/i2c-1
lrwxrwxrwx 1 root root 0 Mar 5 18:18 /sys/bus/i2c/devices/i2c-2 -> ../../../devices/platform/soc/1f02400.i2c/i2c-2
opipc@orangepipc2:~$ sudo ls -l /dev/i2c*
crw-rw---- 1 root i2c 89, 0 Mar 2 19:30 /dev/i2c-0 Hardware I2C bus on PA12 and PA11 (physical pins 3 and 5)
crw-rw---- 1 root i2c 89, 1 Mar 2 19:30 /dev/i2c-1 Internal I2C bus for hdmi controller
crw-rw---- 1 root i2c 89, 2 Mar 2 19:30 /dev/i2c-2 Internal I2C bus for SY8106A voltage regulator
opipc@orangepipc2:~$ sudo i2cdetect -y 0
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
The two devices connected to physical pins 3 and 5 of the 40 pin header assigned to the i2c-0
controller are found at the correct addresses.
- 0x57: AT24C32 EEPROM
- 0x68: DS3231 Real time clock.
The physical module with these two devices was discussed in detail when installed on a Raspberry Pi. I wanted to replicate the read and write to EEPROM test done in that post but I ran into a couple of difficulties. The first was easy to fix: add the default user to the i2c
group that was created when i2c-tools
was installed, to avoid the need to resort to the sudo
command all the time when dealing with the I2C bus.
opipc@orangepipc2:~$ sudo adduser opipc i2c
Adding user `opipc' to group `i2c' ...
Adding user opipc to group i2c
Done.
opipc@orangepipc2:~$ exit
The second problem was a **** stack smashing detected ***
error each time I tried running the eeprog
program. All discussions of "stack smashing" talked of buffer overruns which sent me on a futile search for buffers in the source code. Trying to locate the latest version of the original branch of eeprog
, I found a
fork of version 0.7.6 by Alvin Wang with one change in the 24cXX.c
source code that fixed the problem. Here is how to install and fix the
"tear" version of eeprog
in the same manner.
opipc@orangepipc2:~ $ wget https://github.com/jsarenik/eeprog/archive/master.zip
--2020-01-29 19:10:06-- https://github.com/jsarenik/eeprog/archive/master.zip
...
2020-01-29 19:10:07 (268 KB/s) - ‘master.zip’ saved [19445]
opipc@orangepipc2:~ $ unzip master.zip
...
opipc@orangepipc2:~ $ mv eeprog-master eeprog
opipc@orangepipc2:~ $ cd eeprog
opipc@orangepipc2:~/eeprog$ nano 24cXX.c
In the editor change the first line of the eeprom_open
function.
int eeprom_open(char *dev_fqn, int addr, int type, int write_cycle_time, struct eeprom* e)
{
int funcs, fd, r;
to
int eeprom_open(char *dev_fqn, int addr, int type, int write_cycle_time, struct eeprom* e)
{
// int funcs, fd, r;
// https://github.com/alvintpwang/eeprog/commit/8ffb91311d87af0aa87a817f2a6cfd63121f7c02
unsigned long funcs;
int fd, r;
What I think is going on is that ioctl(fd, I2C_FUNCS, &funcs)
, called in eeprom_open
, returns a 64 bit list of functions in Armbian Bionic which is a 64 bit OS but an int
is 32 bits. The problem did not occur in Raspbian Buster which is still a 32 bit system.
After that fix, it was possible to carry on as with the Raspberry Pi.
opipc@orangepipc2:~/eeprog $ make
opipc@orangepipc2:~/eeprog $ cd ..
opipc@orangepipc2:~$ eeprog/eeprog -f -16 -r 0:16 /dev/i2c-0 0x57
eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer
Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved.
Copyright (c) 2011 by Kris Rusocki - All rights reserved.
Bus: /dev/i2c-0, Address: 0x57, Mode: 16bit
Operation: read 16 bytes from offset 0, Output file: <stdout>
Reading 16 bytes from 0x0
����������������
opipc@orangepipc2:~$ echo "eeprom on i2c-0 " | eeprog/eeprog -f -16 -w 0x00 -t 2 /dev/i2c-0 0x57
eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer
Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved.
Copyright (c) 2011 by Kris Rusocki - All rights reserved.
Bus: /dev/i2c-0, Address: 0x57, Mode: 16bit
Operation: write at offset 0, Input file: <stdin>
Write cycle time: 2 milliseconds
Writing <stdin> starting at address 0x0
.................
opipc@orangepipc2:~$ eeprog/eeprog -f -16 -r 0:16 /dev/i2c-0 0x57
eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer
Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved.
Copyright (c) 2011 by Kris Rusocki - All rights reserved.
Bus: /dev/i2c-0, Address: 0x57, Mode: 16bit
Operation: read 16 bytes from offset 0, Output file: <stdout>
Reading 16 bytes from 0x0
eeprom on i2c-0
Since there is a real-time clock on the H5 SoC which is enabled in the kernel and there does not seem to be a real-time clock overlay
equivalent to i2c-rtc
found in Raspbian, hwclock
cannot be used to acces the DS3231 (this is not an accurate statement and, as shown further on, an rtc overlay can be installed.) It was easy to read and write the real time clock registers with some i2c-tools
utilities: i2cdump
and i2cset
.
opipc@orangepipc2:~$ i2cdump -y -r 0x00-0x06 0 0x68 b
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 18 03 00 01 01 01 00 ??.???.
This corresponds to the time 00-01-01 00:03:18. Let's change the year and dump the RTC registers again.
opipc@orangepipc2:~$ i2cset -y 0 0x68 0x06 0x22 b
opipc@orangepipc2:~$ i2cdump -y -r 0x00-0x06 0 0x68 b
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 14 08 00 01 01 01 22 ??.???"
The time was changed to 22-01-01 00:08:14 so that clearly the year had been updated without problem.
It was easy to check that i2c1
controls the hardware I2C bus on pins 27 and 28 of the 40 GPIO header by connecting the RTC/EEPROM module to those pins (SDA to pin 27, SCL to pin 28). This is the modified configuration file.
verbosity=1
console=both
overlay_prefix=sun50i-h5
rootdev=UUID=a948f949-ea06-4a76-9d5d-4c9da81e0efe
rootfstype=ext4
usbstoragequirks=0x2537:0x1066:u,0x2537:0x1068:u
overlays=i2c0 i2c1
After rebooting, I checked all I2C buses.
opipc@orangepipc2:~$ ls -l /sys/bus/i2c/devices/i2c*
lrwxrwxrwx 1 root root 0 Mar 5 19:56 /sys/bus/i2c/devices/i2c-0 -> ../../../devices/platform/soc/1c2ac00.i2c/i2c-0
lrwxrwxrwx 1 root root 0 Mar 5 19:56 /sys/bus/i2c/devices/i2c-1 -> ../../../devices/platform/soc/1c2b000.i2c/i2c-1
lrwxrwxrwx 1 root root 0 Mar 5 19:56 /sys/bus/i2c/devices/i2c-2 -> ../../../devices/platform/soc/1ee0000.hdmi/i2c-2
lrwxrwxrwx 1 root root 0 Mar 5 19:56 /sys/bus/i2c/devices/i2c-3 -> ../../../devices/platform/soc/1f02400.i2c/i2c-3
opipc@orangepipc2:~$ ls -l /dev/i2c*
crw-rw---- 1 root i2c 89, 0 Mar 2 19:30 /dev/i2c-0 Hardware I2C bus on PA12 and PA11 (physical pins 3 and 5)
crw-rw---- 1 root i2c 89, 1 Mar 2 19:30 /dev/i2c-1 Hardware I2C bus on PA19 and PA18 (physical pins 27 and 28)
crw-rw---- 1 root i2c 89, 2 Mar 2 19:30 /dev/i2c-2 Internal I2C bus for hdmi controller
crw-rw---- 1 root i2c 89, 3 Mar 3 23:10 /dev/i2c-3 Internal I2C bus for SY8106A voltage regulator
As before, the internal I2C controllers are assigned higher bus numbers because of the I2C controllers added with overlays. It was a simple matter to check that the EEPROM on bus 1 could be accessed.
opipc@orangepipc2:~$ echo "eeprom on i2c-1 " | eeprog/eeprog -f -16 -w 0x00 -t 2 /dev/i2c-1 0x57
eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer
Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved.
Copyright (c) 2011 by Kris Rusocki - All rights reserved.
Bus: /dev/i2c-1, Address: 0x57, Mode: 16bit
Operation: write at offset 0, Input file: <stdin>
Write cycle time: 2 milliseconds
Writing <stdin> starting at address 0x0
.................
opipc@orangepipc2:~$ eeprog/eeprog -f -16 -r 0:16 /dev/i2c-1 0x57
eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer
Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved.
Copyright (c) 2011 by Kris Rusocki - All rights reserved.
Bus: /dev/i2c-1, Address: 0x57, Mode: 16bit
Operation: read 16 bytes from offset 0, Output file: <stdout>
Reading 16 bytes from 0x0
eeprom on i2c-1
This time I used an updated version of a rtc
Python script to verify that it was possible to read and write to the DS3231 on bus 1.
opipc@orangepipc2:~$ ve rtcpy
(rtcpy) opipc@orangepipc2:~$ rtcpy/rtc -i 1
Mon Sep 1 02:29:16 2059
(rtcpy) opipc@orangepipc2:~$ rtcpy/rtc -i 1 -s "2018-07-01 01:01:05"
(rtcpy) opipc@orangepipc2:~$ rtcpy/rtc -i 1
Sun Jul 1 01:01:07 2018
Here is the part of the description file pertaining to I2C overlays.
opipc@orangepipc2:~$ cat /boot/dtb/allwinner/overlay/README.sun50i-h5-overlays
...
### i2c2
Activates TWI/I2C bus 2
I2C2 pins (SCL, SDA): PE12, PE13
On most board this bus is wired to Camera (CSI) socket
...
While the main reference for the OPiPC2 hardware does describe the camera serial interface (CSI), it does not specify the I2C controller used nor the GPIO pins. The schematic does show that pins PE12 and PE13 of the H5, identified as PE12/CSI_SCK/TWI2_SCK and PE13/CSI_SDA/TWI2_SDA are connected to CAM-SCK and CAM-SDA (pins 4 and 3 of the CSI connector).
I was hoping to use a Raspberry Pi camera to test the I2C - CSI connection on the OPiPC2 but a discussion on the Orange Pi Forum,
How to Interface Raspberry Pi Camera on Orange pi, and a related Hackaday entry: Raspberry Pi camera on Orange Pi Plus board. Convert MIPI CSI-2 2 lanes into DVP using a FPGA. considerably diminished my hopes. They were completely dashed when it became obvious the camera cable did not fit in the OPiPC2 CSI connector. Nevertheless, I enabled the I2C bus and proceeded with the usual detection of the I2C buses.
verbosity=1
console=both
overlay_prefix=sun50i-h5
rootdev=UUID=a948f949-ea06-4a76-9d5d-4c9da81e0efe
rootfstype=ext4
overlays=i2c0 i2c1 i2c2
usbstoragequirks=0x2537:0x1066:u,0x2537:0x1068:u
As before there are two more I2C buses beside the three enabled with device tree overlays.
opipc@orangepipc2:~$ ls -l /sys/bus/i2c/devices/i2c*
lrwxrwxrwx 1 root root 0 Mar 5 20:36 /sys/bus/i2c/devices/i2c-0 -> ../../../devices/platform/soc/1c2ac00.i2c/i2c-0
lrwxrwxrwx 1 root root 0 Mar 5 20:36 /sys/bus/i2c/devices/i2c-1 -> ../../../devices/platform/soc/1c2b000.i2c/i2c-1
lrwxrwxrwx 1 root root 0 Mar 5 20:36 /sys/bus/i2c/devices/i2c-2 -> ../../../devices/platform/soc/1c2b400.i2c/i2c-2
lrwxrwxrwx 1 root root 0 Mar 5 20:36 /sys/bus/i2c/devices/i2c-3 -> ../../../devices/platform/soc/1ee0000.hdmi/i2c-3
lrwxrwxrwx 1 root root 0 Mar 5 20:36 /sys/bus/i2c/devices/i2c-4 -> ../../../devices/platform/soc/1f02400.i2c/i2c-4
opipc@orangepipc2:~$ ls -l /dev/i2c*
crw-rw---- 1 root i2c 89, 0 Mar 5 20:36 /dev/i2c-0 Hardware I2C bus on PA12 and PA11 (physical pins 3 and 5)
crw-rw---- 1 root i2c 89, 1 Mar 5 20:36 /dev/i2c-1 Hardware I2C bus on PA19 and PA18 (physical pins 27 and 28)
crw-rw---- 1 root i2c 89, 2 Mar 5 20:36 /dev/i2c-2 Hardware I2C bus on PE13 and PE12 (pins 3 and 4 of CSI connector)
crw-rw---- 1 root i2c 89, 3 Mar 5 20:36 /dev/i2c-3
crw-rw---- 1 root i2c 89, 4 Mar 5 20:36 /dev/i2c-4
opipc@orangepipc2:~$ ls -l /dev/i2c*
crw-rw---- 1 root i2c 89, 0 Mar 4 14:28 /dev/i2c-0 Hardware I2C bus on physical pins 3 and 5
crw-rw---- 1 root i2c 89, 1 Mar 4 14:28 /dev/i2c-1 Hardware I2C bus on physical pins 27 and 28
crw-rw---- 1 root i2c 89, 2 Mar 4 14:28 /dev/i2c-2 Hardware I2C bus on CSI connector
crw-rw---- 1 root i2c 89, 3 Mar 4 14:28 /dev/i2c-3 Internal I2C bus for hdmi controller
crw-rw---- 1 root i2c 89, 4 Mar 4 14:28 /dev/i2c-4 Internal I2C bus for SY8106A voltage regulator
Strangely i2cdetect -y 2 took more than four minutes to complete the bus scan.
opipc@orangepipc2:~$ date
Thu Mar 5 20:45:33 AST 2020
opipc@orangepipc2:~$ 2cdetect -y 2
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
opipc@orangepipc2:~$ date
Thu Mar 5 20:49:51 AST 2020
Unfortunately, I could not investigate this I2C hardware bus any further.
Among the example custom overlays in the Armbian Github repository, there is one named i2c-ds1307.dts
which can be installed following the
Armbian User Guide instructions. Preparing for that, I cutdown on the number of I2C controllers, installing only i2c1
. Here is the content of the /boot/armbianEnv.txt
file.
verbosity=1
console=both
overlay_prefix=sun50i-h5
rootdev=UUID=a948f949-ea06-4a76-9d5d-4c9da81e0efe
rootfstype=ext4
overlays=i2c1
usbstoragequirks=0x2537:0x1066:u,0x2537:0x1068:u
After rebooting, there were three I2C devices.
opipc@orangepipc2:~$ ls -l /dev/i2c*
crw-rw---- 1 root i2c 89, 1 Mar 4 14:28 /dev/i2c-1 Hardware I2C bus on physical pins 27 and 28
crw-rw---- 1 root i2c 89, 2 Mar 4 14:28 /dev/i2c-2 Spurious I2C bus
crw-rw---- 1 root i2c 89, 3 Mar 4 14:28 /dev/i2c-3 Internal I2C bus for SY8106A voltage regulator
I created a directory and copied the overlay source file to it.
opipc@orangepipc2:~$ mkdir ds1307_dts
opipc@orangepipc2:~$ wget https://raw.githubusercontent.com/armbian/sunxi-DT-overlays/master/examples/i2c-ds1307.dts -O ds1307_dts/i2c-ds1307.dts
I changed the alias to set the DS3231 as device rtc1
instead of rtc0
so that hwclock
can read/write both the DS3231 and the built-in real-time clock.
opipc@orangepipc2:~$ cat ds1307_dts/i2c-ds1307.dts
/dts-v1/;
/plugin/;
/ {
compatible = "allwinner,sun4i-a10", "allwinner,sun7i-a20", "allwinner,sun8i-h3", "allwinner,sun50i-a64", "allwinner,sun50i-h5";
/*
* Aliases can be used to set the external RTC as rtc0
* Needs supplying the correct path to the I2C controller RTC is connected to,
* this example is for I2C1 on H3 - works on I2C1 H5
* NOTE: setting time at boot by the kernel
* may not work in some cases if the external RTC module is loaded too late
*/
fragment@0 {
target-path = "/aliases";
__overlay__ {
#rtc0 = "/soc/i2c@01c2b000/ds1307@68";
rtc1 = "/soc/i2c@01c2b000/ds1307@68";
};
};
fragment@1 {
target = <&i2c1>;
__overlay__ {
#address-cells = <1>;
#size-cells = <0>;
ds1307@68 {
compatible = "dallas,ds1307";
reg = <0x68>;
status = "okay";
};
};
};
};
If the hardware clock was to be connected to the PA12 and PA11 I2C bus and appear as rtc3
in the /dev directory then the "alias" fragment should be rtc3 = "/soc//i2c@1c2ac00/ds1307@68";
. Of course, the i2c0
parameter would have to be included in the overlays
line of the /boot/armbianEnv.txt
configuration file.
The overlay had to be compiled and the system then had to be rebooted.
opipc@orangepipc2:~/ds1307_dts$ sudo armbian-add-overlay i2c-ds1307.dts
Compiling the overlay
Copying the compiled overlay file to /boot/overlay-user/
Reboot is required to apply the changes
A first check of I2C buses, loaded kernel modules and rtc
devices after the reboot was very encouraging.
opipc@orangepipc2:~$ ls -l /sys/bus/i2c/devices/
total 0
lrwxrwxrwx 1 root root 0 Mar 5 21:18 1-0068 -> ../../../devices/platform/soc/1c2b000.i2c/i2c-1/1-0068
lrwxrwxrwx 1 root root 0 Mar 5 21:18 3-0065 -> ../../../devices/platform/soc/1f02400.i2c/i2c-3/3-0065
lrwxrwxrwx 1 root root 0 Mar 5 21:18 i2c-1 -> ../../../devices/platform/soc/1c2b000.i2c/i2c-1
lrwxrwxrwx 1 root root 0 Mar 5 21:18 i2c-2 -> ../../../devices/platform/soc/1ee0000.hdmi/i2c-2
lrwxrwxrwx 1 root root 0 Mar 5 21:18 i2c-3 -> ../../../devices/platform/soc/1f02400.i2c/i2c-3
opipc@orangepipc2:~$ lsmod | grep ds1307
rtc_ds1307 32768 0
opipc@orangepipc2:~$ ls -l /dev/rtc*
lrwxrwxrwx 1 root root 4 Mar 4 15:40 /dev/rtc -> rtc0
crw------- 1 root root 253, 0 Mar 4 15:40 /dev/rtc0
crw------- 1 root root 253, 1 Mar 4 15:40 /dev/rtc1
The following shows that the system utility hwclock
can be used to read or set the time of both the external DS3231 real-time clock and the internal real-time clock.
opipc@orangepipc2:~$ sudo hwclock -D
hwclock from util-linux 2.31.1
System Time: 1583350900.345862
Trying to open: /dev/rtc0
Using the rtc interface to the clock.
Assuming hardware clock is kept in UTC time.
Waiting for clock tick...
...got clock tick
Time read from Hardware Clock: 2020/03/04 19:41:42
Hw clock time : 2020/03/04 19:41:42 = 1583350902 seconds since 1969
Time since last adjustment is 1583350902 seconds
Calculated Hardware Clock drift is 0.000000 seconds
2020-03-04 15:41:40.143502-0400
opipc@orangepipc2:~$ sudo hwclock -f /dev/rtc1 -D
hwclock from util-linux 2.31.1
System Time: 1583350951.574846
Using the rtc interface to the clock.
Assuming hardware clock is kept in UTC time.
Waiting for clock tick...
ioctl(4, RTC_UIE_ON, 0): Invalid argument
Waiting in loop for time from /dev/rtc1 to change
...got clock tick
Time read from Hardware Clock: 2000/01/01 01:34:52
Hw clock time : 2000/01/01 01:34:52 = 946690492 seconds since 1969
Time since last adjustment is 946690492 seconds
Calculated Hardware Clock drift is 0.000000 seconds
1999-12-31 21:34:50.992573-0400
opipc@orangepipc2:~$ sudo hwclock -f /dev/rtc1 --set --date "2020-03-03 13:52:00" -D
hwclock from util-linux 2.31.1
System Time: 1583351018.357764
Using the rtc interface to the clock.
Assuming hardware clock is kept in UTC time.
1583351018.857764 is close enough to 1583351018.857764 (0.000000 < 0.001000)
Set RTC to 1583257920 (1583257920 + 0; refsystime = 1583351018.357764)
Setting Hardware Clock to 17:52:00 = 1583257920 seconds since 1969
ioctl(RTC_SET_TIME) was successful.
Not adjusting drift factor because the --update-drift option was not used.
New /etc/adjtime data:
0.000000 1583257920 0.000000
1583257920
UTC
opipc@orangepipc2:~$ date
Wed Mar 4 16:08:18 AST 2020
opipc@orangepipc2:~$ sudo hwclock
2020-03-04 16:08:11.146445-0400
opipc@orangepipc2:~$ sudo hwclock -f /dev/rtc1
2020-03-03 14:16:54.798416-0400
As far as I know, armbian-add-overlay
compiles i2c-ds1307.dts
to /boot/overlay-user/i2c-ds1307.dtbo
and added the user_overlays
line in /boot/armbianEnv.txt
.
opipc@orangepipc2:~$ ls -l /boot/overlay-user
total 4
-rw-r--r-- 1 root root 640 Mar 4 15:39 i2c-ds1307.dtbo
opipc@orangepipc2:~$ cat /boot/armbianEnv.txt
verbosity=1
console=both
overlay_prefix=sun50i-h5
rootdev=UUID=a948f949-ea06-4a76-9d5d-4c9da81e0efe
rootfstype=ext4
overlays=i2c1
user_overlays=i2c-ds1307
usbstoragequirks=0x2537:0x1066:u,0x2537:0x1068:u
So to remove the overlay, I deleted the compiled dtbo
file, leaving an empty /boot/overlay-user/
directory, and I removed the user_overlays=i2c-ds1307
line in /boot/armbianEnv.txt
file. After rebooting, /dev/rtc1
was gone.
The armbian-add-overlay
compiler will not add the overlays=i2c1
to the configuration file on its own. This must be done manually as shown above.