Why is software I2C faster than hardware I2C?

All ESP32 boards running MicroPython.
Target audience: MicroPython users with an ESP32 board.
Post Reply
Moo
Posts: 2
Joined: Wed May 27, 2020 9:31 am

Why is software I2C faster than hardware I2C?

Post by Moo » Wed May 27, 2020 10:20 am

Hi,
When I set up a nominally 400 kbit/s software I2C bus on an ESP32 it runs significantly faster than when I set it up as a hardware I2C bus at the same frequency. Should this not be the other way around, if there's any difference at all? I'm interested in this as I'd like to minimise time taken by I2C communications. The software I2C bus takes about 250 μs to read one byte from a peripheral's register, whereas the hardware implementation takes about 420 μs.

I see from github that there's some granularity in the achievable bus frequencies for a software I2C implementation, but if I understood this correctly they shouldn't be faster than specified, so that doesn't seem to explain it.

Does anyone have any suggestions for why this may be, or hints about how I can make sure that my I2C bus is going at it's full speed?


Further info:

I'm using micropython v1.12 on an ESP32-WROOM-32D on a DFRobot Firebeetle board, communicating with an LSM9DS1 sensor (that supports an I2C frequency of up to 400 kbit/s). The software I2C bus is set up as follows:

Code: Select all

from machine import Pin, I2C
i2c = I2C(-1, scl=Pin(22), sda=Pin(14), freq=400_000)
and the hardware I2C bus is set up as follows:

Code: Select all

from machine import Pin, I2C
i2c = I2C(0, scl=Pin(22), sda=Pin(14), freq=400_000)
--------------------
Matt

User avatar
tve
Posts: 216
Joined: Wed Jan 01, 2020 10:12 pm
Location: Santa Barbara, CA
Contact:

Re: Why is software I2C faster than hardware I2C?

Post by tve » Wed May 27, 2020 3:00 pm

I can't tell from your message what you're measuring when you speak about speed. Did you hook up an oscilloscope and measure the clock frequency or do you measure elapsed time for a specific set of I2C transactions? If the latter, please post your test code.

Moo
Posts: 2
Joined: Wed May 27, 2020 9:31 am

Re: Why is software I2C faster than hardware I2C?

Post by Moo » Fri May 29, 2020 8:59 am

Hi tve, it's the latter: I don't have a scope available so I'm just timing how long it takes to repeatedly read a byte lots of times. Test code is below.

Code: Select all

'''
Comparison of the time taken to read a register from a peripheral over the I2C bus
when implemented in hardware or software.
'''
import time
from machine import Pin, I2C
from micropython import const

# number of times to run function to time it
N = 1000

# address of the peripheral on the I2C bus
device_address = const(0x6b)

# register address to read from
reg_address = const(0x0f)

def repeat_read_byte(i2c, n):
	'''
	repeatedly read 1 byte over the I2C bus

	## parameters
	`i2c` - machine.I2C bus object to use for the communication
	`n` - number of times to read the byte
	'''
	# allocate a buffer to store the repeatedly read byte into
	buf = bytearray(1)

	# cache the function for reading the byte (provides a small speed increase)
	read = i2c.readfrom_mem_into

	# read a byte over I2C bus n times
	for i in range(n):
		read(device_address, reg_address, buf)

def hardware_i2c(n):
	'''read 1 byte over a hardware I2C bus n times'''
	i2c = I2C(0, scl=Pin(22), sda=Pin(14), freq=400_000)
	repeat_read_byte(i2c, n)

def software_i2c(n):
	'''read 1 byte over a software I2C bus n times'''
	i2c = I2C(-1, scl=Pin(22), sda=Pin(14), freq=400_000)
	repeat_read_byte(i2c, n)

def time_it(f, n):
	'''
	print the running time of funciton f, that performs a task n times
	Inspired by this PyCon talk: https://www.youtube.com/watch?v=hHec4qL00x0
	'''
	t0 = time.ticks_us()
	f(n)
	t1 = time.ticks_us()
	dt = time.ticks_diff(t1, t0)
	fmt = '{:5.3f} sec, {:6.3f} usec/read : {:8.2f} reads/sec'
	print(fmt.format(dt * 1e-6, dt / N, N / dt * 1e6))

print('hardware I2C performance:')
time_it(hardware_i2c, N)
print('')
print('software I2C performance:')
time_it(software_i2c, N)
It outputs:
hardware I2C performance:
0.424 sec, 424.261 usec/read : 2357.04 reads/sec

software I2C performance:
0.255 sec, 254.730 usec/read : 3925.73 reads/sec
----------
Matt

User avatar
tve
Posts: 216
Joined: Wed Jan 01, 2020 10:12 pm
Location: Santa Barbara, CA
Contact:

Re: Why is software I2C faster than hardware I2C?

Post by tve » Sat May 30, 2020 5:13 pm

The hardware i2c just has higher per transaction overhead...

Post Reply