Unverified Commit db7b3495 authored by Mirco Pizzichini's avatar Mirco Pizzichini Committed by GitHub

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

Co-authored-by: default avatarMe No Dev <me-no-dev@users.noreply.github.com>
parent e99437c8
...@@ -52,7 +52,7 @@ TwoWire::TwoWire(uint8_t bus_num) ...@@ -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,15 +433,15 @@ void TwoWire::beginTransmission(uint16_t address) ...@@ -433,15 +433,15 @@ 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
} if(lock == NULL || xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
//acquire lock log_e("could not acquire lock");
if(lock == NULL || xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){ return;
log_e("could not acquire lock"); }
return; currentTaskHandle = task;
} }
#endif #endif
nonStop = false; nonStop = false;
...@@ -475,15 +475,13 @@ uint8_t TwoWire::endTransmission(bool sendStop) ...@@ -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) ...@@ -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();
#endif if (currentTaskHandle != task)
){ {
//acquire lock
if(lock == NULL || xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
log_e("could not acquire lock");
return 0;
}
currentTaskHandle = task;
}
#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) ...@@ -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) ...@@ -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
......
...@@ -69,7 +69,7 @@ protected: ...@@ -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:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment