Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Host fixes (RTC clock setting, UART restrictions, thread race condition) #2477

Merged
merged 5 commits into from
Feb 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Sming/Arch/Host/Components/driver/component.mk
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ ENABLE_HOST_UARTID ?=
# Options to add when running emulator
CACHE_VARS += HOST_UART_OPTIONS
HOST_UART_OPTIONS ?= $(addprefix --uart=,$(ENABLE_HOST_UARTID))
CLI_TARGET_OPTIONS += $(HOST_UART_OPTIONS)
override CLI_TARGET_OPTIONS += $(HOST_UART_OPTIONS)

# $1 -> Uart ID
define RunHostTerminal
Expand Down
55 changes: 13 additions & 42 deletions Sming/Arch/Host/Components/driver/uart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,10 @@ smg_uart_t* smg_uart_init_ex(const smg_uart_config_t& cfg)
return nullptr;
}

if(cfg.uart_nr >= UART_COUNT) {
return nullptr;
}

auto uart = new smg_uart_t;
if(uart == nullptr) {
return nullptr;
Expand All @@ -377,53 +381,20 @@ smg_uart_t* smg_uart_init_ex(const smg_uart_config_t& cfg)
rxBufferSize += UART_RX_FIFO_SIZE;
txBufferSize += UART_TX_FIFO_SIZE;

switch(cfg.uart_nr) {
case UART0:
case UART2:
if(smg_uart_rx_enabled(uart) && !realloc_buffer(uart->rx_buffer, rxBufferSize)) {
delete uart;
return nullptr;
}

if(smg_uart_tx_enabled(uart) && !realloc_buffer(uart->tx_buffer, txBufferSize)) {
delete uart->rx_buffer;
delete uart;
return nullptr;
}

if(cfg.uart_nr == UART2) {
break;
}

// OK, buffers allocated so setup hardware
smg_uart_detach(cfg.uart_nr);

break;

case UART1:
// Note: uart_interrupt_handler does not support RX on UART 1
if(uart->mode == UART_RX_ONLY) {
delete uart;
return nullptr;
}
uart->mode = UART_TX_ONLY;

// Transmit buffer optional
if(!realloc_buffer(uart->tx_buffer, txBufferSize)) {
delete uart;
return nullptr;
}

// Setup hardware
smg_uart_detach(cfg.uart_nr);
break;
if(smg_uart_rx_enabled(uart) && !realloc_buffer(uart->rx_buffer, rxBufferSize)) {
delete uart;
return nullptr;
}

default:
// big fail!
if(smg_uart_tx_enabled(uart) && !realloc_buffer(uart->tx_buffer, txBufferSize)) {
delete uart->rx_buffer;
delete uart;
return nullptr;
}

// OK, buffers allocated so setup hardware
smg_uart_detach(cfg.uart_nr);

smg_uart_set_baudrate(uart, cfg.baudrate);
smg_uart_flush(uart);
uartInstances[cfg.uart_nr] = uart;
Expand Down
7 changes: 5 additions & 2 deletions Sming/Arch/Host/Components/driver/uart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ Introduction
Implements a UART driver to connect via TCP socket, allowing terminal emulation using telnet,
or directly to local host serial device (e.g. /dev/ttyUSB0, COM4, etc.)

By default, output to UART0 is sent to the console and keyboard input is written to the UART0 receive queue.
If emulation is enabled on any ports then this behaviour is disabled.
If not otherwise reassigned, UART0 output is sent to the console and keyboard input is written to the UART0 receive queue.


Build variables
Expand Down Expand Up @@ -101,3 +100,7 @@ For Windows, substitute the appropriate device name, e.g. ``COM4`` instead of ``
.. note::

If necessary, add ``ENABLE_HOST_UARTID=`` to prevent telnet windows from being created.

Console I/O may be assigned to a different port like this::

make run HOST_UART_OPTIONS="--uart=1 --device=console"
33 changes: 23 additions & 10 deletions Sming/Arch/Host/Components/driver/uart_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ namespace
{
unsigned portBase{10000};
std::unique_ptr<CUart> servers[UART_COUNT];
} // namespace

class KeyboardThread : public CThread
{
Expand Down Expand Up @@ -93,9 +92,9 @@ void* KeyboardThread::thread_routine()
return nullptr;
}

static KeyboardThread* keyboardThread;
KeyboardThread* keyboardThread;

static void destroyKeyboardThread()
void destroyKeyboardThread()
{
if(keyboardThread == nullptr) {
return;
Expand All @@ -106,7 +105,7 @@ static void destroyKeyboardThread()
keyboardThread = nullptr;
}

static void onUart0Notify(smg_uart_t* uart, smg_uart_notify_code_t code)
void uartConsoleNotify(smg_uart_t* uart, smg_uart_notify_code_t code)
{
switch(code) {
case UART_NOTIFY_AFTER_WRITE: {
Expand Down Expand Up @@ -135,6 +134,8 @@ static void onUart0Notify(smg_uart_t* uart, smg_uart_notify_code_t code)
}
}

} // namespace

void startup(const Config& config)
{
if(config.portBase != 0) {
Expand All @@ -143,31 +144,43 @@ void startup(const Config& config)

auto notify = [](smg_uart_t* uart, smg_uart_notify_code_t code) {
auto& server = servers[uart->uart_nr];
if(server) {
if(server != nullptr) {
server->onNotify(uart, code);
} else if(code == UART_NOTIFY_AFTER_WRITE) {
uart->tx_buffer->clear();
}
};

bool consoleAssigned{false};
for(unsigned i = 0; i < UART_COUNT; ++i) {
smg_uart_set_notify(i, notify);
if(!bitRead(config.enableMask, i)) {
continue;
}
auto devname = config.deviceNames[i];
if(devname != nullptr && strcmp(devname, "console") == 0) {
if(consoleAssigned) {
host_debug_e("Console may not be assigned to multiple ports");
exit(1);
}
smg_uart_set_notify(i, uartConsoleNotify);
consoleAssigned = true;
continue;
}

auto& server = servers[i];
if(config.deviceNames[i] == nullptr) {
if(devname == nullptr) {
server.reset(new CUartPort(i));
} else {
server.reset(new CUartDevice(i, config.deviceNames[i], config.baud[i]));
server.reset(new CUartDevice(i, devname, config.baud[i]));
}
server->execute();
}

// If no ports have been enabled then redirect port 0 output to host console
if(config.enableMask == 0) {
// Redirect port 0 to console if not otherwise enabled
if(!bitRead(config.enableMask, 0) && !consoleAssigned) {
// Redirect the main serial port to console output
smg_uart_set_notify(UART0, onUart0Notify);
smg_uart_set_notify(UART0, uartConsoleNotify);
}
}

Expand Down
2 changes: 1 addition & 1 deletion Sming/Arch/Host/Components/esp_wifi/component.mk
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ COMPONENT_DEPENDS := lwip
# Options to add for configuring host network behaviour
CACHE_VARS += HOST_NETWORK_OPTIONS
HOST_NETWORK_OPTIONS ?=
CLI_TARGET_OPTIONS += $(HOST_NETWORK_OPTIONS)
override CLI_TARGET_OPTIONS += $(HOST_NETWORK_OPTIONS)

App-build: esp-wifi-check

Expand Down
6 changes: 4 additions & 2 deletions Sming/Arch/Host/Components/hostlib/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@
XX(help, no_argument, "Show help", nullptr, nullptr, nullptr) \
XX(uart, required_argument, "Enable UART server", "PORT", "Which UART number to enable", \
"e.g. --uart=0 --uart=1 enable servers for UART0, UART1\0") \
XX(device, required_argument, "Set device for uart", "DEVICE", "Optionally map uart to device", \
"e.g. --uart=0 --device=/dev/ttyUSB0\0") \
XX(device, required_argument, "Set device for uart", "DEVICE", \
"Optionally map uart to device. Use `console` to change printf target.", \
"e.g. --uart=0 --device=/dev/ttyUSB0\0" \
" --uart=1 --device=console\0") \
XX(baud, required_argument, "Set baud rate for UART", "BAUD", "Requires --device argument", \
"e.g. --uart=0 --device=/dev/ttyUSB0 --baud=115200\0") \
XX(portbase, required_argument, "Specify base port number for UART socket servers", "PORT", "IP port number", \
Expand Down
15 changes: 10 additions & 5 deletions Sming/Arch/Host/Components/hostlib/threads.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,13 +223,18 @@ void CThread::interrupt_begin()
assert(interrupt_level > interrupt_mask);

// Are we suspended by another thread?
suspendMutex.lock();
interrupt->lock();
while(suspended != 0) {
suspendMutex.wait(resumeCond);
}
suspendMutex.unlock();
interrupt->unlock();

interrupt->lock();
suspendMutex.lock();
while(suspended != 0) {
suspendMutex.wait(resumeCond);
}
suspendMutex.unlock();

interrupt->lock();
}

if(interrupt_mask == 0) {
suspend_main_thread();
Expand Down
2 changes: 1 addition & 1 deletion Sming/Arch/Host/Components/vflash/component.mk
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ SPI_SIZE = $(STORAGE_DEVICE_spiFlash_SIZE)
# Options to add when running emulator
CACHE_VARS += HOST_FLASH_OPTIONS
HOST_FLASH_OPTIONS ?= --flashfile=$(FLASH_BIN) --flashsize=$(SPI_SIZE)
CLI_TARGET_OPTIONS += $(HOST_FLASH_OPTIONS)
override CLI_TARGET_OPTIONS += $(HOST_FLASH_OPTIONS)

# Virtual flasher tool
VFLASH := $(PYTHON) $(COMPONENT_PATH)/vflash.py $(FLASH_BIN) $(STORAGE_DEVICE_spiFlash_SIZE_BYTES)
Expand Down
11 changes: 9 additions & 2 deletions Sming/Arch/Host/Platform/RTC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@

RtcClass RTC;

namespace
{
int timeDiff; // Difference between set time and system time
}

RtcClass::RtcClass()
{
}
Expand All @@ -30,7 +35,7 @@ uint32_t RtcClass::getRtcSeconds()
{
struct timeval tv;
gettimeofday(&tv, nullptr);
return tv.tv_sec;
return tv.tv_sec + timeDiff;
}

bool RtcClass::setRtcNanoseconds(uint64_t nanoseconds)
Expand All @@ -40,5 +45,7 @@ bool RtcClass::setRtcNanoseconds(uint64_t nanoseconds)

bool RtcClass::setRtcSeconds(uint32_t seconds)
{
return false;
timeDiff = 0;
timeDiff = seconds - getRtcSeconds();
return true;
}