Add lock to protect concurrent i2c transactions performed by different tasks (#8127)

Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com>
This commit is contained in:
Mirco Pizzichini 2023-11-29 10:42:56 +01:00 committed by GitHub
parent e99437c850
commit db7b3495d5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 25 deletions

View file

@ -52,7 +52,7 @@ TwoWire::TwoWire(uint8_t bus_num)
,_timeOutMillis(50) ,_timeOutMillis(50)
,nonStop(false) ,nonStop(false)
#if !CONFIG_DISABLE_HAL_LOCKS #if !CONFIG_DISABLE_HAL_LOCKS
,nonStopTask(NULL) ,currentTaskHandle(NULL)
,lock(NULL) ,lock(NULL)
#endif #endif
#if SOC_I2C_SUPPORT_SLAVE #if SOC_I2C_SUPPORT_SLAVE
@ -433,16 +433,16 @@ void TwoWire::beginTransmission(uint16_t address)
} }
#endif /* SOC_I2C_SUPPORT_SLAVE */ #endif /* SOC_I2C_SUPPORT_SLAVE */
#if !CONFIG_DISABLE_HAL_LOCKS #if !CONFIG_DISABLE_HAL_LOCKS
if(nonStop && nonStopTask == xTaskGetCurrentTaskHandle()){ TaskHandle_t task = xTaskGetCurrentTaskHandle();
log_e("Unfinished Repeated Start transaction! Expected requestFrom, not beginTransmission! Clearing..."); if (currentTaskHandle != task)
//release lock {
xSemaphoreGive(lock);
}
//acquire lock //acquire lock
if(lock == NULL || xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){ if(lock == NULL || xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
log_e("could not acquire lock"); log_e("could not acquire lock");
return; return;
} }
currentTaskHandle = task;
}
#endif #endif
nonStop = false; nonStop = false;
txAddress = address; txAddress = address;
@ -475,15 +475,13 @@ uint8_t TwoWire::endTransmission(bool sendStop)
if(sendStop){ if(sendStop){
err = i2cWrite(num, txAddress, txBuffer, txLength, _timeOutMillis); err = i2cWrite(num, txAddress, txBuffer, txLength, _timeOutMillis);
#if !CONFIG_DISABLE_HAL_LOCKS #if !CONFIG_DISABLE_HAL_LOCKS
currentTaskHandle = NULL;
//release lock //release lock
xSemaphoreGive(lock); xSemaphoreGive(lock);
#endif #endif
} else { } else {
//mark as non-stop //mark as non-stop
nonStop = true; nonStop = true;
#if !CONFIG_DISABLE_HAL_LOCKS
nonStopTask = xTaskGetCurrentTaskHandle();
#endif
} }
switch(err){ switch(err){
case ESP_OK: return 0; case ESP_OK: return 0;
@ -507,13 +505,26 @@ size_t TwoWire::requestFrom(uint16_t address, size_t size, bool sendStop)
return 0; return 0;
} }
esp_err_t err = ESP_OK; esp_err_t err = ESP_OK;
if(nonStop
#if !CONFIG_DISABLE_HAL_LOCKS #if !CONFIG_DISABLE_HAL_LOCKS
&& nonStopTask == xTaskGetCurrentTaskHandle() TaskHandle_t task = xTaskGetCurrentTaskHandle();
if (currentTaskHandle != task)
{
//acquire lock
if(lock == NULL || xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
log_e("could not acquire lock");
return 0;
}
currentTaskHandle = task;
}
#endif #endif
){ if(nonStop){
if(address != txAddress){ if(address != txAddress){
log_e("Unfinished Repeated Start transaction! Expected address do not match! %u != %u", address, txAddress); log_e("Unfinished Repeated Start transaction! Expected address do not match! %u != %u", address, txAddress);
#if !CONFIG_DISABLE_HAL_LOCKS
currentTaskHandle = NULL;
//release lock
xSemaphoreGive(lock);
#endif
return 0; return 0;
} }
nonStop = false; nonStop = false;
@ -524,13 +535,6 @@ size_t TwoWire::requestFrom(uint16_t address, size_t size, bool sendStop)
log_e("i2cWriteReadNonStop returned Error %d", err); log_e("i2cWriteReadNonStop returned Error %d", err);
} }
} else { } else {
#if !CONFIG_DISABLE_HAL_LOCKS
//acquire lock
if(lock == NULL || xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
log_e("could not acquire lock");
return 0;
}
#endif
rxIndex = 0; rxIndex = 0;
rxLength = 0; rxLength = 0;
err = i2cRead(num, address, rxBuffer, size, _timeOutMillis, &rxLength); err = i2cRead(num, address, rxBuffer, size, _timeOutMillis, &rxLength);
@ -539,6 +543,7 @@ size_t TwoWire::requestFrom(uint16_t address, size_t size, bool sendStop)
} }
} }
#if !CONFIG_DISABLE_HAL_LOCKS #if !CONFIG_DISABLE_HAL_LOCKS
currentTaskHandle = NULL;
//release lock //release lock
xSemaphoreGive(lock); xSemaphoreGive(lock);
#endif #endif

View file

@ -69,7 +69,7 @@ protected:
uint32_t _timeOutMillis; uint32_t _timeOutMillis;
bool nonStop; bool nonStop;
#if !CONFIG_DISABLE_HAL_LOCKS #if !CONFIG_DISABLE_HAL_LOCKS
TaskHandle_t nonStopTask; TaskHandle_t currentTaskHandle;
SemaphoreHandle_t lock; SemaphoreHandle_t lock;
#endif #endif
private: private: