diff --git a/Sming/Arch/Host/Components/driver/component.mk b/Sming/Arch/Host/Components/driver/component.mk index 334ca3db26..2e19ed401d 100644 --- a/Sming/Arch/Host/Components/driver/component.mk +++ b/Sming/Arch/Host/Components/driver/component.mk @@ -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 diff --git a/Sming/Arch/Host/Components/driver/uart.cpp b/Sming/Arch/Host/Components/driver/uart.cpp index bde5e7dfdd..ee5d285202 100644 --- a/Sming/Arch/Host/Components/driver/uart.cpp +++ b/Sming/Arch/Host/Components/driver/uart.cpp @@ -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; @@ -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; diff --git a/Sming/Arch/Host/Components/driver/uart.rst b/Sming/Arch/Host/Components/driver/uart.rst index 8e8a6e19c8..ea635a9846 100644 --- a/Sming/Arch/Host/Components/driver/uart.rst +++ b/Sming/Arch/Host/Components/driver/uart.rst @@ -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 @@ -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" diff --git a/Sming/Arch/Host/Components/driver/uart_server.cpp b/Sming/Arch/Host/Components/driver/uart_server.cpp index 16b78c3cdc..aadc360bd1 100644 --- a/Sming/Arch/Host/Components/driver/uart_server.cpp +++ b/Sming/Arch/Host/Components/driver/uart_server.cpp @@ -31,7 +31,6 @@ namespace { unsigned portBase{10000}; std::unique_ptr servers[UART_COUNT]; -} // namespace class KeyboardThread : public CThread { @@ -93,9 +92,9 @@ void* KeyboardThread::thread_routine() return nullptr; } -static KeyboardThread* keyboardThread; +KeyboardThread* keyboardThread; -static void destroyKeyboardThread() +void destroyKeyboardThread() { if(keyboardThread == nullptr) { return; @@ -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: { @@ -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) { @@ -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); } } diff --git a/Sming/Arch/Host/Components/esp_wifi/component.mk b/Sming/Arch/Host/Components/esp_wifi/component.mk index bb59c69494..1fd2c3aeb5 100644 --- a/Sming/Arch/Host/Components/esp_wifi/component.mk +++ b/Sming/Arch/Host/Components/esp_wifi/component.mk @@ -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 diff --git a/Sming/Arch/Host/Components/hostlib/options.h b/Sming/Arch/Host/Components/hostlib/options.h index 89ecd9306e..73ef80d6d0 100644 --- a/Sming/Arch/Host/Components/hostlib/options.h +++ b/Sming/Arch/Host/Components/hostlib/options.h @@ -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", \ diff --git a/Sming/Arch/Host/Components/hostlib/threads.cpp b/Sming/Arch/Host/Components/hostlib/threads.cpp index b5eb10033e..c35ae5d785 100644 --- a/Sming/Arch/Host/Components/hostlib/threads.cpp +++ b/Sming/Arch/Host/Components/hostlib/threads.cpp @@ -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(); diff --git a/Sming/Arch/Host/Components/vflash/component.mk b/Sming/Arch/Host/Components/vflash/component.mk index 65f9df027a..d70bebe643 100644 --- a/Sming/Arch/Host/Components/vflash/component.mk +++ b/Sming/Arch/Host/Components/vflash/component.mk @@ -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) diff --git a/Sming/Arch/Host/Platform/RTC.cpp b/Sming/Arch/Host/Platform/RTC.cpp index bfe723b1f3..6d93b702be 100644 --- a/Sming/Arch/Host/Platform/RTC.cpp +++ b/Sming/Arch/Host/Platform/RTC.cpp @@ -14,6 +14,11 @@ RtcClass RTC; +namespace +{ +int timeDiff; // Difference between set time and system time +} + RtcClass::RtcClass() { } @@ -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) @@ -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; }