-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Add lock in Wire.cpp to protect concurrent i2c transactions performed by different tasks #8127
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
Conversation
|
Can you please provide example code that can replicate the issue you are seeing? The code is meant to release the lock only if called from the same task that last called |
Sorry but now I don't have any example code... I should work on it to recreate a simple example. int8_t readBytes(uint8_t regAddr, uint8_t length, uint8_t *data)
{
Wire.beginTransmission(devAddr);
Wire.write(regAddr);
Wire.endTransmission(false);
return Wire.requestFrom(devAddr, length, data);
} The uint8_t TwoWire::endTransmission(bool sendStop)
{
...
nonStop = true;
// HERE --> the other task call its beginTransmission
#if !CONFIG_DISABLE_HAL_LOCKS
nonStopTask = xTaskGetCurrentTaskHandle();
#endif
...
} In this case, T2 finds nonStop as true, but nonStopTask is not updated yet (it's still T2 and not T1). So T2 tries to release the lock because both conditions are true, but the last task which acquired the lock was T1 (hence the assert) if(nonStop && nonStopTask == xTaskGetCurrentTaskHandle()) {
log_e("Unfinished Repeated Start transaction! Expected requestFrom, not beginTransmission! Clearing...");
//release lock
xSemaphoreGive(lock);
} With my commit, all i2c transactions are protected, not only the non-stop transactions. |
Adding to 3.0.0 milestone so we will resolve this. |
Description of Change
This is the problem. In my application, two different tasks access the i2c.
Sometimes I get the following assert:
This comes from this piece of code:
The xSemaphoreGive is not always correct, because I can't release a mutex if it is taken by another thread.
The solution is to protect all i2c transaction, by taking the lock at the beginning of each transaction if the current task is different from the one already performing a i2c transaction.
Tests scenarios
I have tested my Pull Request on Arduino-esp32 core v2.0.8 with ESP32 Board with this scenario.