From 35e9cf2db255d08a4dcf612e81405e69cabd4403 Mon Sep 17 00:00:00 2001 From: Mirco Pizzichini Date: Wed, 26 Apr 2023 14:00:12 +0200 Subject: [PATCH] Add lock to protect concurrent i2c transactions performed by different tasks --- libraries/Wire/src/Wire.cpp | 53 ++++++++++++++++++++----------------- libraries/Wire/src/Wire.h | 2 +- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/libraries/Wire/src/Wire.cpp b/libraries/Wire/src/Wire.cpp index ae05e2752a0..ca6a7f1d4e5 100644 --- a/libraries/Wire/src/Wire.cpp +++ b/libraries/Wire/src/Wire.cpp @@ -48,7 +48,7 @@ TwoWire::TwoWire(uint8_t bus_num) ,_timeOutMillis(50) ,nonStop(false) #if !CONFIG_DISABLE_HAL_LOCKS - ,nonStopTask(NULL) + ,currentTaskHandle(NULL) ,lock(NULL) #endif ,is_slave(false) @@ -412,15 +412,15 @@ void TwoWire::beginTransmission(uint16_t address) return; } #if !CONFIG_DISABLE_HAL_LOCKS - if(nonStop && nonStopTask == xTaskGetCurrentTaskHandle()){ - log_e("Unfinished Repeated Start transaction! Expected requestFrom, not beginTransmission! Clearing..."); - //release lock - xSemaphoreGive(lock); - } - //acquire lock - if(lock == NULL || xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){ - log_e("could not acquire lock"); - return; + TaskHandle_t task = xTaskGetCurrentTaskHandle(); + if (currentTaskHandle != task) + { + //acquire lock + if(lock == NULL || xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){ + log_e("could not acquire lock"); + return; + } + currentTaskHandle = task; } #endif nonStop = false; @@ -452,15 +452,13 @@ uint8_t TwoWire::endTransmission(bool sendStop) if(sendStop){ err = i2cWrite(num, txAddress, txBuffer, txLength, _timeOutMillis); #if !CONFIG_DISABLE_HAL_LOCKS + currentTaskHandle = NULL; //release lock xSemaphoreGive(lock); #endif } else { //mark as non-stop nonStop = true; -#if !CONFIG_DISABLE_HAL_LOCKS - nonStopTask = xTaskGetCurrentTaskHandle(); -#endif } switch(err){ case ESP_OK: return 0; @@ -482,13 +480,26 @@ size_t TwoWire::requestFrom(uint16_t address, size_t size, bool sendStop) return 0; } esp_err_t err = ESP_OK; - if(nonStop #if !CONFIG_DISABLE_HAL_LOCKS - && nonStopTask == xTaskGetCurrentTaskHandle() -#endif - ){ + 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 + if(nonStop){ if(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; } nonStop = false; @@ -499,13 +510,6 @@ size_t TwoWire::requestFrom(uint16_t address, size_t size, bool sendStop) log_e("i2cWriteReadNonStop returned Error %d", err); } } 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; rxLength = 0; err = i2cRead(num, address, rxBuffer, size, _timeOutMillis, &rxLength); @@ -514,6 +518,7 @@ size_t TwoWire::requestFrom(uint16_t address, size_t size, bool sendStop) } } #if !CONFIG_DISABLE_HAL_LOCKS + currentTaskHandle = NULL; //release lock xSemaphoreGive(lock); #endif diff --git a/libraries/Wire/src/Wire.h b/libraries/Wire/src/Wire.h index 339b0e2866f..646ee4be4a3 100644 --- a/libraries/Wire/src/Wire.h +++ b/libraries/Wire/src/Wire.h @@ -64,7 +64,7 @@ class TwoWire: public Stream uint32_t _timeOutMillis; bool nonStop; #if !CONFIG_DISABLE_HAL_LOCKS - TaskHandle_t nonStopTask; + TaskHandle_t currentTaskHandle; SemaphoreHandle_t lock; #endif private: