Skip to content

I2C driver read() thread safety #8228

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

Closed
1 task done
novirium opened this issue May 19, 2023 · 3 comments
Closed
1 task done

I2C driver read() thread safety #8228

novirium opened this issue May 19, 2023 · 3 comments
Labels
Area: Peripherals API Relates to peripheral's APIs. Resolution: Wontfix Arduino ESP32 team will not fix the issue Type: For reference Common questions & problems Type: Question Only question

Comments

@novirium
Copy link

Board

ESP32 Devkit C V4

Device Description

Plain Devkit C V4

Hardware Configuration

Testing was done with an SX1509 GPIO expander, but this is relevant to any I2C device.

Version

latest master (checkout manually)

IDE Name

PlatformIO

Operating System

Linux

Flash frequency

40Mhz

PSRAM enabled

yes

Upload speed

115200

Description

While a lot of the I2C driver is now largely thread/task safe with the use of the lock mutex, as far as I can tell there is still nothing stopping another task from resetting or writing over the top of rxBuffer once the transmission is finished and the lock is released with requestFrom(), but before the end user has finished calling read() to get the bytes of out the buffer. This has been mentioned directly here, but doesn't look like it was addressed when the I2C driver was refactored to be thread-safe.

There's not really any reliable way of the end user signalling that they're finished with the RX buffer built into the driver, so the only way I can see this working in a thread safe way is to allow a user-allocated buffer be optionally passed into requestFrom(), where received bytes get loaded into that instead.

Understandably, changing the Arduino Wire API probably isn't a popular idea, and allowing a new option wouldn't make existing libraries using I2C thread/task safe anyway, which negates a lot of the benefit.

While at the moment writes are thread safe, very few real-world uses of I2C don't also need to read from the slave device. Without it actually being thread safe, is the current Wire implementation potentially hazardous to users, suggesting it can be used between tasks without extra locks when this will very likely result in intermittent and hard-to-trace errors (chance timing occasionally resulting in RX buffer resets and overwrites)?

Note: I do get that the thread safety is not actually advertised anywhere in the documentation as a feature. This only comes up when people (like me) are looking around for how to implement thread/task safety when dealing with I2C on an ESP32, and come across the code in the Wire implementation here with all the locks scattered through it and the option CONFIG_DISABLE_HAL_LOCKS.

Sketch

_

Debug Message

_

Other Steps to Reproduce

No response

I have checked existing issues, online documentation and the Troubleshooting Guide

  • I confirm I have checked existing issues, online documentation and Troubleshooting guide.
@novirium novirium added the Status: Awaiting triage Issue is waiting for triage label May 19, 2023
@me-no-dev
Copy link
Member

If you want to do a thread-safe reading, I suggest you drop to esp32-hal-i2c API. https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/esp32-hal-i2c.h#L33

The Wire class calls this directly to fill the RX buffer, so you would be all good. Yes, we long thought on options to make Wire.read thread-safe, but as you found yourself, it can not be safe by design and use (not all received data is always fully read by the code. sometimes only a few bytes are what is needed and people leave unread data in the buffers)

@VojtechBartoska VojtechBartoska added Area: Peripherals API Relates to peripheral's APIs. Type: Question Only question and removed Status: Awaiting triage Issue is waiting for triage labels May 19, 2023
@novirium
Copy link
Author

novirium commented May 20, 2023

Yep, or put a lock higher up around library calls ourselves if we want to use pre-existing libraries in different tasks that already use Wire in the standard Arduino way.

This can probably be closed as "wontfix" - it was more to file an issue for people to find if they assume the whole driver is safe to use between tasks, and wind up wondering why it's having intermittent problems.

@me-no-dev me-no-dev added the Type: For reference Common questions & problems label May 22, 2023
@VojtechBartoska
Copy link
Contributor

Hello, closing this as wontfix.

@VojtechBartoska VojtechBartoska closed this as not planned Won't fix, can't repro, duplicate, stale Dec 12, 2023
@VojtechBartoska VojtechBartoska added the Resolution: Wontfix Arduino ESP32 team will not fix the issue label Dec 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: Peripherals API Relates to peripheral's APIs. Resolution: Wontfix Arduino ESP32 team will not fix the issue Type: For reference Common questions & problems Type: Question Only question
Projects
None yet
Development

No branches or pull requests

3 participants