rusefi-1/firmware/console/binary/tunerstudio_io.cpp

258 lines
7.8 KiB
C++
Raw Normal View History

2015-07-10 06:01:56 -07:00
/**
* @file tunerstudio_io.cpp
*
* @date Mar 8, 2015
2018-01-20 17:55:31 -08:00
* @author Andrey Belomutskiy, (c) 2012-2018
2015-07-10 06:01:56 -07:00
*/
#include "main.h"
#include "tunerstudio_io.h"
#include "console_io.h"
#include "engine.h"
#if EFI_SIMULATOR || defined(__DOXYGEN__)
#include "rusEfiFunctionalTest.h"
#endif
EXTERN_ENGINE;
extern LoggingWithStorage tsLogger;
#if EFI_PROD_CODE || defined(__DOXYGEN__)
#include "pin_repository.h"
#include "usbconsole.h"
#if HAL_USE_SERIAL_USB || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
extern SerialUSBDriver SDU1;
2017-05-23 10:10:43 -07:00
#define CONSOLE_USB_DEVICE &SDU1
#endif
2015-07-10 06:01:56 -07:00
2017-05-23 10:10:43 -07:00
#if TS_UART_DMA_MODE
// Async. FIFO buffer takes some RAM...
static uart_dma_s tsUartDma;
/* 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; ) {
2018-01-24 05:14:21 -08:00
if (iqPutI(&tsUartDma.fifoRxQueue, tsUartDma.dmaBuffer[newReadPos]) != Q_OK) {
2017-05-23 10:10:43 -07:00
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
2015-07-10 06:01:56 -07:00
static SerialConfig tsSerialConfig = { 0, 0, USART_CR2_STOP1_BITS | USART_CR2_LINEN, 0 };
2017-05-23 10:10:43 -07:00
#endif /* TS_UART_DMA_MODE */
#endif /* EFI_PROD_CODE */
2015-07-10 06:01:56 -07:00
2017-05-23 10:10:43 -07:00
void startTsPort(ts_channel_s *tsChannel) {
#if EFI_PROD_CODE || defined(__DOXYGEN__)
2015-10-23 19:01:44 -07:00
#if EFI_USB_SERIAL || defined(__DOXYGEN__)
2017-01-05 02:01:46 -08:00
if (isCommandLineConsoleOverTTL()) {
2015-07-10 06:01:56 -07:00
print("TunerStudio over USB serial");
/**
* This method contains a long delay, that's the reason why this is not done on the main thread
*/
usb_serial_start();
2017-05-23 10:10:43 -07:00
// if console uses UART then TS uses USB
tsChannel->channel = (BaseChannel *) CONSOLE_USB_DEVICE;
2015-10-23 19:01:44 -07:00
} else
#endif
{
if (boardConfiguration->useSerialPort) {
2015-07-10 06:01:56 -07:00
2015-11-09 16:03:32 -08:00
print("TunerStudio over USART");
2017-05-15 05:40:54 -07:00
efiSetPadMode("tunerstudio rx", engineConfiguration->binarySerialRxPin, PAL_MODE_ALTERNATE(TS_SERIAL_AF));
efiSetPadMode("tunerstudio tx", engineConfiguration->binarySerialTxPin, PAL_MODE_ALTERNATE(TS_SERIAL_AF));
2015-07-10 06:01:56 -07:00
2017-05-23 10:10:43 -07:00
#if TS_UART_DMA_MODE
print("Using UART-DMA mode");
// init FIFO queue
2018-01-24 05:14:21 -08:00
iqObjectInit(&tsUartDma.fifoRxQueue, tsUartDma.buffer, sizeof(tsUartDma.buffer), NULL, NULL);
2017-05-23 10:10:43 -07:00
// 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");
2015-11-09 16:03:32 -08:00
tsSerialConfig.speed = boardConfiguration->tunerStudioSerialSpeed;
2015-07-10 06:01:56 -07:00
2015-11-09 16:03:32 -08:00
sdStart(TS_SERIAL_UART_DEVICE, &tsSerialConfig);
2017-05-23 10:10:43 -07:00
tsChannel->channel = (BaseChannel *) TS_SERIAL_UART_DEVICE;
#endif /* TS_UART_DMA_MODE */
} else
tsChannel->channel = (BaseChannel *) NULL; // actually not used
2015-10-23 19:01:44 -07:00
}
2017-05-23 10:10:43 -07:00
#else /* EFI_PROD_CODE */
tsChannel->channel = (BaseChannel *) TS_SIMULATOR_PORT;
2015-07-10 06:01:56 -07:00
#endif /* EFI_PROD_CODE */
}
bool stopTsPort(ts_channel_s *tsChannel) {
#if EFI_PROD_CODE || defined(__DOXYGEN__)
#if EFI_USB_SERIAL || defined(__DOXYGEN__)
if (isCommandLineConsoleOverTTL()) {
#if 0
usb_serial_stop();
#endif
// don't stop USB!
return false;
} else
#endif
{
if (boardConfiguration->useSerialPort) {
// todo: disable Rx/Tx pads?
#if TS_UART_DMA_MODE
uartStop(TS_DMA_UART_DEVICE);
#else
sdStop(TS_SERIAL_UART_DEVICE);
#endif /* TS_UART_DMA_MODE */
}
}
tsChannel->channel = (BaseChannel *) NULL;
return true;
#else /* EFI_PROD_CODE */
// don't stop simulator!
return false;
#endif /* EFI_PROD_CODE */
}
void sr5WriteData(ts_channel_s *tsChannel, const uint8_t * buffer, int size) {
2018-07-25 20:03:04 -07:00
efiAssertVoid(CUSTOM_ERR_6570, getRemainingStack(chThdGetSelfX()) > 64, "tunerStudioWriteData");
2015-07-10 06:01:56 -07:00
#if EFI_SIMULATOR || defined(__DOXYGEN__)
logMsg("chSequentialStreamWrite [%d]\r\n", size);
#endif
2017-05-23 10:10:43 -07:00
#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;
2018-01-24 18:34:05 -08:00
// int transferred = chnWriteTimeout(tsChannel->channel, buffer, size, BINARY_IO_TIMEOUT);
// temporary attempt to work around #553
// instead of one huge packet let's try sending a few smaller packets
int transferred = 0;
int stillToTransfer = size;
while (stillToTransfer > 0) {
2018-01-25 06:46:31 -08:00
int thisTransferSize = minI(stillToTransfer, 768);
2018-01-24 18:34:05 -08:00
transferred += chnWriteTimeout(tsChannel->channel, buffer, thisTransferSize, BINARY_IO_TIMEOUT);
buffer += thisTransferSize;
stillToTransfer -= thisTransferSize;
}
2017-05-23 10:10:43 -07:00
#endif
2015-07-10 06:01:56 -07:00
#if EFI_SIMULATOR || defined(__DOXYGEN__)
logMsg("transferred [%d]\r\n", transferred);
#endif
if (transferred != size) {
#if EFI_SIMULATOR || defined(__DOXYGEN__)
logMsg("!!! NOT ACCEPTED %d out of %d !!!", transferred, size);
2017-05-23 14:39:47 -07:00
#endif /* EFI_SIMULATOR */
2015-07-10 06:01:56 -07:00
scheduleMsg(&tsLogger, "!!! NOT ACCEPTED %d out of %d !!!", transferred, size);
}
}
2017-05-30 11:08:12 -07:00
int sr5ReadDataTimeout(ts_channel_s *tsChannel, uint8_t * buffer, int size, int timeout) {
2017-05-23 14:39:47 -07:00
#if TS_UART_DMA_MODE || defined(__DOXYGEN__)
2017-05-23 10:10:43 -07:00
UNUSED(tsChannel);
2018-01-24 05:14:21 -08:00
return (int)iqReadTimeout(&tsUartDma.fifoRxQueue, (uint8_t * )buffer, (size_t)size, timeout);
2017-05-23 14:39:47 -07:00
#else /* TS_UART_DMA_MODE */
2017-05-23 10:10:43 -07:00
if (tsChannel->channel == NULL)
return 0;
2017-05-30 11:08:12 -07:00
return chnReadTimeout(tsChannel->channel, (uint8_t * )buffer, size, timeout);
2017-05-23 14:39:47 -07:00
#endif /* TS_UART_DMA_MODE */
2017-05-23 10:10:43 -07:00
}
2017-05-30 11:08:12 -07:00
int sr5ReadData(ts_channel_s *tsChannel, uint8_t * buffer, int size) {
return sr5ReadDataTimeout(tsChannel, buffer, size, SR5_READ_TIMEOUT);
}
2017-05-23 10:10:43 -07:00
2015-07-10 06:01:56 -07:00
/**
* Adds size to the beginning of a packet and a crc32 at the end. Then send the packet.
*/
void sr5WriteCrcPacket(ts_channel_s *tsChannel, const uint8_t responseCode, const void *buf, const uint16_t size) {
2015-07-10 06:01:56 -07:00
uint8_t *writeBuffer = tsChannel->writeBuffer;
2017-05-23 12:12:20 -07:00
uint8_t *crcBuffer = &tsChannel->writeBuffer[3];
2015-07-10 06:01:56 -07:00
*(uint16_t *) writeBuffer = SWAP_UINT16(size + 1); // packet size including command
2017-01-02 04:02:49 -08:00
*(uint8_t *) (writeBuffer + 2) = responseCode;
2015-08-22 11:02:14 -07:00
2015-07-10 06:01:56 -07:00
// CRC on whole packet
2015-08-22 11:02:14 -07:00
uint32_t crc = crc32((void *) (writeBuffer + 2), 1); // command part of CRC
crc = crc32inc((void *) buf, crc, (uint32_t) (size)); // combined with packet CRC
2015-07-10 06:01:56 -07:00
2017-05-23 12:12:20 -07:00
*(uint32_t *) (crcBuffer) = SWAP_UINT32(crc);
sr5WriteData(tsChannel, writeBuffer, 3); // header
2015-08-22 11:02:14 -07:00
if (size > 0) {
sr5WriteData(tsChannel, (const uint8_t*)buf, size); // body
2015-08-22 11:02:14 -07:00
}
2017-05-23 12:12:20 -07:00
sr5WriteData(tsChannel, crcBuffer, 4); // CRC footer
2015-07-10 06:01:56 -07:00
}
void sr5SendResponse(ts_channel_s *tsChannel, ts_response_format_e mode, const uint8_t * buffer, int size) {
2015-07-10 06:01:56 -07:00
if (mode == TS_CRC) {
sr5WriteCrcPacket(tsChannel, TS_RESPONSE_OK, buffer, size);
2015-07-10 06:01:56 -07:00
} else {
if (size > 0)
sr5WriteData(tsChannel, buffer, size);
2015-07-10 06:01:56 -07:00
}
}
2017-05-23 11:54:40 -07:00
bool sr5IsReady(bool isConsoleRedirect) {
2017-05-23 10:10:43 -07:00
#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
}