rusefi-1/firmware/console/console_io.cpp

266 lines
6.8 KiB
C++
Raw Normal View History

2015-07-10 06:01:56 -07:00
/**
* @file console_io.cpp
*
* @date Dec 29, 2012
2018-01-20 17:55:31 -08:00
* @author Andrey Belomutskiy, (c) 2012-2018
2015-07-10 06:01:56 -07:00
*
* This file is part of rusEfi - see http://rusefi.com
*
* rusEfi is free software; you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* rusEfi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <http://www.gnu.org/licenses/>.
*/
2018-09-16 19:25:17 -07:00
#include "global.h"
#include "engine.h"
2015-07-10 06:01:56 -07:00
#include "console_io.h"
#include "rfiutil.h"
#include "tunerstudio.h"
#if EFI_SIMULATOR || defined(__DOXYGEN__)
#include "rusEfiFunctionalTest.h"
2017-01-05 01:03:02 -08:00
#endif /*EFI_SIMULATOR */
2015-07-10 06:01:56 -07:00
2016-02-14 09:03:48 -08:00
EXTERN_ENGINE;
2015-07-10 06:01:56 -07:00
#if HAL_USE_SERIAL_USB || defined(__DOXYGEN__)
#include "usbcfg.h"
#include "usbconsole.h"
extern SerialUSBDriver SDU1;
2017-01-05 01:03:02 -08:00
#endif /* HAL_USE_SERIAL_USB */
2015-07-10 06:01:56 -07:00
int lastWriteSize;
int lastWriteActual;
static bool isSerialConsoleStarted = false;
2016-02-04 12:01:45 -08:00
static event_listener_t consoleEventListener;
2015-07-10 06:01:56 -07:00
2016-02-13 18:02:14 -08:00
bool consoleByteArrived = false;
void onDataArrived(void) {
consoleByteArrived = true;
}
2015-07-10 06:01:56 -07:00
/**
* @brief Reads a whole line from the input channel.
*
* @param[in] chp pointer to a @p BaseChannel object
* @param[in] line pointer to the line buffer
* @param[in] size buffer maximum length
* @return The operation status.
* @retval TRUE the channel was reset or CTRL-D pressed.
* @retval FALSE operation successful.
*/
static bool getConsoleLine(BaseSequentialStream *chp, char *line, unsigned size) {
char *p = line;
while (true) {
2017-01-05 01:03:02 -08:00
if (!isCommandLineConsoleReady()) {
2015-07-10 06:01:56 -07:00
// we better do not read from USB serial before it is ready
chThdSleepMilliseconds(10);
continue;
}
short c = (short) streamGet(chp);
2016-02-13 18:02:14 -08:00
onDataArrived();
2015-07-10 06:01:56 -07:00
2017-05-23 10:10:43 -07:00
#if defined(EFI_CONSOLE_UART_DEVICE) || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
uint32_t flags;
chSysLock()
;
flags = chEvtGetAndClearFlagsI(&consoleEventListener);
chSysUnlock()
;
if (flags & SD_OVERRUN_ERROR) {
2016-10-10 11:02:17 -07:00
// firmwareError(OBD_PCM_Processor_Fault, "serial overrun");
2015-07-10 06:01:56 -07:00
}
2017-05-23 10:10:43 -07:00
#endif
2015-07-10 06:01:56 -07:00
#if EFI_UART_ECHO_TEST_MODE
/**
* That's test code - let's test connectivity
*/
consolePutChar((uint8_t) c);
continue;
#endif
if (c < 0 || c == 4) {
return true;
}
if (c == 8) {
if (p != line) {
// backspace
consolePutChar((uint8_t) c);
consolePutChar(0x20);
consolePutChar((uint8_t) c);
p--;
}
continue;
}
if (c == '\r') {
consolePutChar('\r');
consolePutChar('\n');
*p = 0;
return false;
}
if (c == '\n') {
consolePutChar('\n');
*p = 0;
return false;
}
if (c < 0x20) {
continue;
}
if (p < line + size - 1) {
consolePutChar((uint8_t) c);
*p++ = (char) c;
}
}
}
CommandHandler console_line_callback;
2017-01-05 02:01:46 -08:00
bool isCommandLineConsoleOverTTL(void) {
return true;
2015-07-10 06:01:56 -07:00
}
#if (defined(EFI_CONSOLE_UART_DEVICE) && ! EFI_SIMULATOR ) || defined(__DOXYGEN__)
2017-06-04 08:31:20 -07:00
static SerialConfig serialConfig = { 0, 0, USART_CR2_STOP1_BITS | USART_CR2_LINEN, 0 };
2015-07-10 06:01:56 -07:00
#endif
2017-01-04 15:02:35 -08:00
bool consoleInBinaryMode = false;
void runConsoleLoop(ts_channel_s *console) {
#if EFI_TUNER_STUDIO || defined(__DOXYGEN__)
runBinaryProtocolLoop(console, true);
#endif /* EFI_TUNER_STUDIO */
2017-01-04 15:02:35 -08:00
while (true) {
2019-02-23 09:33:49 -08:00
efiAssertVoid(CUSTOM_ERR_6571, getCurrentRemainingStack() > 256, "lowstck#9e");
2017-01-04 15:02:35 -08:00
bool end = getConsoleLine((BaseSequentialStream*) console->channel, console->crcReadBuffer, sizeof(console->crcReadBuffer) - 3);
if (end) {
// firmware simulator is the only case when this happens
continue;
}
char *trimmed = efiTrim(console->crcReadBuffer);
(console_line_callback)(trimmed);
// switch to binary protocol
#if EFI_TUNER_STUDIO || defined(__DOXYGEN__)
runBinaryProtocolLoop(console, true);
#endif /* EFI_TUNER_STUDIO */
2017-01-04 15:02:35 -08:00
}
}
2017-01-05 01:03:02 -08:00
#if EFI_PROD_CODE || EFI_EGT || defined(__DOXYGEN__)
2017-05-23 10:10:43 -07:00
BaseChannel * getConsoleChannel(void) {
2015-07-10 06:01:56 -07:00
#if defined(EFI_CONSOLE_UART_DEVICE) || defined(__DOXYGEN__)
return (BaseChannel *) EFI_CONSOLE_UART_DEVICE;
2015-07-10 06:01:56 -07:00
#endif /* EFI_CONSOLE_UART_DEVICE */
#if HAL_USE_SERIAL_USB || defined(__DOXYGEN__)
2017-05-23 10:10:43 -07:00
return (BaseChannel *) &SDU1;
2015-07-10 06:01:56 -07:00
#else
return NULL;
2017-01-05 01:03:02 -08:00
#endif /* HAL_USE_SERIAL_USB */
2015-07-10 06:01:56 -07:00
}
2017-01-05 01:03:02 -08:00
bool isCommandLineConsoleReady(void) {
return isSerialConsoleStarted;
2015-07-10 06:01:56 -07:00
}
#endif /* EFI_PROD_CODE || EFI_EGT */
#if !defined(EFI_CONSOLE_NO_THREAD) || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
ts_channel_s binaryConsole;
2015-11-24 20:03:17 -08:00
static THD_WORKING_AREA(consoleThreadStack, 3 * UTILITY_THREAD_STACK_SIZE);
2016-02-04 12:01:45 -08:00
static THD_FUNCTION(consoleThreadThreadEntryPoint, arg) {
2015-07-10 06:01:56 -07:00
(void) arg;
chRegSetThreadName("console thread");
2015-10-23 19:01:44 -07:00
#if (EFI_PROD_CODE && EFI_USB_SERIAL) || defined(__DOXYGEN__)
2017-01-05 02:01:46 -08:00
if (!isCommandLineConsoleOverTTL()) {
2015-07-10 06:01:56 -07:00
/**
* This method contains a long delay, that's the reason why this is not done on the main thread
*/
usb_serial_start();
}
#endif /* EFI_PROD_CODE */
2016-02-14 09:03:48 -08:00
2017-01-04 15:02:35 -08:00
binaryConsole.channel = (BaseChannel *) getConsoleChannel();
2017-05-23 10:10:43 -07:00
if (binaryConsole.channel != NULL)
runConsoleLoop(&binaryConsole);
2015-07-10 06:01:56 -07:00
}
#endif /* EFI_CONSOLE_NO_THREAD */
2015-07-10 06:01:56 -07:00
// 10 seconds
#define CONSOLE_WRITE_TIMEOUT 10000
2016-02-13 14:02:32 -08:00
void consolePutChar(int x) {
chnWriteTimeout(getConsoleChannel(), (const uint8_t *)&x, 1, CONSOLE_WRITE_TIMEOUT);
}
2015-07-10 06:01:56 -07:00
void consoleOutputBuffer(const uint8_t *buf, int size) {
lastWriteSize = size;
#if !EFI_UART_ECHO_TEST_MODE
lastWriteActual = chnWriteTimeout(getConsoleChannel(), buf, size, CONSOLE_WRITE_TIMEOUT);
// if (r != size)
2016-10-10 11:02:17 -07:00
// firmwareError(OBD_PCM_Processor_Fault, "Partial console write");
2015-07-10 06:01:56 -07:00
#endif /* EFI_UART_ECHO_TEST_MODE */
}
static Logging *logger;
void startConsole(Logging *sharedLogger, CommandHandler console_line_callback_p) {
logger = sharedLogger;
console_line_callback = console_line_callback_p;
#if (defined(EFI_CONSOLE_UART_DEVICE) && ! EFI_SIMULATOR) || defined(__DOXYGEN__)
2017-01-05 02:01:46 -08:00
if (isCommandLineConsoleOverTTL()) {
2015-07-10 06:01:56 -07:00
/*
2017-06-04 08:31:20 -07:00
* Activates the serial
2015-07-10 06:01:56 -07:00
* it is important to set 'NONE' as flow control! in terminal application on the PC
*/
2017-06-04 08:31:20 -07:00
serialConfig.speed = engineConfiguration->uartConsoleSerialSpeed;
2015-07-10 06:01:56 -07:00
sdStart(EFI_CONSOLE_UART_DEVICE, &serialConfig);
// cannot use pin repository here because pin repository prints to console
palSetPadMode(EFI_CONSOLE_RX_PORT, EFI_CONSOLE_RX_PIN, PAL_MODE_ALTERNATE(EFI_CONSOLE_AF));
palSetPadMode(EFI_CONSOLE_TX_PORT, EFI_CONSOLE_TX_PIN, PAL_MODE_ALTERNATE(EFI_CONSOLE_AF));
isSerialConsoleStarted = true;
2016-02-04 12:01:45 -08:00
chEvtRegisterMask((event_source_t *) chnGetEventSource(EFI_CONSOLE_UART_DEVICE), &consoleEventListener, 1);
2015-07-10 06:01:56 -07:00
}
#endif /* EFI_PROD_CODE */
#if !defined(EFI_CONSOLE_NO_THREAD) || defined(__DOXYGEN__)
2016-02-04 12:01:45 -08:00
chThdCreateStatic(consoleThreadStack, sizeof(consoleThreadStack), NORMALPRIO, (tfunc_t)consoleThreadThreadEntryPoint, NULL);
#endif /* EFI_CONSOLE_NO_THREAD */
2015-07-10 06:01:56 -07:00
}