mirror of
https://git.mirrors.martin98.com/https://github.com/luc-github/ESP3D.git
synced 2025-07-31 00:22:03 +08:00
Fix serial2socket module lock after a while
All checks were successful
build-ci / build (push) Successful in 1h42m17s
All checks were successful
build-ci / build (push) Successful in 1h42m17s
This commit is contained in:
parent
6e439231e3
commit
1a0928ed3b
@ -22,7 +22,7 @@
|
||||
#define _VERSION_ESP3D_H
|
||||
|
||||
// version and sources location
|
||||
#define FW_VERSION "3.0.0.6b1"
|
||||
#define FW_VERSION "3.0.0.7b1"
|
||||
#define REPOSITORY "https://github.com/luc-github/ESP3D/tree/3.0"
|
||||
|
||||
#endif //_VERSION_ESP3D_H
|
||||
|
@ -23,6 +23,8 @@
|
||||
|
||||
#if defined(ESP3DLIB_ENV) && COMMUNICATION_PROTOCOL == SOCKET_SERIAL
|
||||
#include <Arduino.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
#include "../../core/esp3d_commands.h"
|
||||
#include "../../core/esp3d_message.h"
|
||||
@ -30,8 +32,34 @@
|
||||
|
||||
Serial_2_Socket Serial2Socket;
|
||||
|
||||
Serial_2_Socket::Serial_2_Socket() { end(); }
|
||||
Serial_2_Socket::~Serial_2_Socket() { end(); }
|
||||
Serial_2_Socket::Serial_2_Socket() {
|
||||
_rxBufferMutex = (void*)xSemaphoreCreateMutex();
|
||||
if (_rxBufferMutex == NULL) {
|
||||
esp3d_log_e("Serial2Socket: Failed to create RX mutex");
|
||||
}
|
||||
|
||||
_txBufferMutex = (void*)xSemaphoreCreateMutex();
|
||||
if (_txBufferMutex == NULL) {
|
||||
esp3d_log_e("Serial2Socket: Failed to create TX mutex");
|
||||
}
|
||||
|
||||
end();
|
||||
}
|
||||
|
||||
Serial_2_Socket::~Serial_2_Socket() {
|
||||
if (_rxBufferMutex != NULL) {
|
||||
vSemaphoreDelete((SemaphoreHandle_t)_rxBufferMutex);
|
||||
_rxBufferMutex = NULL;
|
||||
}
|
||||
|
||||
if (_txBufferMutex != NULL) {
|
||||
vSemaphoreDelete((SemaphoreHandle_t)_txBufferMutex);
|
||||
_txBufferMutex = NULL;
|
||||
}
|
||||
|
||||
end();
|
||||
}
|
||||
|
||||
void Serial_2_Socket::begin(long speed) { end(); }
|
||||
|
||||
void Serial_2_Socket::enable(bool enable) { _started = enable; }
|
||||
@ -39,9 +67,23 @@ void Serial_2_Socket::enable(bool enable) { _started = enable; }
|
||||
void Serial_2_Socket::pause(bool state) {
|
||||
_paused = state;
|
||||
if (_paused) {
|
||||
_TXbufferSize = 0;
|
||||
_RXbufferSize = 0;
|
||||
_RXbufferpos = 0;
|
||||
// Protect TX buffer access with mutex
|
||||
if (_txBufferMutex != NULL && xSemaphoreTake((SemaphoreHandle_t)_txBufferMutex, pdMS_TO_TICKS(100)) == pdTRUE) {
|
||||
_TXbufferSize = 0;
|
||||
xSemaphoreGive((SemaphoreHandle_t)_txBufferMutex);
|
||||
} else {
|
||||
_TXbufferSize = 0;
|
||||
}
|
||||
|
||||
// Protect RX buffer access with mutex
|
||||
if (_rxBufferMutex != NULL && xSemaphoreTake((SemaphoreHandle_t)_rxBufferMutex, pdMS_TO_TICKS(100)) == pdTRUE) {
|
||||
_RXbufferSize = 0;
|
||||
_RXbufferpos = 0;
|
||||
xSemaphoreGive((SemaphoreHandle_t)_rxBufferMutex);
|
||||
} else {
|
||||
_RXbufferSize = 0;
|
||||
_RXbufferpos = 0;
|
||||
}
|
||||
} else {
|
||||
_lastflush = millis();
|
||||
}
|
||||
@ -50,9 +92,24 @@ void Serial_2_Socket::pause(bool state) {
|
||||
bool Serial_2_Socket::isPaused() { return _paused; }
|
||||
|
||||
void Serial_2_Socket::end() {
|
||||
_TXbufferSize = 0;
|
||||
_RXbufferSize = 0;
|
||||
_RXbufferpos = 0;
|
||||
// Protect TX buffer access with mutex
|
||||
if (_txBufferMutex != NULL && xSemaphoreTake((SemaphoreHandle_t)_txBufferMutex, pdMS_TO_TICKS(100)) == pdTRUE) {
|
||||
_TXbufferSize = 0;
|
||||
xSemaphoreGive((SemaphoreHandle_t)_txBufferMutex);
|
||||
} else {
|
||||
_TXbufferSize = 0;
|
||||
}
|
||||
|
||||
// Protect RX buffer access with mutex
|
||||
if (_rxBufferMutex != NULL && xSemaphoreTake((SemaphoreHandle_t)_rxBufferMutex, pdMS_TO_TICKS(100)) == pdTRUE) {
|
||||
_RXbufferSize = 0;
|
||||
_RXbufferpos = 0;
|
||||
xSemaphoreGive((SemaphoreHandle_t)_rxBufferMutex);
|
||||
} else {
|
||||
_RXbufferSize = 0;
|
||||
_RXbufferpos = 0;
|
||||
}
|
||||
|
||||
_started = false;
|
||||
_paused = false;
|
||||
_lastflush = millis();
|
||||
@ -70,16 +127,32 @@ bool Serial_2_Socket::started() { return _started; }
|
||||
Serial_2_Socket::operator bool() const { return true; }
|
||||
|
||||
int Serial_2_Socket::available() {
|
||||
if (_paused) {
|
||||
if (_paused || !_started) {
|
||||
return 0;
|
||||
}
|
||||
return _RXbufferSize;
|
||||
if (_RXbufferSize == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Protect RX buffer access with mutex
|
||||
if (_rxBufferMutex != NULL && xSemaphoreTake((SemaphoreHandle_t)_rxBufferMutex, pdMS_TO_TICKS(100)) != pdTRUE) {
|
||||
esp3d_log_e("Serial2Socket: Failed to take mutex for available");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int size = _RXbufferSize;
|
||||
|
||||
if (_rxBufferMutex != NULL) {
|
||||
xSemaphoreGive((SemaphoreHandle_t)_rxBufferMutex);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t Serial_2_Socket::write(uint8_t c) {
|
||||
if (!_started || _paused) {
|
||||
return 1;
|
||||
}
|
||||
esp3d_log_d("Serial2Socket: write one char %c", c);
|
||||
return write(&c, 1);
|
||||
}
|
||||
|
||||
@ -88,39 +161,81 @@ size_t Serial_2_Socket::write(const uint8_t *buffer, size_t size) {
|
||||
esp3d_log("Serial2Socket: no data, not started or paused");
|
||||
return size;
|
||||
}
|
||||
|
||||
// Take TX buffer mutex once for the entire function
|
||||
if (_txBufferMutex != NULL && xSemaphoreTake((SemaphoreHandle_t)_txBufferMutex, pdMS_TO_TICKS(100)) != pdTRUE) {
|
||||
esp3d_log_e("Serial2Socket: Failed to take mutex for write");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (_TXbufferSize == 0) {
|
||||
_lastflush = millis();
|
||||
}
|
||||
// send full line
|
||||
|
||||
// Check if buffer is full and needs flushing
|
||||
if (_TXbufferSize + size > S2S_TXBUFFERSIZE) {
|
||||
flush();
|
||||
esp3d_log_d("Serial2Socket: buffer full, flush it");
|
||||
flush(false); // Use flush without mutex since we already have it
|
||||
}
|
||||
// need periodic check to force to flush in case of no end
|
||||
|
||||
// Add data to buffer and flush on newline
|
||||
for (int i = 0; i < size; i++) {
|
||||
_TXbuffer[_TXbufferSize] = buffer[i];
|
||||
_TXbufferSize++;
|
||||
if (buffer[i] == (const uint8_t)'\n') {
|
||||
esp3d_log("S2S: %s TXSize: %d", (const char *)_TXbuffer, _TXbufferSize);
|
||||
flush();
|
||||
esp3d_log_d("S2S: %s TXSize: %d", (const char *)_TXbuffer, _TXbufferSize);
|
||||
flush(false); // Use flush without mutex since we already have it
|
||||
}
|
||||
}
|
||||
handle_flush();
|
||||
|
||||
// Check if we need to flush based on time
|
||||
if (_TXbufferSize > 0 && ((millis() - _lastflush) > S2S_FLUSHTIMEOUT)) {
|
||||
flush(false); // Use flush without mutex since we already have it
|
||||
}
|
||||
|
||||
// Release the mutex at the end
|
||||
if (_txBufferMutex != NULL) {
|
||||
xSemaphoreGive((SemaphoreHandle_t)_txBufferMutex);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int Serial_2_Socket::peek(void) {
|
||||
if (_RXbufferSize > 0 && _started) {
|
||||
return _RXbuffer[_RXbufferpos];
|
||||
} else {
|
||||
esp3d_log_d("Serial2Socket: peek first of %d", _RXbufferSize);
|
||||
if (_RXbufferSize <= 0 || !_started) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Protect RX buffer access with mutex
|
||||
if (_rxBufferMutex != NULL && xSemaphoreTake((SemaphoreHandle_t)_rxBufferMutex, pdMS_TO_TICKS(100)) != pdTRUE) {
|
||||
esp3d_log_e("Serial2Socket: Failed to take mutex for peek");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t v = _RXbuffer[_RXbufferpos];
|
||||
|
||||
if (_rxBufferMutex != NULL) {
|
||||
xSemaphoreGive((SemaphoreHandle_t)_rxBufferMutex);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
bool Serial_2_Socket::push(const uint8_t *buffer, size_t size) {
|
||||
// Send data to socket output buffer
|
||||
bool Serial_2_Socket::push2RX(const uint8_t *buffer, size_t size) {
|
||||
if (buffer == NULL || size == 0 || !_started || _paused) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Protect RX buffer access with mutex
|
||||
if (_rxBufferMutex != NULL && xSemaphoreTake((SemaphoreHandle_t)_rxBufferMutex, pdMS_TO_TICKS(100)) != pdTRUE) {
|
||||
esp3d_log_e("Serial2Socket: cannot take mutex for push2RX");
|
||||
return false;
|
||||
}
|
||||
|
||||
int data_size = size;
|
||||
bool success = false;
|
||||
esp3d_log_d("Serial2Socket: pushing %d chars to buffer", data_size);
|
||||
if ((data_size + _RXbufferSize) <= S2S_RXBUFFERSIZE) {
|
||||
int current = _RXbufferpos + _RXbufferSize;
|
||||
if (current > S2S_RXBUFFERSIZE) {
|
||||
@ -134,24 +249,41 @@ bool Serial_2_Socket::push(const uint8_t *buffer, size_t size) {
|
||||
current++;
|
||||
}
|
||||
_RXbufferSize += size;
|
||||
_RXbuffer[current] = 0;
|
||||
return true;
|
||||
if (current < S2S_RXBUFFERSIZE) {
|
||||
_RXbuffer[current] = 0;
|
||||
}
|
||||
success = true;
|
||||
}
|
||||
return false;
|
||||
|
||||
if (_rxBufferMutex != NULL) {
|
||||
xSemaphoreGive((SemaphoreHandle_t)_rxBufferMutex);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
int Serial_2_Socket::read(void) {
|
||||
if (_RXbufferSize > 0 && _started && !_paused) {
|
||||
int v = _RXbuffer[_RXbufferpos];
|
||||
_RXbufferpos++;
|
||||
if (_RXbufferpos > (S2S_RXBUFFERSIZE - 1)) {
|
||||
_RXbufferpos = 0;
|
||||
}
|
||||
_RXbufferSize--;
|
||||
return v;
|
||||
} else {
|
||||
if (_RXbufferSize <= 0 || !_started || _paused) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Protect RX buffer access with mutex
|
||||
if (_rxBufferMutex != NULL && xSemaphoreTake((SemaphoreHandle_t)_rxBufferMutex, pdMS_TO_TICKS(100)) != pdTRUE) {
|
||||
esp3d_log_e("Serial2Socket: Failed to take mutex for read");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t v = _RXbuffer[_RXbufferpos];
|
||||
_RXbufferpos++;
|
||||
if (_RXbufferpos > (S2S_RXBUFFERSIZE - 1)) {
|
||||
_RXbufferpos = 0;
|
||||
}
|
||||
_RXbufferSize--;
|
||||
esp3d_log_d("Serial2Socket: read one char %c", v);
|
||||
|
||||
if (_rxBufferMutex != NULL) {
|
||||
xSemaphoreGive((SemaphoreHandle_t)_rxBufferMutex);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
void Serial_2_Socket::handle() { handle_flush(); }
|
||||
@ -161,16 +293,35 @@ void Serial_2_Socket::handle_flush() {
|
||||
if ((_TXbufferSize >= S2S_TXBUFFERSIZE) ||
|
||||
((millis() - _lastflush) > S2S_FLUSHTIMEOUT)) {
|
||||
esp3d_log("force socket flush");
|
||||
flush();
|
||||
flush(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
void Serial_2_Socket::flush(void) {
|
||||
|
||||
void Serial_2_Socket::flush(bool useMutex) {
|
||||
|
||||
// Process buffer if there's data and we're not paused
|
||||
if (_TXbufferSize > 0 && _started && !_paused) {
|
||||
// Protect TX buffer access with mutex if requested
|
||||
if (useMutex && _txBufferMutex != NULL) {
|
||||
if (xSemaphoreTake((SemaphoreHandle_t)_txBufferMutex, pdMS_TO_TICKS(100)) != pdTRUE) {
|
||||
esp3d_log_e("Serial2Socket: Failed to take mutex for flush");
|
||||
return;
|
||||
}
|
||||
}
|
||||
ESP3DMessage *msg = esp3d_message_manager.newMsg(
|
||||
ESP3DClientType::socket_serial, ESP3DClientType::all_clients, _TXbuffer,
|
||||
_TXbufferSize, _auth);
|
||||
// dispatch command
|
||||
|
||||
// Reset buffer before processing
|
||||
_lastflush = millis();
|
||||
_TXbufferSize = 0;
|
||||
|
||||
// Release mutex if we took it
|
||||
if (useMutex && _txBufferMutex != NULL) {
|
||||
xSemaphoreGive((SemaphoreHandle_t)_txBufferMutex);
|
||||
}
|
||||
|
||||
if (msg) {
|
||||
// process command
|
||||
msg->type = ESP3DMessageType::unique;
|
||||
@ -178,10 +329,6 @@ void Serial_2_Socket::flush(void) {
|
||||
} else {
|
||||
esp3d_log_e("Cannot create message");
|
||||
}
|
||||
// refresh timout
|
||||
_lastflush = millis();
|
||||
// reset buffer
|
||||
_TXbufferSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,7 +338,8 @@ bool Serial_2_Socket::dispatch(ESP3DMessage *message) {
|
||||
return false;
|
||||
}
|
||||
if (message->size > 0 && message->data) {
|
||||
if (!push(message->data, message->size)) {
|
||||
esp3d_log_d("Serial2Socket: dispatch message %d", message->size);
|
||||
if (!push2RX(message->data, message->size)) {
|
||||
esp3d_log_e("Serial2Socket: cannot push all data");
|
||||
return false;
|
||||
}
|
||||
|
@ -24,8 +24,8 @@
|
||||
#include <Print.h>
|
||||
|
||||
#include "../authentication/authentication_level_types.h"
|
||||
#define S2S_TXBUFFERSIZE 1200
|
||||
#define S2S_RXBUFFERSIZE 128
|
||||
#define S2S_TXBUFFERSIZE 512
|
||||
#define S2S_RXBUFFERSIZE 256
|
||||
#define S2S_FLUSHTIMEOUT 500
|
||||
|
||||
class ESP3DMessage; // forward declaration
|
||||
@ -51,8 +51,8 @@ class Serial_2_Socket : public Stream {
|
||||
int available();
|
||||
int peek(void);
|
||||
int read(void);
|
||||
bool push(const uint8_t *buffer, size_t size);
|
||||
void flush(void);
|
||||
bool push2RX(const uint8_t *buffer, size_t size);
|
||||
void flush(bool useMutex = true);
|
||||
void handle_flush();
|
||||
void handle();
|
||||
operator bool() const;
|
||||
@ -63,10 +63,12 @@ class Serial_2_Socket : public Stream {
|
||||
bool _started;
|
||||
bool _paused;
|
||||
ESP3DAuthenticationLevel _auth;
|
||||
void* _rxBufferMutex; // Opaque pointer for RX buffer mutex
|
||||
void* _txBufferMutex; // Opaque pointer for TX buffer mutex
|
||||
uint32_t _lastflush;
|
||||
uint8_t _TXbuffer[S2S_TXBUFFERSIZE];
|
||||
uint8_t _TXbuffer[S2S_TXBUFFERSIZE+1];
|
||||
uint16_t _TXbufferSize;
|
||||
uint8_t _RXbuffer[S2S_RXBUFFERSIZE];
|
||||
uint8_t _RXbuffer[S2S_RXBUFFERSIZE+1];
|
||||
uint16_t _RXbufferSize;
|
||||
uint16_t _RXbufferpos;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user