mirror of https://github.com/rusefi/rusefi-1.git
Working UART-DMA v2.0
This commit is contained in:
parent
f45e5757b4
commit
d473fbf94f
|
@ -1 +1 @@
|
||||||
Subproject commit fa141e270361bc75da809abe3c6d44c4dc22c46b
|
Subproject commit 5746069508d98a2ac94a2e0d9bdc46a532f46edf
|
|
@ -243,8 +243,16 @@
|
||||||
#define EFI_CONSOLE_UART_DEVICE (&SD3)
|
#define EFI_CONSOLE_UART_DEVICE (&SD3)
|
||||||
#endif
|
#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)
|
#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
|
#endif
|
||||||
|
|
||||||
// todo: start using consoleSerialTxPin? Not sure
|
// todo: start using consoleSerialTxPin? Not sure
|
||||||
|
|
|
@ -132,8 +132,13 @@
|
||||||
* @brief Enables the SERIAL subsystem.
|
* @brief Enables the SERIAL subsystem.
|
||||||
*/
|
*/
|
||||||
#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
|
#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
|
#define HAL_USE_SERIAL TRUE
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enables the SERIAL over USB subsystem.
|
* @brief Enables the SERIAL over USB subsystem.
|
||||||
|
@ -153,8 +158,13 @@
|
||||||
* @brief Enables the UART subsystem.
|
* @brief Enables the UART subsystem.
|
||||||
*/
|
*/
|
||||||
#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
|
#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
|
#define HAL_USE_UART FALSE
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enables the USB subsystem.
|
* @brief Enables the USB subsystem.
|
||||||
|
@ -353,8 +363,13 @@
|
||||||
* @note Disabling this option saves both code and data space.
|
* @note Disabling this option saves both code and data space.
|
||||||
*/
|
*/
|
||||||
#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__)
|
#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
|
#define UART_USE_WAIT FALSE
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs.
|
* @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs.
|
||||||
|
|
|
@ -34,6 +34,11 @@
|
||||||
*/
|
*/
|
||||||
#define ICU_PRIORITY 3
|
#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.
|
* SysTick driver system settings.
|
||||||
*/
|
*/
|
||||||
|
@ -332,12 +337,12 @@
|
||||||
#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
|
#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_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_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7)
|
||||||
#define STM32_UART_USART1_IRQ_PRIORITY 12
|
#define STM32_UART_USART1_IRQ_PRIORITY UART_DMA_IRQ_PRIORITY
|
||||||
#define STM32_UART_USART2_IRQ_PRIORITY 12
|
#define STM32_UART_USART2_IRQ_PRIORITY UART_DMA_IRQ_PRIORITY
|
||||||
#define STM32_UART_USART3_IRQ_PRIORITY 12
|
#define STM32_UART_USART3_IRQ_PRIORITY UART_DMA_IRQ_PRIORITY
|
||||||
#define STM32_UART_UART4_IRQ_PRIORITY 12
|
#define STM32_UART_UART4_IRQ_PRIORITY UART_DMA_IRQ_PRIORITY
|
||||||
#define STM32_UART_UART5_IRQ_PRIORITY 12
|
#define STM32_UART_UART5_IRQ_PRIORITY UART_DMA_IRQ_PRIORITY
|
||||||
#define STM32_UART_USART6_IRQ_PRIORITY 12
|
#define STM32_UART_USART6_IRQ_PRIORITY UART_DMA_IRQ_PRIORITY
|
||||||
#define STM32_UART_USART1_DMA_PRIORITY 0
|
#define STM32_UART_USART1_DMA_PRIORITY 0
|
||||||
#define STM32_UART_USART2_DMA_PRIORITY 0
|
#define STM32_UART_USART2_DMA_PRIORITY 0
|
||||||
#define STM32_UART_USART3_DMA_PRIORITY 0
|
#define STM32_UART_USART3_DMA_PRIORITY 0
|
||||||
|
|
|
@ -94,9 +94,6 @@ extern persistent_config_container_s persistentState;
|
||||||
|
|
||||||
extern short currentPageId;
|
extern short currentPageId;
|
||||||
|
|
||||||
// that's 3 seconds
|
|
||||||
#define TS_READ_TIMEOUT MS2ST(3000)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* note the use-case where text console port is switched into
|
* note the use-case where text console port is switched into
|
||||||
* binary port
|
* binary port
|
||||||
|
@ -113,21 +110,7 @@ extern persistent_config_container_s persistentState;
|
||||||
|
|
||||||
static efitimems_t previousWriteReportMs = 0;
|
static efitimems_t previousWriteReportMs = 0;
|
||||||
|
|
||||||
ts_channel_s tsChannel;
|
static 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 uint16_t BINARY_RESPONSE = (uint16_t) SWAP_UINT16(BINARY_SWITCH_TAG);
|
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) {
|
static void onlineTuneBytes(int currentPageId, uint32_t offset, int count) {
|
||||||
|
UNUSED(currentPageId);
|
||||||
if (offset > sizeof(engine_configuration_s)) {
|
if (offset > sizeof(engine_configuration_s)) {
|
||||||
int maxSize = sizeof(persistent_config_s) - offset;
|
int maxSize = sizeof(persistent_config_s) - offset;
|
||||||
if (count > maxSize) {
|
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,
|
void handleWriteValueCommand(ts_channel_s *tsChannel, ts_response_format_e mode, uint16_t page, uint16_t offset,
|
||||||
uint8_t value) {
|
uint8_t value) {
|
||||||
|
UNUSED(tsChannel);
|
||||||
|
UNUSED(mode);
|
||||||
tsState.writeValueCommandCounter++;
|
tsState.writeValueCommandCounter++;
|
||||||
|
|
||||||
currentPageId = page;
|
currentPageId = page;
|
||||||
|
@ -442,7 +428,7 @@ void runBinaryProtocolLoop(ts_channel_s *tsChannel, bool isConsoleRedirect) {
|
||||||
bool isFirstByte = true;
|
bool isFirstByte = true;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
int isReady = ts_serial_ready(isConsoleRedirect);
|
int isReady = tsIsReady(isConsoleRedirect);
|
||||||
if (!isReady) {
|
if (!isReady) {
|
||||||
chThdSleepMilliseconds(10);
|
chThdSleepMilliseconds(10);
|
||||||
wasReady = false;
|
wasReady = false;
|
||||||
|
@ -457,13 +443,13 @@ void runBinaryProtocolLoop(ts_channel_s *tsChannel, bool isConsoleRedirect) {
|
||||||
tsState.totalCounter++;
|
tsState.totalCounter++;
|
||||||
|
|
||||||
uint8_t firstByte;
|
uint8_t firstByte;
|
||||||
int recieved = chnReadTimeout(tsChannel->channel, &firstByte, 1, TS_READ_TIMEOUT);
|
int received = tunerStudioReadData(tsChannel, &firstByte, 1);
|
||||||
#if EFI_SIMULATOR || defined(__DOXYGEN__)
|
#if EFI_SIMULATOR || defined(__DOXYGEN__)
|
||||||
logMsg("recieved %d\r\n", recieved);
|
logMsg("received %d\r\n", received);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (recieved != 1) {
|
if (received != 1) {
|
||||||
// tunerStudioError("ERROR: no command");
|
// tunerStudioError("ERROR: no command");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -482,8 +468,8 @@ void runBinaryProtocolLoop(ts_channel_s *tsChannel, bool isConsoleRedirect) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
uint8_t secondByte;
|
uint8_t secondByte;
|
||||||
recieved = chnReadTimeout(tsChannel->channel, &secondByte, 1, TS_READ_TIMEOUT);
|
received = tunerStudioReadData(tsChannel, &secondByte, 1);
|
||||||
if (recieved != 1) {
|
if (received != 1) {
|
||||||
tunerStudioError("TS: ERROR: no second byte");
|
tunerStudioError("TS: ERROR: no second byte");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -504,8 +490,8 @@ void runBinaryProtocolLoop(ts_channel_s *tsChannel, bool isConsoleRedirect) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
recieved = chnReadTimeout(tsChannel->channel, (uint8_t* )tsChannel->crcReadBuffer, 1, TS_READ_TIMEOUT);
|
received = tunerStudioReadData(tsChannel, (uint8_t* )tsChannel->crcReadBuffer, 1);
|
||||||
if (recieved != 1) {
|
if (received != 1) {
|
||||||
tunerStudioError("ERROR: did not receive command");
|
tunerStudioError("ERROR: did not receive command");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -524,11 +510,11 @@ void runBinaryProtocolLoop(ts_channel_s *tsChannel, bool isConsoleRedirect) {
|
||||||
|
|
||||||
// scheduleMsg(logger, "TunerStudio: reading %d+4 bytes(s)", incomingPacketSize);
|
// scheduleMsg(logger, "TunerStudio: reading %d+4 bytes(s)", incomingPacketSize);
|
||||||
|
|
||||||
recieved = chnReadTimeout(tsChannel->channel, (uint8_t * ) (tsChannel->crcReadBuffer + 1),
|
received = tunerStudioReadData(tsChannel, (uint8_t * ) (tsChannel->crcReadBuffer + 1),
|
||||||
incomingPacketSize + CRC_VALUE_SIZE - 1, TS_READ_TIMEOUT);
|
incomingPacketSize + CRC_VALUE_SIZE - 1);
|
||||||
int expectedSize = incomingPacketSize + CRC_VALUE_SIZE - 1;
|
int expectedSize = incomingPacketSize + CRC_VALUE_SIZE - 1;
|
||||||
if (recieved != expectedSize) {
|
if (received != expectedSize) {
|
||||||
scheduleMsg(&tsLogger, "Got only %d bytes while expecting %d for command %c", recieved,
|
scheduleMsg(&tsLogger, "Got only %d bytes while expecting %d for command %c", received,
|
||||||
expectedSize, command);
|
expectedSize, command);
|
||||||
tunerStudioError("ERROR: not enough bytes in stream");
|
tunerStudioError("ERROR: not enough bytes in stream");
|
||||||
sendResponseCode(TS_CRC, tsChannel, TS_RESPONSE_UNDERRUN);
|
sendResponseCode(TS_CRC, tsChannel, TS_RESPONSE_UNDERRUN);
|
||||||
|
@ -565,9 +551,7 @@ static THD_FUNCTION(tsThreadEntryPoint, arg) {
|
||||||
(void) arg;
|
(void) arg;
|
||||||
chRegSetThreadName("tunerstudio thread");
|
chRegSetThreadName("tunerstudio thread");
|
||||||
|
|
||||||
#if EFI_PROD_CODE || defined(__DOXYGEN__)
|
startTsPort(&tsChannel);
|
||||||
startTsPort();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
runBinaryProtocolLoop(&tsChannel, false);
|
runBinaryProtocolLoop(&tsChannel, false);
|
||||||
}
|
}
|
||||||
|
@ -675,8 +659,8 @@ bool handlePlainCommand(ts_channel_s *tsChannel, uint8_t command) {
|
||||||
handleTestCommand(tsChannel);
|
handleTestCommand(tsChannel);
|
||||||
return true;
|
return true;
|
||||||
} else if (command == TS_PAGE_COMMAND) {
|
} else if (command == TS_PAGE_COMMAND) {
|
||||||
int recieved = chnReadTimeout(tsChannel->channel, (uint8_t * )&pageIn, sizeof(pageIn), TS_READ_TIMEOUT);
|
int received = tunerStudioReadData(tsChannel, (uint8_t * )&pageIn, sizeof(pageIn));
|
||||||
if (recieved != sizeof(pageIn)) {
|
if (received != sizeof(pageIn)) {
|
||||||
tunerStudioError("ERROR: not enough for PAGE");
|
tunerStudioError("ERROR: not enough for PAGE");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -685,8 +669,8 @@ bool handlePlainCommand(ts_channel_s *tsChannel, uint8_t command) {
|
||||||
} else if (command == TS_BURN_COMMAND) {
|
} else if (command == TS_BURN_COMMAND) {
|
||||||
scheduleMsg(&tsLogger, "Got naked BURN");
|
scheduleMsg(&tsLogger, "Got naked BURN");
|
||||||
uint16_t page;
|
uint16_t page;
|
||||||
int recieved = chnReadTimeout(tsChannel->channel, (uint8_t * )&page, sizeof(page), TS_READ_TIMEOUT);
|
int received = tunerStudioReadData(tsChannel, (uint8_t * )&page, sizeof(page));
|
||||||
if (recieved != sizeof(page)) {
|
if (received != sizeof(page)) {
|
||||||
tunerStudioError("ERROR: Not enough for plain burn");
|
tunerStudioError("ERROR: Not enough for plain burn");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -694,17 +678,15 @@ bool handlePlainCommand(ts_channel_s *tsChannel, uint8_t command) {
|
||||||
return true;
|
return true;
|
||||||
} else if (command == TS_CHUNK_WRITE_COMMAND) {
|
} else if (command == TS_CHUNK_WRITE_COMMAND) {
|
||||||
scheduleMsg(&tsLogger, "Got naked CHUNK_WRITE");
|
scheduleMsg(&tsLogger, "Got naked CHUNK_WRITE");
|
||||||
int recieved = chnReadTimeout(tsChannel->channel, (uint8_t * )&writeChunkRequest, sizeof(writeChunkRequest),
|
int received = tunerStudioReadData(tsChannel, (uint8_t * )&writeChunkRequest, sizeof(writeChunkRequest));
|
||||||
TS_READ_TIMEOUT);
|
if (received != sizeof(writeChunkRequest)) {
|
||||||
if (recieved != sizeof(writeChunkRequest)) {
|
scheduleMsg(&tsLogger, "ERROR: Not enough for plain chunk write header: %d", received);
|
||||||
scheduleMsg(&tsLogger, "ERROR: Not enough for plain chunk write header: %d", recieved);
|
|
||||||
tsState.errorCounter++;
|
tsState.errorCounter++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
recieved = chnReadTimeout(tsChannel->channel, (uint8_t * )&tsChannel->crcReadBuffer, writeChunkRequest.count,
|
received = tunerStudioReadData(tsChannel, (uint8_t * )&tsChannel->crcReadBuffer, writeChunkRequest.count);
|
||||||
TS_READ_TIMEOUT);
|
if (received != writeChunkRequest.count) {
|
||||||
if (recieved != writeChunkRequest.count) {
|
scheduleMsg(&tsLogger, "ERROR: Not enough for plain chunk write content: %d while expecting %d", received,
|
||||||
scheduleMsg(&tsLogger, "ERROR: Not enough for plain chunk write content: %d while expecting %d", recieved,
|
|
||||||
writeChunkRequest.count);
|
writeChunkRequest.count);
|
||||||
tsState.errorCounter++;
|
tsState.errorCounter++;
|
||||||
return true;
|
return true;
|
||||||
|
@ -716,9 +698,8 @@ bool handlePlainCommand(ts_channel_s *tsChannel, uint8_t command) {
|
||||||
return true;
|
return true;
|
||||||
} else if (command == TS_READ_COMMAND) {
|
} else if (command == TS_READ_COMMAND) {
|
||||||
//scheduleMsg(logger, "Got naked READ PAGE???");
|
//scheduleMsg(logger, "Got naked READ PAGE???");
|
||||||
int recieved = chnReadTimeout(tsChannel->channel, (uint8_t * )&readRequest, sizeof(readRequest),
|
int received = tunerStudioReadData(tsChannel, (uint8_t * )&readRequest, sizeof(readRequest));
|
||||||
TS_READ_TIMEOUT);
|
if (received != sizeof(readRequest)) {
|
||||||
if (recieved != sizeof(readRequest)) {
|
|
||||||
tunerStudioError("Not enough for plain read header");
|
tunerStudioError("Not enough for plain read header");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -830,8 +811,6 @@ void startTunerStudioConnectivity(void) {
|
||||||
addConsoleAction("reset_ts", resetTs);
|
addConsoleAction("reset_ts", resetTs);
|
||||||
addConsoleActionI("set_ts_speed", setTsSpeed);
|
addConsoleActionI("set_ts_speed", setTsSpeed);
|
||||||
|
|
||||||
tsChannel.channel = getTsSerialDevice();
|
|
||||||
|
|
||||||
chThdCreateStatic(tsThreadStack, sizeof(tsThreadStack), NORMALPRIO, (tfunc_t)tsThreadEntryPoint, NULL);
|
chThdCreateStatic(tsThreadStack, sizeof(tsThreadStack), NORMALPRIO, (tfunc_t)tsThreadEntryPoint, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,9 @@ EXTERN_ENGINE;
|
||||||
|
|
||||||
extern LoggingWithStorage tsLogger;
|
extern LoggingWithStorage tsLogger;
|
||||||
|
|
||||||
|
// that's 1 second
|
||||||
|
#define TS_READ_TIMEOUT MS2ST(1000)
|
||||||
|
|
||||||
#if EFI_PROD_CODE || defined(__DOXYGEN__)
|
#if EFI_PROD_CODE || defined(__DOXYGEN__)
|
||||||
#include "pin_repository.h"
|
#include "pin_repository.h"
|
||||||
#include "usbconsole.h"
|
#include "usbconsole.h"
|
||||||
|
@ -24,14 +27,61 @@ extern LoggingWithStorage tsLogger;
|
||||||
|
|
||||||
#if HAL_USE_SERIAL_USB || defined(__DOXYGEN__)
|
#if HAL_USE_SERIAL_USB || defined(__DOXYGEN__)
|
||||||
extern SerialUSBDriver SDU1;
|
extern SerialUSBDriver SDU1;
|
||||||
#define CONSOLE_DEVICE &SDU1
|
#define CONSOLE_USB_DEVICE &SDU1
|
||||||
#else
|
|
||||||
#define CONSOLE_DEVICE TS_SERIAL_UART_DEVICE
|
|
||||||
#endif
|
#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 EFI_USB_SERIAL || defined(__DOXYGEN__)
|
||||||
if (isCommandLineConsoleOverTTL()) {
|
if (isCommandLineConsoleOverTTL()) {
|
||||||
print("TunerStudio over USB serial");
|
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
|
* This method contains a long delay, that's the reason why this is not done on the main thread
|
||||||
*/
|
*/
|
||||||
usb_serial_start();
|
usb_serial_start();
|
||||||
|
// if console uses UART then TS uses USB
|
||||||
|
tsChannel->channel = (BaseChannel *) CONSOLE_USB_DEVICE;
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
@ -48,29 +100,32 @@ void startTsPort(void) {
|
||||||
efiSetPadMode("tunerstudio rx", engineConfiguration->binarySerialRxPin, PAL_MODE_ALTERNATE(TS_SERIAL_AF));
|
efiSetPadMode("tunerstudio rx", engineConfiguration->binarySerialRxPin, PAL_MODE_ALTERNATE(TS_SERIAL_AF));
|
||||||
efiSetPadMode("tunerstudio tx", engineConfiguration->binarySerialTxPin, 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;
|
tsSerialConfig.speed = boardConfiguration->tunerStudioSerialSpeed;
|
||||||
|
|
||||||
sdStart(TS_SERIAL_UART_DEVICE, &tsSerialConfig);
|
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 */
|
#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) {
|
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__)
|
#if EFI_SIMULATOR || defined(__DOXYGEN__)
|
||||||
logMsg("chSequentialStreamWrite [%d]\r\n", size);
|
logMsg("chSequentialStreamWrite [%d]\r\n", size);
|
||||||
#endif
|
#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);
|
int transferred = chnWriteTimeout(tsChannel->channel, buffer, size, BINARY_IO_TIMEOUT);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if EFI_SIMULATOR || defined(__DOXYGEN__)
|
#if EFI_SIMULATOR || defined(__DOXYGEN__)
|
||||||
logMsg("transferred [%d]\r\n", transferred);
|
logMsg("transferred [%d]\r\n", transferred);
|
||||||
#endif
|
#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.
|
* 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
|
// CRC on whole packet
|
||||||
uint32_t crc = crc32((void *) (writeBuffer + 2), 1); // command part of CRC
|
uint32_t crc = crc32((void *) (writeBuffer + 2), 1); // command part of CRC
|
||||||
crc = crc32inc((void *) buf, crc, (uint32_t) (size)); // combined with packet 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) {
|
if (size > 0) {
|
||||||
tunerStudioWriteData(tsChannel, (const uint8_t*)buf, size); // body
|
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) {
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ typedef enum {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
BaseChannel * channel;
|
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
|
* we use 'blockingFactor = 320' in rusefi.ini
|
||||||
* todo: should we just do (320 + CRC_WRAPPING_SIZE) ?
|
* todo: should we just do (320 + CRC_WRAPPING_SIZE) ?
|
||||||
|
@ -47,6 +47,23 @@ typedef struct {
|
||||||
char crcReadBuffer[BLOCKING_FACTOR + 30];
|
char crcReadBuffer[BLOCKING_FACTOR + 30];
|
||||||
} ts_channel_s;
|
} 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_DEPRECATED 'H' // 0x48
|
||||||
#define TS_HELLO_COMMAND 'S' // 0x53
|
#define TS_HELLO_COMMAND 'S' // 0x53
|
||||||
#define TS_TEST_COMMAND 't' // 0x74
|
#define TS_TEST_COMMAND 't' // 0x74
|
||||||
|
@ -71,14 +88,16 @@ typedef struct {
|
||||||
// todo: double-check this
|
// todo: double-check this
|
||||||
#define CRC_WRAPPING_SIZE (CRC_VALUE_SIZE + 3)
|
#define CRC_WRAPPING_SIZE (CRC_VALUE_SIZE + 3)
|
||||||
|
|
||||||
BaseChannel * getTsSerialDevice(void);
|
|
||||||
void startTsPort(void);
|
|
||||||
|
|
||||||
// that's 3 seconds
|
void startTsPort(ts_channel_s *tsChannel);
|
||||||
#define BINARY_IO_TIMEOUT MS2ST(3000)
|
|
||||||
|
// that's 1 second
|
||||||
|
#define BINARY_IO_TIMEOUT MS2ST(1000)
|
||||||
|
|
||||||
void tunerStudioWriteData(ts_channel_s *tsChannel, const uint8_t * buffer, int size);
|
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 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);
|
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_ */
|
#endif /* CONSOLE_TUNERSTUDIO_TUNERSTUDIO_IO_H_ */
|
||||||
|
|
|
@ -72,6 +72,7 @@ static bool getConsoleLine(BaseSequentialStream *chp, char *line, unsigned size)
|
||||||
short c = (short) chSequentialStreamGet(chp);
|
short c = (short) chSequentialStreamGet(chp);
|
||||||
onDataArrived();
|
onDataArrived();
|
||||||
|
|
||||||
|
#if defined(EFI_CONSOLE_UART_DEVICE) || defined(__DOXYGEN__)
|
||||||
if (isCommandLineConsoleOverTTL()) {
|
if (isCommandLineConsoleOverTTL()) {
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
chSysLock()
|
chSysLock()
|
||||||
|
@ -80,12 +81,11 @@ static bool getConsoleLine(BaseSequentialStream *chp, char *line, unsigned size)
|
||||||
flags = chEvtGetAndClearFlagsI(&consoleEventListener);
|
flags = chEvtGetAndClearFlagsI(&consoleEventListener);
|
||||||
chSysUnlock()
|
chSysUnlock()
|
||||||
;
|
;
|
||||||
|
|
||||||
if (flags & SD_OVERRUN_ERROR) {
|
if (flags & SD_OVERRUN_ERROR) {
|
||||||
// firmwareError(OBD_PCM_Processor_Fault, "serial overrun");
|
// firmwareError(OBD_PCM_Processor_Fault, "serial overrun");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if EFI_UART_ECHO_TEST_MODE
|
#if EFI_UART_ECHO_TEST_MODE
|
||||||
/**
|
/**
|
||||||
|
@ -176,15 +176,15 @@ void runConsoleLoop(ts_channel_s *console) {
|
||||||
#if EFI_PROD_CODE || EFI_EGT || defined(__DOXYGEN__)
|
#if EFI_PROD_CODE || EFI_EGT || defined(__DOXYGEN__)
|
||||||
|
|
||||||
|
|
||||||
SerialDriver * getConsoleChannel(void) {
|
BaseChannel * getConsoleChannel(void) {
|
||||||
#if defined(EFI_CONSOLE_UART_DEVICE) || defined(__DOXYGEN__)
|
#if defined(EFI_CONSOLE_UART_DEVICE) || defined(__DOXYGEN__)
|
||||||
if (isCommandLineConsoleOverTTL()) {
|
if (isCommandLineConsoleOverTTL()) {
|
||||||
return (SerialDriver *) EFI_CONSOLE_UART_DEVICE;
|
return (BaseChannel *) EFI_CONSOLE_UART_DEVICE;
|
||||||
}
|
}
|
||||||
#endif /* EFI_CONSOLE_UART_DEVICE */
|
#endif /* EFI_CONSOLE_UART_DEVICE */
|
||||||
|
|
||||||
#if HAL_USE_SERIAL_USB || defined(__DOXYGEN__)
|
#if HAL_USE_SERIAL_USB || defined(__DOXYGEN__)
|
||||||
return (SerialDriver *) &SDU1;
|
return (BaseChannel *) &SDU1;
|
||||||
#else
|
#else
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif /* HAL_USE_SERIAL_USB */
|
#endif /* HAL_USE_SERIAL_USB */
|
||||||
|
@ -217,8 +217,8 @@ static THD_FUNCTION(consoleThreadThreadEntryPoint, arg) {
|
||||||
|
|
||||||
|
|
||||||
binaryConsole.channel = (BaseChannel *) getConsoleChannel();
|
binaryConsole.channel = (BaseChannel *) getConsoleChannel();
|
||||||
runConsoleLoop(&binaryConsole);
|
if (binaryConsole.channel != NULL)
|
||||||
|
runConsoleLoop(&binaryConsole);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 10 seconds
|
// 10 seconds
|
||||||
|
|
|
@ -29,7 +29,7 @@ typedef void (*CommandHandler)(char *);
|
||||||
#define GET_CONSOLE_MODE_VALUE() palReadPad(CONSOLE_MODE_SWITCH_PORT, CONSOLE_MODE_SWITCH_PIN)
|
#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)
|
#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 consolePutChar(int x);
|
||||||
void consoleOutputBuffer(const uint8_t *buf, int size);
|
void consoleOutputBuffer(const uint8_t *buf, int size);
|
||||||
|
|
Loading…
Reference in New Issue