mirror of
https://git.mirrors.martin98.com/https://github.com/luc-github/ESP3D.git
synced 2025-07-31 21:51:59 +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
|
#define _VERSION_ESP3D_H
|
||||||
|
|
||||||
// version and sources location
|
// 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"
|
#define REPOSITORY "https://github.com/luc-github/ESP3D/tree/3.0"
|
||||||
|
|
||||||
#endif //_VERSION_ESP3D_H
|
#endif //_VERSION_ESP3D_H
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
|
|
||||||
#if defined(ESP3DLIB_ENV) && COMMUNICATION_PROTOCOL == SOCKET_SERIAL
|
#if defined(ESP3DLIB_ENV) && COMMUNICATION_PROTOCOL == SOCKET_SERIAL
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/semphr.h"
|
||||||
|
|
||||||
#include "../../core/esp3d_commands.h"
|
#include "../../core/esp3d_commands.h"
|
||||||
#include "../../core/esp3d_message.h"
|
#include "../../core/esp3d_message.h"
|
||||||
@ -30,8 +32,34 @@
|
|||||||
|
|
||||||
Serial_2_Socket Serial2Socket;
|
Serial_2_Socket Serial2Socket;
|
||||||
|
|
||||||
Serial_2_Socket::Serial_2_Socket() { end(); }
|
Serial_2_Socket::Serial_2_Socket() {
|
||||||
Serial_2_Socket::~Serial_2_Socket() { end(); }
|
_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::begin(long speed) { end(); }
|
||||||
|
|
||||||
void Serial_2_Socket::enable(bool enable) { _started = enable; }
|
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) {
|
void Serial_2_Socket::pause(bool state) {
|
||||||
_paused = state;
|
_paused = state;
|
||||||
if (_paused) {
|
if (_paused) {
|
||||||
_TXbufferSize = 0;
|
// Protect TX buffer access with mutex
|
||||||
_RXbufferSize = 0;
|
if (_txBufferMutex != NULL && xSemaphoreTake((SemaphoreHandle_t)_txBufferMutex, pdMS_TO_TICKS(100)) == pdTRUE) {
|
||||||
_RXbufferpos = 0;
|
_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 {
|
} else {
|
||||||
_lastflush = millis();
|
_lastflush = millis();
|
||||||
}
|
}
|
||||||
@ -50,9 +92,24 @@ void Serial_2_Socket::pause(bool state) {
|
|||||||
bool Serial_2_Socket::isPaused() { return _paused; }
|
bool Serial_2_Socket::isPaused() { return _paused; }
|
||||||
|
|
||||||
void Serial_2_Socket::end() {
|
void Serial_2_Socket::end() {
|
||||||
_TXbufferSize = 0;
|
// Protect TX buffer access with mutex
|
||||||
_RXbufferSize = 0;
|
if (_txBufferMutex != NULL && xSemaphoreTake((SemaphoreHandle_t)_txBufferMutex, pdMS_TO_TICKS(100)) == pdTRUE) {
|
||||||
_RXbufferpos = 0;
|
_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;
|
_started = false;
|
||||||
_paused = false;
|
_paused = false;
|
||||||
_lastflush = millis();
|
_lastflush = millis();
|
||||||
@ -70,16 +127,32 @@ bool Serial_2_Socket::started() { return _started; }
|
|||||||
Serial_2_Socket::operator bool() const { return true; }
|
Serial_2_Socket::operator bool() const { return true; }
|
||||||
|
|
||||||
int Serial_2_Socket::available() {
|
int Serial_2_Socket::available() {
|
||||||
if (_paused) {
|
if (_paused || !_started) {
|
||||||
return 0;
|
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) {
|
size_t Serial_2_Socket::write(uint8_t c) {
|
||||||
if (!_started || _paused) {
|
if (!_started || _paused) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
esp3d_log_d("Serial2Socket: write one char %c", c);
|
||||||
return write(&c, 1);
|
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");
|
esp3d_log("Serial2Socket: no data, not started or paused");
|
||||||
return size;
|
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) {
|
if (_TXbufferSize == 0) {
|
||||||
_lastflush = millis();
|
_lastflush = millis();
|
||||||
}
|
}
|
||||||
// send full line
|
|
||||||
|
// Check if buffer is full and needs flushing
|
||||||
if (_TXbufferSize + size > S2S_TXBUFFERSIZE) {
|
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++) {
|
for (int i = 0; i < size; i++) {
|
||||||
_TXbuffer[_TXbufferSize] = buffer[i];
|
_TXbuffer[_TXbufferSize] = buffer[i];
|
||||||
_TXbufferSize++;
|
_TXbufferSize++;
|
||||||
if (buffer[i] == (const uint8_t)'\n') {
|
if (buffer[i] == (const uint8_t)'\n') {
|
||||||
esp3d_log("S2S: %s TXSize: %d", (const char *)_TXbuffer, _TXbufferSize);
|
esp3d_log_d("S2S: %s TXSize: %d", (const char *)_TXbuffer, _TXbufferSize);
|
||||||
flush();
|
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;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Serial_2_Socket::peek(void) {
|
int Serial_2_Socket::peek(void) {
|
||||||
if (_RXbufferSize > 0 && _started) {
|
esp3d_log_d("Serial2Socket: peek first of %d", _RXbufferSize);
|
||||||
return _RXbuffer[_RXbufferpos];
|
if (_RXbufferSize <= 0 || !_started) {
|
||||||
} else {
|
|
||||||
return -1;
|
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) {
|
if (buffer == NULL || size == 0 || !_started || _paused) {
|
||||||
return false;
|
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;
|
int data_size = size;
|
||||||
|
bool success = false;
|
||||||
|
esp3d_log_d("Serial2Socket: pushing %d chars to buffer", data_size);
|
||||||
if ((data_size + _RXbufferSize) <= S2S_RXBUFFERSIZE) {
|
if ((data_size + _RXbufferSize) <= S2S_RXBUFFERSIZE) {
|
||||||
int current = _RXbufferpos + _RXbufferSize;
|
int current = _RXbufferpos + _RXbufferSize;
|
||||||
if (current > S2S_RXBUFFERSIZE) {
|
if (current > S2S_RXBUFFERSIZE) {
|
||||||
@ -134,24 +249,41 @@ bool Serial_2_Socket::push(const uint8_t *buffer, size_t size) {
|
|||||||
current++;
|
current++;
|
||||||
}
|
}
|
||||||
_RXbufferSize += size;
|
_RXbufferSize += size;
|
||||||
_RXbuffer[current] = 0;
|
if (current < S2S_RXBUFFERSIZE) {
|
||||||
return true;
|
_RXbuffer[current] = 0;
|
||||||
|
}
|
||||||
|
success = true;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
if (_rxBufferMutex != NULL) {
|
||||||
|
xSemaphoreGive((SemaphoreHandle_t)_rxBufferMutex);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Serial_2_Socket::read(void) {
|
int Serial_2_Socket::read(void) {
|
||||||
if (_RXbufferSize > 0 && _started && !_paused) {
|
if (_RXbufferSize <= 0 || !_started || _paused) {
|
||||||
int v = _RXbuffer[_RXbufferpos];
|
|
||||||
_RXbufferpos++;
|
|
||||||
if (_RXbufferpos > (S2S_RXBUFFERSIZE - 1)) {
|
|
||||||
_RXbufferpos = 0;
|
|
||||||
}
|
|
||||||
_RXbufferSize--;
|
|
||||||
return v;
|
|
||||||
} else {
|
|
||||||
return -1;
|
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(); }
|
void Serial_2_Socket::handle() { handle_flush(); }
|
||||||
@ -161,16 +293,35 @@ void Serial_2_Socket::handle_flush() {
|
|||||||
if ((_TXbufferSize >= S2S_TXBUFFERSIZE) ||
|
if ((_TXbufferSize >= S2S_TXBUFFERSIZE) ||
|
||||||
((millis() - _lastflush) > S2S_FLUSHTIMEOUT)) {
|
((millis() - _lastflush) > S2S_FLUSHTIMEOUT)) {
|
||||||
esp3d_log("force socket flush");
|
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) {
|
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(
|
ESP3DMessage *msg = esp3d_message_manager.newMsg(
|
||||||
ESP3DClientType::socket_serial, ESP3DClientType::all_clients, _TXbuffer,
|
ESP3DClientType::socket_serial, ESP3DClientType::all_clients, _TXbuffer,
|
||||||
_TXbufferSize, _auth);
|
_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) {
|
if (msg) {
|
||||||
// process command
|
// process command
|
||||||
msg->type = ESP3DMessageType::unique;
|
msg->type = ESP3DMessageType::unique;
|
||||||
@ -178,10 +329,6 @@ void Serial_2_Socket::flush(void) {
|
|||||||
} else {
|
} else {
|
||||||
esp3d_log_e("Cannot create message");
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
if (message->size > 0 && message->data) {
|
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");
|
esp3d_log_e("Serial2Socket: cannot push all data");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,8 @@
|
|||||||
#include <Print.h>
|
#include <Print.h>
|
||||||
|
|
||||||
#include "../authentication/authentication_level_types.h"
|
#include "../authentication/authentication_level_types.h"
|
||||||
#define S2S_TXBUFFERSIZE 1200
|
#define S2S_TXBUFFERSIZE 512
|
||||||
#define S2S_RXBUFFERSIZE 128
|
#define S2S_RXBUFFERSIZE 256
|
||||||
#define S2S_FLUSHTIMEOUT 500
|
#define S2S_FLUSHTIMEOUT 500
|
||||||
|
|
||||||
class ESP3DMessage; // forward declaration
|
class ESP3DMessage; // forward declaration
|
||||||
@ -51,8 +51,8 @@ class Serial_2_Socket : public Stream {
|
|||||||
int available();
|
int available();
|
||||||
int peek(void);
|
int peek(void);
|
||||||
int read(void);
|
int read(void);
|
||||||
bool push(const uint8_t *buffer, size_t size);
|
bool push2RX(const uint8_t *buffer, size_t size);
|
||||||
void flush(void);
|
void flush(bool useMutex = true);
|
||||||
void handle_flush();
|
void handle_flush();
|
||||||
void handle();
|
void handle();
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
@ -63,10 +63,12 @@ class Serial_2_Socket : public Stream {
|
|||||||
bool _started;
|
bool _started;
|
||||||
bool _paused;
|
bool _paused;
|
||||||
ESP3DAuthenticationLevel _auth;
|
ESP3DAuthenticationLevel _auth;
|
||||||
|
void* _rxBufferMutex; // Opaque pointer for RX buffer mutex
|
||||||
|
void* _txBufferMutex; // Opaque pointer for TX buffer mutex
|
||||||
uint32_t _lastflush;
|
uint32_t _lastflush;
|
||||||
uint8_t _TXbuffer[S2S_TXBUFFERSIZE];
|
uint8_t _TXbuffer[S2S_TXBUFFERSIZE+1];
|
||||||
uint16_t _TXbufferSize;
|
uint16_t _TXbufferSize;
|
||||||
uint8_t _RXbuffer[S2S_RXBUFFERSIZE];
|
uint8_t _RXbuffer[S2S_RXBUFFERSIZE+1];
|
||||||
uint16_t _RXbufferSize;
|
uint16_t _RXbufferSize;
|
||||||
uint16_t _RXbufferpos;
|
uint16_t _RXbufferpos;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user