diff --git a/lib/channel/GwChannelList.cpp b/lib/channel/GwChannelList.cpp index 7861f3d..c9db748 100644 --- a/lib/channel/GwChannelList.cpp +++ b/lib/channel/GwChannelList.cpp @@ -427,6 +427,7 @@ void GwChannelList::begin(bool fallbackSerial){ if (! fallbackSerial){ GwSerial *usbSerial=createSerialImpl(config, logger,USB_CHANNEL_ID,GWUSB_RX,GWUSB_TX,true); if (usbSerial != nullptr){ + usbSerial->enableWriteLock(); //as it is used for logging we need this additionally GwChannel *usbChannel=createChannel(logger,config,USB_CHANNEL_ID,usbSerial,GWSERIAL_TYPE_BI); if (usbChannel != nullptr){ addChannel(usbChannel); diff --git a/lib/queue/GwSynchronized.h b/lib/queue/GwSynchronized.h index 786b5f0..08c36c6 100644 --- a/lib/queue/GwSynchronized.h +++ b/lib/queue/GwSynchronized.h @@ -3,14 +3,26 @@ class GwSynchronized{ private: - SemaphoreHandle_t *locker; + SemaphoreHandle_t locker=nullptr; + void lock(){ + if (locker != nullptr) xSemaphoreTake(locker, portMAX_DELAY); + } public: + /** + * deprecated + * as SemaphoreHandle_t is already a pointer just use this directly + */ GwSynchronized(SemaphoreHandle_t *locker){ + if (locker == nullptr) return; + this->locker=*locker; + lock(); + } + GwSynchronized(SemaphoreHandle_t locker){ this->locker=locker; - if (locker != nullptr) xSemaphoreTake(*locker, portMAX_DELAY); + lock(); } ~GwSynchronized(){ - if (locker != nullptr) xSemaphoreGive(*locker); + if (locker != nullptr) xSemaphoreGive(locker); } }; diff --git a/lib/serial/GwSerial.cpp b/lib/serial/GwSerial.cpp index c0fb06e..b23c52f 100644 --- a/lib/serial/GwSerial.cpp +++ b/lib/serial/GwSerial.cpp @@ -63,6 +63,7 @@ GwSerial::~GwSerial() { delete buffer; if (readBuffer) delete readBuffer; + if (lock != nullptr) vSemaphoreDelete(lock); } String GwSerial::getMode(){ @@ -87,10 +88,14 @@ size_t GwSerial::enqueue(const uint8_t *data, size_t len, bool partial) } GwBuffer::WriteStatus GwSerial::write(){ if (! isInitialized()) return GwBuffer::ERROR; - size_t numWrite=availableForWrite(); - size_t rt=buffer->fetchData(numWrite,[](uint8_t *buffer,size_t len, void *p){ - return ((GwSerial *)p)->stream->write(buffer,len); - },this); + size_t rt=0; + { + GWSYNCHRONIZED(lock); + size_t numWrite=availableForWrite(); + rt=buffer->fetchData(numWrite,[](uint8_t *buffer,size_t len, void *p){ + return ((GwSerial *)p)->stream->write(buffer,len); + },this); + } if (rt != 0){ LOG_DEBUG(GwLog::DEBUG+1,"Serial %d write %d",id,rt); } diff --git a/lib/serial/GwSerial.h b/lib/serial/GwSerial.h index 5646299..1932878 100644 --- a/lib/serial/GwSerial.h +++ b/lib/serial/GwSerial.h @@ -4,6 +4,7 @@ #include "GwLog.h" #include "GwBuffer.h" #include "GwChannelInterface.h" +#include "GwSynchronized.h" #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 #include "hal/usb_serial_jtag_ll.h" #endif @@ -26,8 +27,12 @@ class GwSerial : public GwChannelInterface{ virtual long getFlushTimeout(){return 2000;} virtual int availableForWrite()=0; int type=0; + SemaphoreHandle_t lock=nullptr; public: GwSerial(GwLog *logger,Stream *stream,int id,int type,bool allowRead=true); + void enableWriteLock(){ + lock=xSemaphoreCreateMutex(); + } virtual ~GwSerial(); bool isInitialized(); virtual size_t sendToClients(const char *buf,int sourceId,bool partial=false);