arduino Serial is not thread safe
This commit is contained in:
parent
13c71164e8
commit
6cc093fea2
4 changed files with 53 additions and 71 deletions
|
@ -53,12 +53,6 @@
|
||||||
|
|
||||||
constexpr const char SERIAL_CFG_FILE[] = "/serial.json";
|
constexpr const char SERIAL_CFG_FILE[] = "/serial.json";
|
||||||
|
|
||||||
#if defined(BUILD_FOR_RP2040)
|
|
||||||
#define Serial_RS232 Serial1
|
|
||||||
#elif defined(TTY_SERIAL_RX)
|
|
||||||
HardwareSerial Serial_RS232(2);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bus *b = nullptr;
|
bus *b = nullptr;
|
||||||
cpu *c = nullptr;
|
cpu *c = nullptr;
|
||||||
tty *tty_ = nullptr;
|
tty *tty_ = nullptr;
|
||||||
|
@ -78,7 +72,7 @@ bool trace_output { false };
|
||||||
|
|
||||||
ntp *ntp_ { nullptr };
|
ntp *ntp_ { nullptr };
|
||||||
|
|
||||||
void console_thread_wrapper_panel(void *const c)
|
static void console_thread_wrapper_panel(void *const c)
|
||||||
{
|
{
|
||||||
console *const cnsl = reinterpret_cast<console *>(c);
|
console *const cnsl = reinterpret_cast<console *>(c);
|
||||||
|
|
||||||
|
@ -213,17 +207,12 @@ void start_network(console *const c)
|
||||||
dc11 *dc11_ = new dc11(1100, b);
|
dc11 *dc11_ = new dc11(1100, b);
|
||||||
|
|
||||||
#if !defined(BUILD_FOR_RP2040) && defined(TTY_SERIAL_RX)
|
#if !defined(BUILD_FOR_RP2040) && defined(TTY_SERIAL_RX)
|
||||||
constexpr uint32_t hwSerialConfig = SERIAL_8N1;
|
|
||||||
uint32_t bitrate = load_serial_speed_configuration();
|
uint32_t bitrate = load_serial_speed_configuration();
|
||||||
|
|
||||||
Serial.printf("* Init TTY (on DC11), baudrate: %d bps, RX: %d, TX: %d", bitrate, TTY_SERIAL_RX, TTY_SERIAL_TX);
|
Serial.printf("* Init TTY (on DC11), baudrate: %d bps, RX: %d, TX: %d", bitrate, TTY_SERIAL_RX, TTY_SERIAL_TX);
|
||||||
Serial.println(F(""));
|
Serial.println(F(""));
|
||||||
|
|
||||||
Serial_RS232.begin(bitrate, hwSerialConfig, TTY_SERIAL_RX, TTY_SERIAL_TX);
|
dc11_->set_serial(bitrate, TTY_SERIAL_RX, TTY_SERIAL_TX);
|
||||||
Serial_RS232.setHwFlowCtrlMode(0);
|
|
||||||
Serial_RS232.println(F("Go!"));
|
|
||||||
|
|
||||||
dc11_->set_serial(&Serial_RS232);
|
|
||||||
#endif
|
#endif
|
||||||
b->add_DC11(dc11_);
|
b->add_DC11(dc11_);
|
||||||
|
|
||||||
|
@ -244,16 +233,6 @@ void recall_configuration(console *const cnsl)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(TTY_SERIAL_RX)
|
|
||||||
void set_tty_serial_speed(console *const c, const uint32_t bps)
|
|
||||||
{
|
|
||||||
Serial_RS232.begin(bps);
|
|
||||||
|
|
||||||
if (save_serial_speed_configuration(bps) == false)
|
|
||||||
c->put_string_lf("Failed to store configuration file with serial settings");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ESP32)
|
#if defined(ESP32)
|
||||||
void heap_caps_alloc_failed_hook(size_t requested_size, uint32_t caps, const char *function_name)
|
void heap_caps_alloc_failed_hook(size_t requested_size, uint32_t caps, const char *function_name)
|
||||||
{
|
{
|
||||||
|
|
69
dc11.cpp
69
dc11.cpp
|
@ -8,6 +8,7 @@
|
||||||
#include <lwip/sockets.h>
|
#include <lwip/sockets.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <driver/uart.h>
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
|
@ -26,6 +27,8 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define ESP32_UART UART_NUM_1
|
||||||
|
|
||||||
const char *const dc11_register_names[] { "RCSR", "RBUF", "TSCR", "TBUF" };
|
const char *const dc11_register_names[] { "RCSR", "RBUF", "TSCR", "TBUF" };
|
||||||
|
|
||||||
bool setup_telnet_session(const int fd)
|
bool setup_telnet_session(const int fd)
|
||||||
|
@ -89,10 +92,7 @@ dc11::~dc11()
|
||||||
delete [] pfds;
|
delete [] pfds;
|
||||||
|
|
||||||
#if defined(ESP32)
|
#if defined(ESP32)
|
||||||
if (serial_th) {
|
// won't work due to freertos thread
|
||||||
serial_th->join();
|
|
||||||
delete serial_th;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,18 +241,47 @@ void dc11::operator()()
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(ESP32)
|
#if defined(ESP32)
|
||||||
void dc11::set_serial(Stream *const s)
|
void dc11_thread_wrapper_serial_handler(void *const c)
|
||||||
{
|
{
|
||||||
if (serial_th) {
|
dc11 *const d = reinterpret_cast<dc11 *>(c);
|
||||||
|
|
||||||
|
d->serial_handler();
|
||||||
|
|
||||||
|
vTaskSuspend(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dc11::set_serial(const int bitrate, const int rx, const int tx)
|
||||||
|
{
|
||||||
|
if (serial_thread_running) {
|
||||||
DOLOG(info, true, "DC11: serial port already configured");
|
DOLOG(info, true, "DC11: serial port already configured");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lck(s_lock);
|
serial_thread_running = true;
|
||||||
this->s = s;
|
|
||||||
s->write("Press enter to connect");
|
|
||||||
|
|
||||||
serial_th = new std::thread(&dc11::serial_handler, this);
|
// Configure UART parameters
|
||||||
|
static uart_config_t uart_config = {
|
||||||
|
.baud_rate = bitrate,
|
||||||
|
.data_bits = UART_DATA_8_BITS,
|
||||||
|
.parity = UART_PARITY_DISABLE,
|
||||||
|
.stop_bits = UART_STOP_BITS_1,
|
||||||
|
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||||
|
.rx_flow_ctrl_thresh = 122,
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(uart_param_config(ESP32_UART, &uart_config));
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(uart_set_pin(ESP32_UART, tx, rx, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||||
|
|
||||||
|
// Setup UART buffered IO with event queue
|
||||||
|
const int uart_buffer_size = 1024 * 2;
|
||||||
|
static QueueHandle_t uart_queue;
|
||||||
|
// Install UART driver using an event queue here
|
||||||
|
ESP_ERROR_CHECK(uart_driver_install(ESP32_UART, uart_buffer_size, uart_buffer_size, 10, &uart_queue, 0));
|
||||||
|
|
||||||
|
const char msg[] = "Press enter to connect\r\n";
|
||||||
|
uart_write_bytes(ESP32_UART, msg, sizeof(msg) - 1);
|
||||||
|
|
||||||
|
xTaskCreate(&dc11_thread_wrapper_serial_handler, "dc11_tty", 3072, this, 1, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dc11::serial_handler()
|
void dc11::serial_handler()
|
||||||
|
@ -260,15 +289,14 @@ void dc11::serial_handler()
|
||||||
while(!stop_flag) {
|
while(!stop_flag) {
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
char c = 0;
|
size_t n_available = 0;
|
||||||
|
ESP_ERROR_CHECK(uart_get_buffered_data_len(ESP32_UART, &n_available));
|
||||||
{
|
if (n_available == 0)
|
||||||
std::unique_lock<std::mutex> lck(s_lock);
|
|
||||||
if (s->available() == 0)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
c = s->read();
|
char c = 0;
|
||||||
}
|
if (uart_read_bytes(ESP32_UART, &c, 1, 100) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
// 3 is reserved for a serial port
|
// 3 is reserved for a serial port
|
||||||
constexpr const int serial_line = 3;
|
constexpr const int serial_line = 3;
|
||||||
|
@ -416,11 +444,8 @@ void dc11::write_word(const uint16_t addr, const uint16_t v)
|
||||||
|
|
||||||
#if defined(ESP32)
|
#if defined(ESP32)
|
||||||
if (line_nr == 3) {
|
if (line_nr == 3) {
|
||||||
if (s != nullptr) {
|
if (serial_thread_running)
|
||||||
std::unique_lock<std::mutex> lck(s_lock);
|
uart_write_bytes(ESP32_UART, &c, 1);
|
||||||
|
|
||||||
s->write(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_tx_interrupt_enabled(line_nr))
|
if (is_tx_interrupt_enabled(line_nr))
|
||||||
trigger_interrupt(line_nr, true);
|
trigger_interrupt(line_nr, true);
|
||||||
|
|
6
dc11.h
6
dc11.h
|
@ -49,9 +49,7 @@ private:
|
||||||
std::vector<char> recv_buffers[dc11_n_lines];
|
std::vector<char> recv_buffers[dc11_n_lines];
|
||||||
std::mutex input_lock[dc11_n_lines];
|
std::mutex input_lock[dc11_n_lines];
|
||||||
#if defined(ESP32)
|
#if defined(ESP32)
|
||||||
std::mutex s_lock;
|
std::atomic_bool serial_thread_running { false };
|
||||||
Stream *s { nullptr };
|
|
||||||
std::thread *serial_th { nullptr };
|
|
||||||
bool serial_enabled { false };
|
bool serial_enabled { false };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -70,7 +68,7 @@ public:
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
#if defined(ESP32)
|
#if defined(ESP32)
|
||||||
void set_serial(Stream *const s);
|
void set_serial(const int bitrate, const int rx, const int tx);
|
||||||
void serial_handler();
|
void serial_handler();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
20
debugger.cpp
20
debugger.cpp
|
@ -43,8 +43,6 @@
|
||||||
void configure_network(console *const cnsl);
|
void configure_network(console *const cnsl);
|
||||||
void check_network(console *const cnsl);
|
void check_network(console *const cnsl);
|
||||||
void start_network(console *const cnsl);
|
void start_network(console *const cnsl);
|
||||||
|
|
||||||
void set_tty_serial_speed(console *const c, const uint32_t bps);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(BUILD_FOR_RP2040) && !defined(linux) && !defined(_WIN32)
|
#if !defined(BUILD_FOR_RP2040) && !defined(linux) && !defined(_WIN32)
|
||||||
|
@ -891,21 +889,6 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#if defined(CONSOLE_SERIAL_RX)
|
|
||||||
else if (parts.at(0) == "serspd") {
|
|
||||||
if (parts.size() == 2) {
|
|
||||||
uint32_t speed = std::stoi(parts.at(1), nullptr, 10);
|
|
||||||
set_tty_serial_speed(cnsl, speed);
|
|
||||||
|
|
||||||
cnsl->put_string_lf(format("Set baudrate to %d", speed));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cnsl->put_string_lf("serspd requires an (decimal) parameter");
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
else if (cmd == "stats") {
|
else if (cmd == "stats") {
|
||||||
show_run_statistics(cnsl, c);
|
show_run_statistics(cnsl, c);
|
||||||
|
@ -1112,9 +1095,6 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto
|
||||||
"cfgnet - configure network (e.g. WiFi)",
|
"cfgnet - configure network (e.g. WiFi)",
|
||||||
"startnet - start network",
|
"startnet - start network",
|
||||||
"chknet - check network status",
|
"chknet - check network status",
|
||||||
#if defined(CONSOLE_SERIAL_RX)
|
|
||||||
"serspd x - set serial speed in bps (8N1 are default)",
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
"cfgdisk - configure disk",
|
"cfgdisk - configure disk",
|
||||||
"log ... - log a message to the logfile",
|
"log ... - log a message to the logfile",
|
||||||
|
|
Loading…
Add table
Reference in a new issue