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

ESP32/ESP32-S2: I2C Workaround #3199

Open
wants to merge 12 commits into
base: main
Choose a base branch
from

Conversation

bjoernQ
Copy link
Contributor

@bjoernQ bjoernQ commented Mar 3, 2025

Thank you for your contribution!

We appreciate the time and effort you've put into this pull request.
To help us review it efficiently, please ensure you've gone through the following checklist:

Submission Checklist 📝

  • I have updated existing examples or added new ones (if applicable).
  • I have used cargo xtask fmt-packages command to ensure that all changed code is formatted correctly.
  • My changes were added to the CHANGELOG.md in the proper section.
  • I have added necessary changes to user code to the Migration Guide.
  • My changes are in accordance to the esp-rs API guidelines

Extra:

Pull Request Details 📖

Description

Fixes #3178
Fixes #3167

Basically, this does three things

  • don't combine STOP with other commands
  • try to place END at the same index during a write, read and write_read
  • don't use FIFO wrapping (to prevent timing issues)

I don't see how to guarantee things will always work for a custom transaction on ESP32/ESP32-S2 - so I added some docs

Testing

I used an VL53L5 sensor (which requires large (32k) writes and reads (a few hundred bytes). Additionally, I tested with a bit-banged I2C slave ( https://github.com/bjoernQ/i2c-dummy-device )

@bugadani
Copy link
Contributor

bugadani commented Mar 3, 2025

We need a test case in the HIL tester that fails without this PR.

@bjoernQ bjoernQ changed the title Esp32 i2c fix for real ESP32/ESP32-S2: I2C Workaround Mar 3, 2025
@bjoernQ
Copy link
Contributor Author

bjoernQ commented Mar 3, 2025

We need a test case in the HIL tester that fails without this PR.

I would love that, but we would need a suitable I2C slave - seems the BMP180 doesn't like to get large writes/reads

@@ -71,7 +71,7 @@ mod tests {
}
}

assert_eq!(ctx.i2c.write(DUT_ADDRESS, &[]), Ok(()));
assert_eq!(ctx.i2c.write(DUT_ADDRESS, &[0xaa]), Ok(()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wrong, we need to support 0-byte writes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah - yeah now I see it was not always a no-op apparently

Copy link
Member

@MabezDev MabezDev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for looking into this, I'm sure it wasn't fun :D.

First review iteration is mostly focused on understanding what's going on here.

@bjoernQ bjoernQ marked this pull request as ready for review March 3, 2025 16:38
@bjoernQ
Copy link
Contributor Author

bjoernQ commented Mar 4, 2025

We need a test case in the HIL tester that fails without this PR.

As said we can't with the BMP180 - one thing we could do it artificially reduce the FIFO size for the test to force the error (maybe) - not sure if that is something we really want - if we want it, we could make the FIFO size user-configurable

@Dominaezzz
Copy link
Collaborator

Dominaezzz commented Mar 4, 2025

we can't with the BMP180

In case y'all decide to add another i2c slave, I vote for a gpio expander, as it can be validated with other peripherals (Like RMT, SPI slave, pcnt, etc)

They also tend to support infinite reads and writes

@bugadani
Copy link
Contributor

bugadani commented Mar 4, 2025

Probably fixes #3060

Copy link
Member

@MabezDev MabezDev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you!

re hil test: I think we definitely want one here, we don't want to debug this again :D, but I suggest that we can merge this and open an issue for adding the test once the hardware arrives.

@@ -2415,8 +2587,13 @@ impl Driver<'_> {
if buffer.is_empty() {
return self.write_operation_blocking(address, &[], start, stop);
}
let chunk_count = buffer.len().div_ceil(I2C_CHUNK_SIZE);
for (idx, chunk) in buffer.chunks(I2C_CHUNK_SIZE).enumerate() {
let chunk_size = if buffer.len() % I2C_CHUNK_SIZE < 2 {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the logic here? Are you trying to avoid having a single byte chunk at the end? Because if so, it's still possible. For esp32, chunk_size is either 31 or 29. If the buffer length is slightly longer than 31 * 29 = 899, the last chunk will be the same size for each chunk_size. Indeed I am hitting timeouts when the buffer length is 900 and 901.

For me on esp32 I am hitting timeouts with certain buffer sizes when the last chunk is of size is 2. So any buffer length in the set {31, 64, 95, 126 ...}, I cannot finish the read (the last chunk times out).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True - this needs to get fixed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But the good news it's that the general way to handle it is fine

@bjoernQ bjoernQ force-pushed the esp32-i2c-fix-for-real branch from a7a24d3 to e06ad6c Compare March 5, 2025 09:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

I2C timeouts reading ublox gps Frequent I2C timeouts when running I2C alongside WiFi stack
5 participants