diff --git a/firmware/ChibiOS3 b/firmware/ChibiOS3 index fa141e2703..5746069508 160000 --- a/firmware/ChibiOS3 +++ b/firmware/ChibiOS3 @@ -1 +1 @@ -Subproject commit fa141e270361bc75da809abe3c6d44c4dc22c46b +Subproject commit 5746069508d98a2ac94a2e0d9bdc46a532f46edf diff --git a/firmware/config/stm32f4ems/efifeatures.h b/firmware/config/stm32f4ems/efifeatures.h index 59af3a0736..c8c73f47cc 100644 --- a/firmware/config/stm32f4ems/efifeatures.h +++ b/firmware/config/stm32f4ems/efifeatures.h @@ -243,8 +243,16 @@ #define EFI_CONSOLE_UART_DEVICE (&SD3) #endif -#ifndef TS_SERIAL_UART_DEVICE +// Use 'UART' DMA-mode driver instead of 'SERIAL' +#define TS_UART_DMA_MODE FALSE + +#define TS_DMA_UART_DEVICE (&UARTD3) #define TS_SERIAL_UART_DEVICE (&SD3) + +// todo: add DMA-mode for Console & GPS? +#if TS_UART_DMA_MODE +#define EFI_UART_GPS FALSE +#undef EFI_CONSOLE_UART_DEVICE #endif // todo: start using consoleSerialTxPin? Not sure diff --git a/firmware/config/stm32f4ems/halconf.h b/firmware/config/stm32f4ems/halconf.h index 5cd540aff1..28faec0877 100644 --- a/firmware/config/stm32f4ems/halconf.h +++ b/firmware/config/stm32f4ems/halconf.h @@ -132,8 +132,13 @@ * @brief Enables the SERIAL subsystem. */ #if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +/* Configured in efifeatures.h */ +#if TS_UART_DMA_MODE +#define HAL_USE_SERIAL FALSE +#else #define HAL_USE_SERIAL TRUE #endif +#endif /** * @brief Enables the SERIAL over USB subsystem. @@ -153,8 +158,13 @@ * @brief Enables the UART subsystem. */ #if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +/* Configured in efifeatures.h */ +#if TS_UART_DMA_MODE +#define HAL_USE_UART TRUE +#else #define HAL_USE_UART FALSE #endif +#endif /** * @brief Enables the USB subsystem. @@ -353,8 +363,13 @@ * @note Disabling this option saves both code and data space. */ #if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +/* Configured in efifeatures.h */ +#if TS_UART_DMA_MODE +#define UART_USE_WAIT TRUE +#else #define UART_USE_WAIT FALSE #endif +#endif /** * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. diff --git a/firmware/config/stm32f4ems/mcuconf.h b/firmware/config/stm32f4ems/mcuconf.h index e4f536176f..47d49e6511 100644 --- a/firmware/config/stm32f4ems/mcuconf.h +++ b/firmware/config/stm32f4ems/mcuconf.h @@ -34,6 +34,11 @@ */ #define ICU_PRIORITY 3 +/** + * UART DMA-mode byte capture (low latency) + */ +#define UART_DMA_IRQ_PRIORITY (PRECISE_SCHEDULING_TIMER_PRIORITY + 2) + /* * SysTick driver system settings. */ @@ -332,12 +337,12 @@ #define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) #define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) #define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) -#define STM32_UART_USART1_IRQ_PRIORITY 12 -#define STM32_UART_USART2_IRQ_PRIORITY 12 -#define STM32_UART_USART3_IRQ_PRIORITY 12 -#define STM32_UART_UART4_IRQ_PRIORITY 12 -#define STM32_UART_UART5_IRQ_PRIORITY 12 -#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_IRQ_PRIORITY UART_DMA_IRQ_PRIORITY +#define STM32_UART_USART2_IRQ_PRIORITY UART_DMA_IRQ_PRIORITY +#define STM32_UART_USART3_IRQ_PRIORITY UART_DMA_IRQ_PRIORITY +#define STM32_UART_UART4_IRQ_PRIORITY UART_DMA_IRQ_PRIORITY +#define STM32_UART_UART5_IRQ_PRIORITY UART_DMA_IRQ_PRIORITY +#define STM32_UART_USART6_IRQ_PRIORITY UART_DMA_IRQ_PRIORITY #define STM32_UART_USART1_DMA_PRIORITY 0 #define STM32_UART_USART2_DMA_PRIORITY 0 #define STM32_UART_USART3_DMA_PRIORITY 0 diff --git a/firmware/console/binary/tunerstudio.cpp b/firmware/console/binary/tunerstudio.cpp index 77bc6b185a..3c0f6d1749 100644 --- a/firmware/console/binary/tunerstudio.cpp +++ b/firmware/console/binary/tunerstudio.cpp @@ -94,9 +94,6 @@ extern persistent_config_container_s persistentState; extern short currentPageId; -// that's 3 seconds -#define TS_READ_TIMEOUT MS2ST(3000) - /** * note the use-case where text console port is switched into * binary port @@ -113,21 +110,7 @@ extern persistent_config_container_s persistentState; static efitimems_t previousWriteReportMs = 0; -ts_channel_s tsChannel; - -static int ts_serial_ready(bool isConsoleRedirect) { -#if EFI_PROD_CODE || defined(__DOXYGEN__) - if (isCommandLineConsoleOverTTL() ^ isConsoleRedirect) { - // TS uses USB when console uses serial - return is_usb_serial_ready(); - } else { - // TS uses serial when console uses USB - return true; - } -#else - return true; -#endif -} +static ts_channel_s tsChannel; static uint16_t BINARY_RESPONSE = (uint16_t) SWAP_UINT16(BINARY_SWITCH_TAG); @@ -243,6 +226,7 @@ void handlePageSelectCommand(ts_channel_s *tsChannel, ts_response_format_e mode, } static void onlineTuneBytes(int currentPageId, uint32_t offset, int count) { + UNUSED(currentPageId); if (offset > sizeof(engine_configuration_s)) { int maxSize = sizeof(persistent_config_s) - offset; if (count > maxSize) { @@ -316,6 +300,8 @@ void handleCrc32Check(ts_channel_s *tsChannel, ts_response_format_e mode, uint16 */ void handleWriteValueCommand(ts_channel_s *tsChannel, ts_response_format_e mode, uint16_t page, uint16_t offset, uint8_t value) { + UNUSED(tsChannel); + UNUSED(mode); tsState.writeValueCommandCounter++; currentPageId = page; @@ -442,7 +428,7 @@ void runBinaryProtocolLoop(ts_channel_s *tsChannel, bool isConsoleRedirect) { bool isFirstByte = true; while (true) { - int isReady = ts_serial_ready(isConsoleRedirect); + int isReady = tsIsReady(isConsoleRedirect); if (!isReady) { chThdSleepMilliseconds(10); wasReady = false; @@ -457,13 +443,13 @@ void runBinaryProtocolLoop(ts_channel_s *tsChannel, bool isConsoleRedirect) { tsState.totalCounter++; uint8_t firstByte; - int recieved = chnReadTimeout(tsChannel->channel, &firstByte, 1, TS_READ_TIMEOUT); + int received = tunerStudioReadData(tsChannel, &firstByte, 1); #if EFI_SIMULATOR || defined(__DOXYGEN__) - logMsg("recieved %d\r\n", recieved); + logMsg("received %d\r\n", received); #endif - if (recieved != 1) { + if (received != 1) { // tunerStudioError("ERROR: no command"); continue; } @@ -482,8 +468,8 @@ void runBinaryProtocolLoop(ts_channel_s *tsChannel, bool isConsoleRedirect) { continue; uint8_t secondByte; - recieved = chnReadTimeout(tsChannel->channel, &secondByte, 1, TS_READ_TIMEOUT); - if (recieved != 1) { + received = tunerStudioReadData(tsChannel, &secondByte, 1); + if (received != 1) { tunerStudioError("TS: ERROR: no second byte"); continue; } @@ -504,8 +490,8 @@ void runBinaryProtocolLoop(ts_channel_s *tsChannel, bool isConsoleRedirect) { continue; } - recieved = chnReadTimeout(tsChannel->channel, (uint8_t* )tsChannel->crcReadBuffer, 1, TS_READ_TIMEOUT); - if (recieved != 1) { + received = tunerStudioReadData(tsChannel, (uint8_t* )tsChannel->crcReadBuffer, 1); + if (received != 1) { tunerStudioError("ERROR: did not receive command"); continue; } @@ -524,11 +510,11 @@ void runBinaryProtocolLoop(ts_channel_s *tsChannel, bool isConsoleRedirect) { // scheduleMsg(logger, "TunerStudio: reading %d+4 bytes(s)", incomingPacketSize); - recieved = chnReadTimeout(tsChannel->channel, (uint8_t * ) (tsChannel->crcReadBuffer + 1), - incomingPacketSize + CRC_VALUE_SIZE - 1, TS_READ_TIMEOUT); + received = tunerStudioReadData(tsChannel, (uint8_t * ) (tsChannel->crcReadBuffer + 1), + incomingPacketSize + CRC_VALUE_SIZE - 1); int expectedSize = incomingPacketSize + CRC_VALUE_SIZE - 1; - if (recieved != expectedSize) { - scheduleMsg(&tsLogger, "Got only %d bytes while expecting %d for command %c", recieved, + if (received != expectedSize) { + scheduleMsg(&tsLogger, "Got only %d bytes while expecting %d for command %c", received, expectedSize, command); tunerStudioError("ERROR: not enough bytes in stream"); sendResponseCode(TS_CRC, tsChannel, TS_RESPONSE_UNDERRUN); @@ -565,9 +551,7 @@ static THD_FUNCTION(tsThreadEntryPoint, arg) { (void) arg; chRegSetThreadName("tunerstudio thread"); -#if EFI_PROD_CODE || defined(__DOXYGEN__) - startTsPort(); -#endif + startTsPort(&tsChannel); runBinaryProtocolLoop(&tsChannel, false); } @@ -675,8 +659,8 @@ bool handlePlainCommand(ts_channel_s *tsChannel, uint8_t command) { handleTestCommand(tsChannel); return true; } else if (command == TS_PAGE_COMMAND) { - int recieved = chnReadTimeout(tsChannel->channel, (uint8_t * )&pageIn, sizeof(pageIn), TS_READ_TIMEOUT); - if (recieved != sizeof(pageIn)) { + int received = tunerStudioReadData(tsChannel, (uint8_t * )&pageIn, sizeof(pageIn)); + if (received != sizeof(pageIn)) { tunerStudioError("ERROR: not enough for PAGE"); return true; } @@ -685,8 +669,8 @@ bool handlePlainCommand(ts_channel_s *tsChannel, uint8_t command) { } else if (command == TS_BURN_COMMAND) { scheduleMsg(&tsLogger, "Got naked BURN"); uint16_t page; - int recieved = chnReadTimeout(tsChannel->channel, (uint8_t * )&page, sizeof(page), TS_READ_TIMEOUT); - if (recieved != sizeof(page)) { + int received = tunerStudioReadData(tsChannel, (uint8_t * )&page, sizeof(page)); + if (received != sizeof(page)) { tunerStudioError("ERROR: Not enough for plain burn"); return true; } @@ -694,17 +678,15 @@ bool handlePlainCommand(ts_channel_s *tsChannel, uint8_t command) { return true; } else if (command == TS_CHUNK_WRITE_COMMAND) { scheduleMsg(&tsLogger, "Got naked CHUNK_WRITE"); - int recieved = chnReadTimeout(tsChannel->channel, (uint8_t * )&writeChunkRequest, sizeof(writeChunkRequest), - TS_READ_TIMEOUT); - if (recieved != sizeof(writeChunkRequest)) { - scheduleMsg(&tsLogger, "ERROR: Not enough for plain chunk write header: %d", recieved); + int received = tunerStudioReadData(tsChannel, (uint8_t * )&writeChunkRequest, sizeof(writeChunkRequest)); + if (received != sizeof(writeChunkRequest)) { + scheduleMsg(&tsLogger, "ERROR: Not enough for plain chunk write header: %d", received); tsState.errorCounter++; return true; } - recieved = chnReadTimeout(tsChannel->channel, (uint8_t * )&tsChannel->crcReadBuffer, writeChunkRequest.count, - TS_READ_TIMEOUT); - if (recieved != writeChunkRequest.count) { - scheduleMsg(&tsLogger, "ERROR: Not enough for plain chunk write content: %d while expecting %d", recieved, + received = tunerStudioReadData(tsChannel, (uint8_t * )&tsChannel->crcReadBuffer, writeChunkRequest.count); + if (received != writeChunkRequest.count) { + scheduleMsg(&tsLogger, "ERROR: Not enough for plain chunk write content: %d while expecting %d", received, writeChunkRequest.count); tsState.errorCounter++; return true; @@ -716,9 +698,8 @@ bool handlePlainCommand(ts_channel_s *tsChannel, uint8_t command) { return true; } else if (command == TS_READ_COMMAND) { //scheduleMsg(logger, "Got naked READ PAGE???"); - int recieved = chnReadTimeout(tsChannel->channel, (uint8_t * )&readRequest, sizeof(readRequest), - TS_READ_TIMEOUT); - if (recieved != sizeof(readRequest)) { + int received = tunerStudioReadData(tsChannel, (uint8_t * )&readRequest, sizeof(readRequest)); + if (received != sizeof(readRequest)) { tunerStudioError("Not enough for plain read header"); return true; } @@ -830,8 +811,6 @@ void startTunerStudioConnectivity(void) { addConsoleAction("reset_ts", resetTs); addConsoleActionI("set_ts_speed", setTsSpeed); - tsChannel.channel = getTsSerialDevice(); - chThdCreateStatic(tsThreadStack, sizeof(tsThreadStack), NORMALPRIO, (tfunc_t)tsThreadEntryPoint, NULL); } diff --git a/firmware/console/binary/tunerstudio_io.cpp b/firmware/console/binary/tunerstudio_io.cpp index f1df9919ee..c93409b75f 100644 --- a/firmware/console/binary/tunerstudio_io.cpp +++ b/firmware/console/binary/tunerstudio_io.cpp @@ -17,6 +17,9 @@ EXTERN_ENGINE; extern LoggingWithStorage tsLogger; +// that's 1 second +#define TS_READ_TIMEOUT MS2ST(1000) + #if EFI_PROD_CODE || defined(__DOXYGEN__) #include "pin_repository.h" #include "usbconsole.h" @@ -24,14 +27,61 @@ extern LoggingWithStorage tsLogger; #if HAL_USE_SERIAL_USB || defined(__DOXYGEN__) extern SerialUSBDriver SDU1; -#define CONSOLE_DEVICE &SDU1 -#else -#define CONSOLE_DEVICE TS_SERIAL_UART_DEVICE +#define CONSOLE_USB_DEVICE &SDU1 #endif -static SerialConfig tsSerialConfig = { 0, 0, USART_CR2_STOP1_BITS | USART_CR2_LINEN, 0 }; +#if TS_UART_DMA_MODE +// Async. FIFO buffer takes some RAM... +static uart_dma_s tsUartDma; -void startTsPort(void) { +/* Common function for all DMA-UART IRQ handlers. */ +static void tsCopyDataFromDMA() { + chSysLockFromISR(); + // get 0-based DMA buffer position + int dmaPos = TS_DMA_BUFFER_SIZE - dmaStreamGetTransactionSize(TS_DMA_UART_DEVICE->dmarx); + // if the position is wrapped (circular DMA-mode enabled) + if (dmaPos < tsUartDma.readPos) + dmaPos += TS_DMA_BUFFER_SIZE; + // we need to update the current readPos + int newReadPos = tsUartDma.readPos; + for (int i = newReadPos; i < dmaPos; ) { + if (chIQPutI(&tsUartDma.fifoRxQueue, tsUartDma.dmaBuffer[newReadPos]) != Q_OK) { + break; // todo: ignore overflow? + } + // the read position should always stay inside the buffer range + newReadPos = (++i) & (TS_DMA_BUFFER_SIZE - 1); + } + tsUartDma.readPos = newReadPos; + chSysUnlockFromISR(); +} + +/* We use the same handler code for both halves. */ +static void tsRxIRQHalfHandler(UARTDriver *uartp, uartflags_t full) { + UNUSED(uartp); + UNUSED(full); + tsCopyDataFromDMA(); +} + +/* This handler is called right after the UART receiver has finished its work. */ +static void tsRxIRQIdleHandler(UARTDriver *uartp) { + UNUSED(uartp); + tsCopyDataFromDMA(); +} + +/* Note: This structure is modified from the default ChibiOS layout! */ +static UARTConfig tsDmaUartConfig = { + NULL, NULL, NULL, NULL, NULL, + 0, 0, 0/*USART_CR2_STOP1_BITS*/ | USART_CR2_LINEN, 0, + /*timeout_cb*/tsRxIRQIdleHandler, /*rxhalf_cb*/tsRxIRQHalfHandler +}; +#else +static SerialConfig tsSerialConfig = { 0, 0, USART_CR2_STOP1_BITS | USART_CR2_LINEN, 0 }; +#endif /* TS_UART_DMA_MODE */ +#endif /* EFI_PROD_CODE */ + + +void startTsPort(ts_channel_s *tsChannel) { +#if EFI_PROD_CODE || defined(__DOXYGEN__) #if EFI_USB_SERIAL || defined(__DOXYGEN__) if (isCommandLineConsoleOverTTL()) { print("TunerStudio over USB serial"); @@ -39,6 +89,8 @@ void startTsPort(void) { * This method contains a long delay, that's the reason why this is not done on the main thread */ usb_serial_start(); + // if console uses UART then TS uses USB + tsChannel->channel = (BaseChannel *) CONSOLE_USB_DEVICE; } else #endif { @@ -48,29 +100,32 @@ void startTsPort(void) { efiSetPadMode("tunerstudio rx", engineConfiguration->binarySerialRxPin, PAL_MODE_ALTERNATE(TS_SERIAL_AF)); efiSetPadMode("tunerstudio tx", engineConfiguration->binarySerialTxPin, PAL_MODE_ALTERNATE(TS_SERIAL_AF)); +#if TS_UART_DMA_MODE + print("Using UART-DMA mode"); + // init FIFO queue + chIQObjectInit(&tsUartDma.fifoRxQueue, tsUartDma.buffer, sizeof(tsUartDma.buffer), NULL, NULL); + + // start DMA driver + tsDmaUartConfig.speed = boardConfiguration->tunerStudioSerialSpeed; + uartStart(TS_DMA_UART_DEVICE, &tsDmaUartConfig); + + // start continuous DMA transfer using our circular buffer + tsUartDma.readPos = 0; + uartStartReceive(TS_DMA_UART_DEVICE, sizeof(tsUartDma.dmaBuffer), tsUartDma.dmaBuffer); +#else + print("Using Serial mode"); tsSerialConfig.speed = boardConfiguration->tunerStudioSerialSpeed; sdStart(TS_SERIAL_UART_DEVICE, &tsSerialConfig); - } + + tsChannel->channel = (BaseChannel *) TS_SERIAL_UART_DEVICE; +#endif /* TS_UART_DMA_MODE */ + } else + tsChannel->channel = (BaseChannel *) NULL; // actually not used } -} - +#else /* EFI_PROD_CODE */ + tsChannel->channel = (BaseChannel *) TS_SIMULATOR_PORT; #endif /* EFI_PROD_CODE */ - -BaseChannel * getTsSerialDevice(void) { -#if EFI_PROD_CODE || defined(__DOXYGEN__) -#if EFI_USB_SERIAL || defined(__DOXYGEN__) - if (isCommandLineConsoleOverTTL()) { - // if console uses UART then TS uses USB - return (BaseChannel *) CONSOLE_DEVICE; - } else -#endif - { - return (BaseChannel *) TS_SERIAL_UART_DEVICE; - } -#else - return (BaseChannel *) TS_SIMULATOR_PORT; -#endif } void tunerStudioWriteData(ts_channel_s *tsChannel, const uint8_t * buffer, int size) { @@ -78,7 +133,17 @@ void tunerStudioWriteData(ts_channel_s *tsChannel, const uint8_t * buffer, int s #if EFI_SIMULATOR || defined(__DOXYGEN__) logMsg("chSequentialStreamWrite [%d]\r\n", size); #endif + +#if TS_UART_DMA_MODE && EFI_PROD_CODE + UNUSED(tsChannel); + int transferred = size; + uartSendTimeout(TS_DMA_UART_DEVICE, (size_t *)&transferred, buffer, BINARY_IO_TIMEOUT); +#else + if (tsChannel->channel == NULL) + return; int transferred = chnWriteTimeout(tsChannel->channel, buffer, size, BINARY_IO_TIMEOUT); +#endif + #if EFI_SIMULATOR || defined(__DOXYGEN__) logMsg("transferred [%d]\r\n", transferred); #endif @@ -90,6 +155,18 @@ void tunerStudioWriteData(ts_channel_s *tsChannel, const uint8_t * buffer, int s } } +int tunerStudioReadData(ts_channel_s *tsChannel, const uint8_t * buffer, int size) { +#if TS_UART_DMA_MODE && EFI_PROD_CODE + UNUSED(tsChannel); + return (int)chIQReadTimeout(&tsUartDma.fifoRxQueue, (uint8_t * )buffer, (size_t)size, TS_READ_TIMEOUT); +#else + if (tsChannel->channel == NULL) + return 0; + return chnReadTimeout(tsChannel->channel, (uint8_t * )buffer, size, TS_READ_TIMEOUT); +#endif +} + + /** * Adds size to the beginning of a packet and a crc32 at the end. Then send the packet. */ @@ -103,13 +180,13 @@ void tunerStudioWriteCrcPacket(ts_channel_s *tsChannel, const uint8_t responseCo // CRC on whole packet uint32_t crc = crc32((void *) (writeBuffer + 2), 1); // command part of CRC crc = crc32inc((void *) buf, crc, (uint32_t) (size)); // combined with packet CRC - *(uint32_t *) (writeBuffer) = SWAP_UINT32(crc); + *(uint32_t *) (writeBuffer + 3) = SWAP_UINT32(crc); if (size > 0) { tunerStudioWriteData(tsChannel, (const uint8_t*)buf, size); // body } - tunerStudioWriteData(tsChannel, writeBuffer, 4); // CRC footer + tunerStudioWriteData(tsChannel, writeBuffer + 3, 4); // CRC footer } void tsSendResponse(ts_channel_s *tsChannel, ts_response_format_e mode, const uint8_t * buffer, int size) { @@ -121,3 +198,17 @@ void tsSendResponse(ts_channel_s *tsChannel, ts_response_format_e mode, const ui } } +bool tsIsReady(bool isConsoleRedirect) { +#if EFI_PROD_CODE || defined(__DOXYGEN__) + if (isCommandLineConsoleOverTTL() ^ isConsoleRedirect) { + // TS uses USB when console uses serial + return is_usb_serial_ready(); + } else { + // TS uses serial when console uses USB + return true; + } +#else + return true; +#endif +} + diff --git a/firmware/console/binary/tunerstudio_io.h b/firmware/console/binary/tunerstudio_io.h index e887d6a310..d31613e99e 100644 --- a/firmware/console/binary/tunerstudio_io.h +++ b/firmware/console/binary/tunerstudio_io.h @@ -39,7 +39,7 @@ typedef enum { typedef struct { BaseChannel * channel; - uint8_t writeBuffer[4]; + uint8_t writeBuffer[7]; // size(2 bytes) + response(1 byte) + crc32 (4 bytes) /** * we use 'blockingFactor = 320' in rusefi.ini * todo: should we just do (320 + CRC_WRAPPING_SIZE) ? @@ -47,6 +47,23 @@ typedef struct { char crcReadBuffer[BLOCKING_FACTOR + 30]; } ts_channel_s; +// See uart_dma_s +#define TS_FIFO_BUFFER_SIZE (BLOCKING_FACTOR + 30) +// This must be a power of 2! +#define TS_DMA_BUFFER_SIZE 32 + +// struct needed for async DMA transfer mode (see TS_UART_DMA_MODE) +typedef struct { + // circular DMA buffer + uint8_t dmaBuffer[TS_DMA_BUFFER_SIZE]; + // current read position for the DMA buffer + volatile int readPos; + // secondary FIFO buffer for async. transfer + uint8_t buffer[TS_FIFO_BUFFER_SIZE]; + // input FIFO Rx queue + input_queue_t fifoRxQueue; +} uart_dma_s; + #define TS_HELLO_COMMAND_DEPRECATED 'H' // 0x48 #define TS_HELLO_COMMAND 'S' // 0x53 #define TS_TEST_COMMAND 't' // 0x74 @@ -71,14 +88,16 @@ typedef struct { // todo: double-check this #define CRC_WRAPPING_SIZE (CRC_VALUE_SIZE + 3) -BaseChannel * getTsSerialDevice(void); -void startTsPort(void); -// that's 3 seconds -#define BINARY_IO_TIMEOUT MS2ST(3000) +void startTsPort(ts_channel_s *tsChannel); + +// that's 1 second +#define BINARY_IO_TIMEOUT MS2ST(1000) void tunerStudioWriteData(ts_channel_s *tsChannel, const uint8_t * buffer, int size); void tunerStudioWriteCrcPacket(ts_channel_s *tsChannel, const uint8_t responseCode, const void *buf, const uint16_t size); void tsSendResponse(ts_channel_s *tsChannel, ts_response_format_e mode, const uint8_t * buffer, int size); +bool tsIsReady(bool isConsoleRedirect); +int tunerStudioReadData(ts_channel_s *tsChannel, const uint8_t * buffer, int size); #endif /* CONSOLE_TUNERSTUDIO_TUNERSTUDIO_IO_H_ */ diff --git a/firmware/console/console_io.cpp b/firmware/console/console_io.cpp index e3f7d9d71d..62958600c2 100644 --- a/firmware/console/console_io.cpp +++ b/firmware/console/console_io.cpp @@ -72,6 +72,7 @@ static bool getConsoleLine(BaseSequentialStream *chp, char *line, unsigned size) short c = (short) chSequentialStreamGet(chp); onDataArrived(); +#if defined(EFI_CONSOLE_UART_DEVICE) || defined(__DOXYGEN__) if (isCommandLineConsoleOverTTL()) { uint32_t flags; chSysLock() @@ -80,12 +81,11 @@ static bool getConsoleLine(BaseSequentialStream *chp, char *line, unsigned size) flags = chEvtGetAndClearFlagsI(&consoleEventListener); chSysUnlock() ; - if (flags & SD_OVERRUN_ERROR) { // firmwareError(OBD_PCM_Processor_Fault, "serial overrun"); } - } +#endif #if EFI_UART_ECHO_TEST_MODE /** @@ -176,15 +176,15 @@ void runConsoleLoop(ts_channel_s *console) { #if EFI_PROD_CODE || EFI_EGT || defined(__DOXYGEN__) -SerialDriver * getConsoleChannel(void) { +BaseChannel * getConsoleChannel(void) { #if defined(EFI_CONSOLE_UART_DEVICE) || defined(__DOXYGEN__) if (isCommandLineConsoleOverTTL()) { - return (SerialDriver *) EFI_CONSOLE_UART_DEVICE; + return (BaseChannel *) EFI_CONSOLE_UART_DEVICE; } #endif /* EFI_CONSOLE_UART_DEVICE */ #if HAL_USE_SERIAL_USB || defined(__DOXYGEN__) - return (SerialDriver *) &SDU1; + return (BaseChannel *) &SDU1; #else return NULL; #endif /* HAL_USE_SERIAL_USB */ @@ -217,8 +217,8 @@ static THD_FUNCTION(consoleThreadThreadEntryPoint, arg) { binaryConsole.channel = (BaseChannel *) getConsoleChannel(); - runConsoleLoop(&binaryConsole); - + if (binaryConsole.channel != NULL) + runConsoleLoop(&binaryConsole); } // 10 seconds diff --git a/firmware/console/console_io.h b/firmware/console/console_io.h index d0da3e9efa..d3ddb30c57 100644 --- a/firmware/console/console_io.h +++ b/firmware/console/console_io.h @@ -29,7 +29,7 @@ typedef void (*CommandHandler)(char *); #define GET_CONSOLE_MODE_VALUE() palReadPad(CONSOLE_MODE_SWITCH_PORT, CONSOLE_MODE_SWITCH_PIN) #define SHOULD_INGORE_FLASH() (palReadPad(CONFIG_RESET_SWITCH_PORT, CONFIG_RESET_SWITCH_PIN) == 0) -SerialDriver * getConsoleChannel(void); +BaseChannel * getConsoleChannel(void); void consolePutChar(int x); void consoleOutputBuffer(const uint8_t *buf, int size);