Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

i2c default clock speed for Pi Pico (RP2040) is 90.9kHz (and 400kHz is around 265kHz) #4466

Closed
kevinjwalters opened this issue Mar 23, 2021 · 11 comments
Labels
bug rp2040 Raspberry Pi RP2040

Comments

@kevinjwalters
Copy link

kevinjwalters commented Mar 23, 2021

I've not had any particular i2c issues but looking at #4082 the clock speed looked wrong on both boards including the Pi Pico running 6.2.0-beta.1. Here's a view from Ikalogic SQ25 of a (Maker) Pi Pico talking to a generic SSD1306-driven screen and using the change contrast command to get something to capture (at 25MHz).

ScanaStudio-pi-pico-slow-i2c-clock-1

This has the 10k pullups on SSD1306 and whatever the RP2040 might be doing. The Maker Pi Pico adds 3M3 to GND on each GPIO and a mosfet gate to drive LED but I don't see that making any difference here.

I took those 3 measurements and 3 others to get mean of 90.8827kHz. That's suspiciously close to 1000/11 = 90.9090.

Would be useful if someone could confirm i2c speed on Pi Pico and perhaps another established processor. These examples are from 6.2.0-beta.4, not 6.2.0-beta.1.

Adafruit CircuitPython 6.2.0-beta.4 on 2021-03-18; Raspberry Pi Pico with rp2040
>>> import board
>>> import busio
>>> i2c = busio.I2C(scl=board.GP1, sda=board.GP0)
>>> i2c.try_lock()
True
>>> buffer = bytearray(2)
>>> buffer[0] = 0x81  ### set contrast command
>>> buffer[1] = 0x80
>>> i2c.writeto(60, buffer)

Same result with frequency=100_000. Oddly, frequency=110_000 gives actual 111.193kHz.

And frequency=400_000 gives actual 250.000 kHz, shown below:

ScanaStudio_pi-pico-6 2 0 beta 4-wanted400-got250withfatpulses-1

That also shows up some fat clock pulses. The first one is 6.88us, the second one 3.16us then it settles into the circa 2.9us rhythm.

For comparison I had a look back at an old trace from a Gemma M0 talking to a bear running CircuitPython 2.2.0 (this is only at 1MHz capture) and everything is much more regular.

ScanaStudio-gemma-m0-pimoroni-bearable-201807vintage-1

@kevinjwalters
Copy link
Author

kevinjwalters commented Mar 23, 2021

I tried some 4 byte writes as I'm pretty sure I've read a discussion (perhaps with @Gadgetoid) about the special case bitbang code kicking in at <= X where X may equal 2.

The trace looks very different for 4 byte write. Here's first part. It's sped up a bit to 265kHz but it's still not the requested 400kHz.

ScanaStudio_pi-pico-6 2 0 beta 4-wanted400-got265-4bytewrite-1

I found related tickets: #4315 and #4378 and maybe raspberrypi/pico-sdk#252

@Gadgetoid
Copy link

@kevinjwalters yes currently any write <= 2 bytes will go through a bitbangio instance:

uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr,
const uint8_t *data, size_t len, bool transmit_stop_bit) {
if (len <= 2) {

I've got an outstanding PR to change this to == 0 since rp2040 can handle 1 and 2 byte writes fine but will not do a 0-byte address-only write (used to check for the address ACK when probing the bus). I think this was the result of some misunderstanding or very early SDK bug.

@dhalbert
Copy link
Collaborator

@kevinjwalters The 2 bytes-or-fewer writes are done using bitbangio and I would expect their timing to be approximate. The other off-timing may be due to clock divisor granularity.

@kevinjwalters
Copy link
Author

kevinjwalters commented Mar 23, 2021

FYI, my PyPortal (SAMD51 / M4) talking to its ADT7410 running 6.1.0 matches the two traces in speed @caternuson put in the other ticket at 94.697 kHz.

@tannewt tannewt added this to the 6.x.x - Bug Fixes milestone Mar 23, 2021
@tannewt tannewt added the rp2040 Raspberry Pi RP2040 label Mar 23, 2021
@kevinjwalters kevinjwalters changed the title i2c default clock speed for Pi Pico (RP2040) is 90.9kHz i2c default clock speed for Pi Pico (RP2040) is 90.9kHz (and 400kHz is around 250kHz) Mar 24, 2021
@kevinjwalters
Copy link
Author

kevinjwalters commented Mar 24, 2021

@dhalbert 786k is the new 400k.

Adafruit CircuitPython 6.2.0-beta.4 on 2021-03-18; Raspberry Pi Pico with rp2040
>>> import board, busio
>>> i2c = busio.I2C(scl=board.GP1, sda=board.GP0, frequency=786_000)
>>> big_buf = bytearray([0x81, 0x46, 0x81, 0x55])  ### four bytes to dodge the bitbang version
>>> i2c.try_lock()
True
>>> i2c.writeto(60, big_buf)

From three runs measuring a chunk of clock pulses

Average Frequency = 399.436 kHz
Average Frequency = 401.070 kHz
Average Frequency = 399.787 kHz

Does this mean it's a bug in https://github.com/raspberrypi/pico-sdk ?

@kevinjwalters kevinjwalters changed the title i2c default clock speed for Pi Pico (RP2040) is 90.9kHz (and 400kHz is around 250kHz) i2c default clock speed for Pi Pico (RP2040) is 90.9kHz (and 400kHz is around 265kHz) Mar 24, 2021
@dhalbert
Copy link
Collaborator

dhalbert commented Mar 24, 2021

The speeds you ask for may not be precisely available based on the way the peripheral clock is generated. It's usually generated by dividing a higher-speed clock. I don't think it's necessarily a bug; you'd need to study the clock setting in the I2C driver.

This is common: for instance, when we have high SPI speeds on other chips, they are very approximate because the divisors are quite small.

EDIT: It may also be the case that the speeds deemed to be made available are only 100k and 400k (and maybe 1MHz) also. So it picks the closest lower speed, for example.

@dhalbert
Copy link
Collaborator

So based on your testing of 4-byte writes this issue title could be revised.

@kevinjwalters
Copy link
Author

I graphed the data

rp2040-i2c-v1-g1

Would be good is someone else could check it in case my SQ25 is misbehaving but that seems unlikely.

@dhalbert
Copy link
Collaborator

We just pass the frequency on to the pico-sdk. Its frequency-setting code is here:
https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/hardware_i2c/i2c.c#L63=L90.

@kevinjwalters
Copy link
Author

kevinjwalters commented Mar 25, 2021

That's what I thought. I put in raspberrypi/pico-sdk#283 for this. I'll close this when it's acknowledged by RPi folk. It's curious the bitbang code is slow. 400kHz looks like it should make the us_delay 1us rather than 2us but perhaps I'm misreading the code or perhaps there's some overhead to get to the underlying delay function.

Would be interesting to hear from anyone who has timed SDK's busy_wait_us_32().

@kevinjwalters
Copy link
Author

kevinjwalters commented Mar 25, 2021

This is the RP2040 doing clock stretching apparently and pull-ups have an effect on speed. It will be interesting to see if it's doing it in appropriate places for fast mode.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug rp2040 Raspberry Pi RP2040
Projects
None yet
Development

No branches or pull requests

4 participants