diff --git a/tasmota/support.ino b/tasmota/support.ino index fcf21a014..f12c6b007 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -111,6 +111,94 @@ String GetResetReason(void) } } + +/*********************************************************************************************\ + * ESP32 AutoMutex +\*********************************************************************************************/ + +////////////////////////////////////////// +// automutex. +// create a mute in your driver with: +// void *mutex = nullptr; +// TasAutoMutex::init(&mutex); +// +// then protect any function with +// TasAutoMutex m(mutex); +// - it will be automagically released when the function is over. +// - the same thread can take multiple times (recursive). +// - advanced options m.give() and m.take() allow you fine control within a function. +class TasAutoMutex { +#ifdef ESP32 + SemaphoreHandle_t mutex; +#endif + bool taken; + public: + TasAutoMutex(void * mutex, bool take=true); + ~TasAutoMutex(); + void give(); + void take(); + static void init(void ** ptr); +}; +////////////////////////////////////////// + +TasAutoMutex::TasAutoMutex(void * mutex, bool take){ +#ifdef ESP32 + if(mutex){ + if (take){ + xSemaphoreTakeRecursive(mutex, portMAX_DELAY); + this->taken = true; + } + this->mutex = (SemaphoreHandle_t ) mutex; + } else { + this->mutex = (SemaphoreHandle_t )nullptr; + } +#endif +} + +TasAutoMutex::~TasAutoMutex(){ +#ifdef ESP32 + if (this->mutex){ + if (this->taken){ + xSemaphoreGiveRecursive(this->mutex); + this->taken = false; + } + } +#endif +} + +void TasAutoMutex::init(void ** ptr){ +#ifdef ESP32 + SemaphoreHandle_t mutex = xSemaphoreCreateRecursiveMutex(); + (*ptr) = (void *) mutex; +#else + // needed, else we will initialis more than once in logging + (*ptr) = (void *) 1; +#endif +} + +void TasAutoMutex::give(){ +#ifdef ESP32 + if (this->mutex){ + if (this->taken){ + xSemaphoreGiveRecursive(this->mutex); + this->taken= false; + } + } +#endif +} +void TasAutoMutex::take(){ +#ifdef ESP32 + if (this->mutex){ + if (!this->taken){ + xSemaphoreTakeRecursive(this->mutex, portMAX_DELAY); + this->taken = true; + } + } +#endif +} + + + /*********************************************************************************************\ * Miscellaneous \*********************************************************************************************/ @@ -1958,6 +2046,10 @@ void SyslogAsync(bool refresh) { } bool NeedLogRefresh(uint32_t req_loglevel, uint32_t index) { + // this takes the mutex, and will be release when the class is destroyed - + // i.e. when the functon leaves You CAN call mutex.give() to leave early. + TasAutoMutex mutex(TasmotaGlobal.log_buffer_mutex); + // Skip initial buffer fill if (strlen(TasmotaGlobal.log_buffer) < LOG_BUFFER_SIZE - LOGSZ) { return false; } @@ -1973,6 +2065,10 @@ bool GetLog(uint32_t req_loglevel, uint32_t* index_p, char** entry_pp, size_t* l if (TasmotaGlobal.uptime < 3) { return false; } // Allow time to setup correct log level if (!req_loglevel || (index == TasmotaGlobal.log_buffer_pointer)) { return false; } + // this takes the mutex, and will be release when the class is destroyed - + // i.e. when the functon leaves You CAN call mutex.give() to leave early. + TasAutoMutex mutex(TasmotaGlobal.log_buffer_mutex); + if (!index) { // Dump all index = TasmotaGlobal.log_buffer_pointer +1; if (index > 255) { index = 1; } @@ -2011,9 +2107,18 @@ bool GetLog(uint32_t req_loglevel, uint32_t* index_p, char** entry_pp, size_t* l } void AddLogData(uint32_t loglevel, const char* log_data) { + + if (!TasmotaGlobal.log_buffer_mutex){ + TasAutoMutex::init(&TasmotaGlobal.log_buffer_mutex); + } + char mxtime[14]; // "13:45:21.999 " snprintf_P(mxtime, sizeof(mxtime), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d.%03d "), RtcTime.hour, RtcTime.minute, RtcTime.second, RtcMillis()); + // this takes the mutex, and will be release when the class is destroyed - + // i.e. when the functon leaves You CAN call mutex.give() to leave early. + TasAutoMutex mutex(TasmotaGlobal.log_buffer_mutex); + if ((loglevel <= TasmotaGlobal.seriallog_level) && (TasmotaGlobal.masterlog_level <= TasmotaGlobal.seriallog_level)) { Serial.printf("%s%s\r\n", mxtime, log_data); diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index b70bd4637..cf35a1fa7 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -171,6 +171,7 @@ struct { char mqtt_topic[TOPSZ]; // Composed MQTT topic char mqtt_data[MESSZ]; // MQTT publish buffer and web page ajax buffer char log_buffer[LOG_BUFFER_SIZE]; // Web log buffer + void *log_buffer_mutex; // control, access to log buffer } TasmotaGlobal; #ifdef SUPPORT_IF_STATEMENT