From 4261c0b416a0c8f70a3b121a6f0ead3957b995ab Mon Sep 17 00:00:00 2001 From: rusEfi Date: Sun, 8 Mar 2015 19:05:03 -0500 Subject: [PATCH] auto-sync --- firmware/console/console_io.cpp | 3 + firmware/console/tunerstudio/tunerstudio.cpp | 38 ++++--- .../console/tunerstudio/tunerstudio_io.cpp | 9 +- firmware/console/tunerstudio/tunerstudio_io.h | 1 + firmware/util/datalogging.cpp | 89 +-------------- firmware/util/datalogging.h | 27 +++-- firmware/util/efilib.cpp | 2 +- firmware/util/loggingcentral.cpp | 101 ++++++++++++++++++ firmware/util/loggingcentral.h | 12 +++ 9 files changed, 160 insertions(+), 122 deletions(-) create mode 100644 firmware/util/loggingcentral.cpp create mode 100644 firmware/util/loggingcentral.h diff --git a/firmware/console/console_io.cpp b/firmware/console/console_io.cpp index d19b9c2526..2e6a81f44b 100644 --- a/firmware/console/console_io.cpp +++ b/firmware/console/console_io.cpp @@ -149,6 +149,8 @@ bool isConsoleReady(void) { } #endif /* EFI_PROD_CODE || EFI_EGT */ +bool_t consoleInBinaryMode = false; + static THD_WORKING_AREA(consoleThreadStack, 2 * UTILITY_THREAD_STACK_SIZE); static msg_t consoleThreadThreadEntryPoint(void *arg) { (void) arg; @@ -198,6 +200,7 @@ static Logging *logger; static void switchToBinaryProtocol(void) { scheduleMsg(logger, "switching to binary protocol"); + consoleInBinaryMode = true; } void startConsole(Logging *sharedLogger, CommandHandler console_line_callback_p) { diff --git a/firmware/console/tunerstudio/tunerstudio.cpp b/firmware/console/tunerstudio/tunerstudio.cpp index ba4e2682ed..3e9cf64c60 100644 --- a/firmware/console/tunerstudio/tunerstudio.cpp +++ b/firmware/console/tunerstudio/tunerstudio.cpp @@ -99,7 +99,6 @@ static efitimems_t previousWriteReportMs = 0; ts_channel_s tsChannel; -char crcReadBuffer[300]; extern uint8_t crcWriteBuffer[300]; static int ts_serial_ready(void) { @@ -360,7 +359,7 @@ static bool isKnownCommand(char command) { return command == TS_HELLO_COMMAND || command == TS_READ_COMMAND || command == TS_OUTPUT_COMMAND || command == TS_PAGE_COMMAND || command == TS_BURN_COMMAND || command == TS_SINGLE_WRITE_COMMAND || command == TS_LEGACY_HELLO_COMMAND || command == TS_CHUNK_WRITE_COMMAND - || command == TS_EXECUTE; + || command == TS_EXECUTE || command == TS_GET_TEXT; } static uint8_t firstByte; @@ -401,20 +400,20 @@ void runBinaryProtocolLoop(ts_channel_s *tsChannel) { uint32_t incomingPacketSize = firstByte * 256 + secondByte; - if (incomingPacketSize == 0 || incomingPacketSize > (sizeof(crcReadBuffer) - CRC_WRAPPING_SIZE)) { + if (incomingPacketSize == 0 || incomingPacketSize > (sizeof(tsChannel->crcReadBuffer) - CRC_WRAPPING_SIZE)) { scheduleMsg(tsLogger, "TunerStudio: invalid size: %d", incomingPacketSize); tunerStudioError("ERROR: CRC header size"); sendErrorCode(tsChannel); continue; } - recieved = chnReadTimeout(tsChannel->channel, (uint8_t*)crcReadBuffer, 1, MS2ST(TS_READ_TIMEOUT)); + recieved = chnReadTimeout(tsChannel->channel, (uint8_t*)tsChannel->crcReadBuffer, 1, MS2ST(TS_READ_TIMEOUT)); if (recieved != 1) { tunerStudioError("ERROR: did not receive command"); continue; } - char command = crcReadBuffer[0]; + char command = tsChannel->crcReadBuffer[0]; if (!isKnownCommand(command)) { scheduleMsg(tsLogger, "unexpected command %x", command); sendErrorCode(tsChannel); @@ -423,7 +422,7 @@ void runBinaryProtocolLoop(ts_channel_s *tsChannel) { // scheduleMsg(logger, "TunerStudio: reading %d+4 bytes(s)", incomingPacketSize); - recieved = chnReadTimeout(tsChannel->channel, (uint8_t * ) (crcReadBuffer + 1), + recieved = chnReadTimeout(tsChannel->channel, (uint8_t * ) (tsChannel->crcReadBuffer + 1), incomingPacketSize + CRC_VALUE_SIZE - 1, MS2ST(TS_READ_TIMEOUT)); int expectedSize = incomingPacketSize + CRC_VALUE_SIZE - 1; if (recieved != expectedSize) { @@ -433,17 +432,17 @@ void runBinaryProtocolLoop(ts_channel_s *tsChannel) { continue; } - uint32_t expectedCrc = *(uint32_t*) (crcReadBuffer + incomingPacketSize); + uint32_t expectedCrc = *(uint32_t*) (tsChannel->crcReadBuffer + incomingPacketSize); expectedCrc = SWAP_UINT32(expectedCrc); - uint32_t actualCrc = crc32(crcReadBuffer, incomingPacketSize); + uint32_t actualCrc = crc32(tsChannel->crcReadBuffer, incomingPacketSize); if (actualCrc != expectedCrc) { - scheduleMsg(tsLogger, "TunerStudio: CRC %x %x %x %x", crcReadBuffer[incomingPacketSize + 0], - crcReadBuffer[incomingPacketSize + 1], crcReadBuffer[incomingPacketSize + 2], - crcReadBuffer[incomingPacketSize + 3]); + scheduleMsg(tsLogger, "TunerStudio: CRC %x %x %x %x", tsChannel->crcReadBuffer[incomingPacketSize + 0], + tsChannel->crcReadBuffer[incomingPacketSize + 1], tsChannel->crcReadBuffer[incomingPacketSize + 2], + tsChannel->crcReadBuffer[incomingPacketSize + 3]); - scheduleMsg(tsLogger, "TunerStudio: command %c actual CRC %x/expected %x", crcReadBuffer[0], actualCrc, + scheduleMsg(tsLogger, "TunerStudio: command %c actual CRC %x/expected %x", tsChannel->crcReadBuffer[0], actualCrc, expectedCrc); tunerStudioError("ERROR: CRC issue"); continue; @@ -452,7 +451,7 @@ void runBinaryProtocolLoop(ts_channel_s *tsChannel) { // scheduleMsg(logger, "TunerStudio: P00-07 %x %x %x %x %x %x %x %x", crcIoBuffer[0], crcIoBuffer[1], // crcIoBuffer[2], crcIoBuffer[3], crcIoBuffer[4], crcIoBuffer[5], crcIoBuffer[6], crcIoBuffer[7]); - int success = tunerStudioHandleCrcCommand(tsChannel, crcReadBuffer, incomingPacketSize); + int success = tunerStudioHandleCrcCommand(tsChannel, tsChannel->crcReadBuffer, incomingPacketSize); if (!success) print("got unexpected TunerStudio command %x:%c\r\n", command, command); @@ -573,7 +572,7 @@ bool handlePlainCommand(ts_channel_s *tsChannel, uint8_t command) { tsState.errorCounter++; return true; } - recieved = chSequentialStreamRead(tsChannel->channel, (uint8_t * )&crcReadBuffer, writeChunkRequest.count); + recieved = chSequentialStreamRead(tsChannel->channel, (uint8_t * )&tsChannel->crcReadBuffer, writeChunkRequest.count); if (recieved != writeChunkRequest.count) { scheduleMsg(tsLogger, "ERROR: Not enough for plain chunk write content: %d while expecting %d", recieved, writeChunkRequest.count); tsState.errorCounter++; @@ -581,7 +580,7 @@ bool handlePlainCommand(ts_channel_s *tsChannel, uint8_t command) { } currentPageId = writeChunkRequest.page; - handleWriteChunkCommand(tsChannel, TS_PLAIN, writeChunkRequest.offset, writeChunkRequest.count, (uint8_t * )&crcReadBuffer); + handleWriteChunkCommand(tsChannel, TS_PLAIN, writeChunkRequest.offset, writeChunkRequest.count, (uint8_t * )&tsChannel->crcReadBuffer); return true; } else if (command == TS_READ_COMMAND) { //scheduleMsg(logger, "Got naked READ PAGE???"); @@ -662,6 +661,13 @@ int tunerStudioHandleCrcCommand(ts_channel_s *tsChannel, char *data, int incomin return true; } +/** + * we use 'blockingFactor = 256' in rusefi.ini + * todo: should we just do (256 + CRC_WRAPPING_SIZE) ? + */ + +static uint8_t tsCrcWriteBuffer[300]; + void startTunerStudioConnectivity(Logging *sharedLogger) { tsLogger = sharedLogger; @@ -679,7 +685,7 @@ void startTunerStudioConnectivity(Logging *sharedLogger) { addConsoleActionI("set_ts_speed", setTsSpeed); tsChannel.channel = getTsSerialDevice(); -// tsChannel.writeBuffer + tsChannel.writeBuffer = tsCrcWriteBuffer; chThdCreateStatic(tsThreadStack, sizeof(tsThreadStack), NORMALPRIO, tsThreadEntryPoint, NULL); } diff --git a/firmware/console/tunerstudio/tunerstudio_io.cpp b/firmware/console/tunerstudio/tunerstudio_io.cpp index b044ef277d..2022a76dd3 100644 --- a/firmware/console/tunerstudio/tunerstudio_io.cpp +++ b/firmware/console/tunerstudio/tunerstudio_io.cpp @@ -13,13 +13,6 @@ EXTERN_ENGINE; extern Logging *tsLogger; -/** - * we use 'blockingFactor = 256' in rusefi.ini - * todo: should we just do (256 + CRC_WRAPPING_SIZE) ? - */ - -uint8_t crcWriteBuffer[300]; -extern char crcReadBuffer[300]; #if EFI_PROD_CODE || defined(__DOXYGEN__) #include "pin_repository.h" @@ -78,7 +71,7 @@ void tunerStudioWriteData(ts_channel_s *tsChannel, const uint8_t * buffer, int s */ void tunerStudioWriteCrcPacket(ts_channel_s *tsChannel, const uint8_t command, const void *buf, const uint16_t size) { - uint8_t *writeBuffer = crcWriteBuffer; + uint8_t *writeBuffer = tsChannel->writeBuffer; // todo: max size validation *(uint16_t *) writeBuffer = SWAP_UINT16(size + 1); // packet size including command diff --git a/firmware/console/tunerstudio/tunerstudio_io.h b/firmware/console/tunerstudio/tunerstudio_io.h index ee8df5592f..fa7e1fa1d0 100644 --- a/firmware/console/tunerstudio/tunerstudio_io.h +++ b/firmware/console/tunerstudio/tunerstudio_io.h @@ -41,6 +41,7 @@ typedef struct { #define TS_PAGE_COMMAND 'P' #define TS_COMMAND_F 'F' #define TS_EXECUTE 'E' +#define TS_GET_TEXT 'G' #define TS_SINGLE_WRITE_COMMAND 'W' #define TS_CHUNK_WRITE_COMMAND 'C' diff --git a/firmware/util/datalogging.cpp b/firmware/util/datalogging.cpp index 274cf69a93..d3fee5f074 100644 --- a/firmware/util/datalogging.cpp +++ b/firmware/util/datalogging.cpp @@ -39,36 +39,11 @@ #include "memstreams.h" #include "console_io.h" #include "rfiutil.h" +#include "loggingcentral.h" // we use this magic constant to make sure it's not just a random non-zero int in memory #define MAGIC_LOGGING_FLAG 45234441 -typedef char log_buf_t[DL_OUTPUT_BUFFER]; - -/** - * we need to leave a byte for zero terminator, also two bytes for the \r\n in - * printWithLength, also couple of bytes just in case - */ -#define MAX_DL_CAPACITY (DL_OUTPUT_BUFFER - 5) - -static log_buf_t pendingBuffers0 CCM_OPTIONAL; -static log_buf_t pendingBuffers1; - -/** - * This is the buffer into which all the data providers write - */ -static char *accumulationBuffer; - -/** - * amount of data accumulated so far - */ -static uint32_t accumulatedSize; - -/** - * We copy all the pending data into this buffer once we are ready to push it out - */ -static char * outputBuffer; - static MemoryStream intermediateLoggingBuffer; static uint8_t intermediateLoggingBufferData[INTERMEDIATE_LOGGING_BUFFER_SIZE] CCM_OPTIONAL; //todo define max-printf-buffer @@ -224,7 +199,7 @@ static char header[16]; /** * this method should invoked on the main thread only */ -static void printWithLength(char *line) { +void printWithLength(char *line) { /** * this is my way to detect serial port transmission errors * following code is functionally identical to @@ -315,70 +290,12 @@ void scheduleMsg(Logging *logging, const char *fmt, ...) { } } -void scheduleLogging(Logging *logging) { - // this could be done without locking - int newLength = efiStrlen(logging->buffer); - - bool alreadyLocked = lockOutputBuffer(); - if (accumulatedSize + newLength >= MAX_DL_CAPACITY) { - /** - * if no one is consuming the data we have to drop it - * this happens in case of serial-over-USB, todo: find a better solution? - */ - if (!alreadyLocked) { - unlockOutputBuffer(); - } - resetLogging(logging); - return; - } - // memcpy is faster then strcpy because it is not looking for line terminator - memcpy(accumulationBuffer + accumulatedSize, logging->buffer, newLength + 1); - accumulatedSize += newLength; - if (!alreadyLocked) { - unlockOutputBuffer(); - } - resetLogging(logging); -} - uint32_t remainingSize(Logging *logging) { return logging->bufferSize - loggingSize(logging); } -/** - * This method actually sends all the pending data to the communication layer. - * This method is invoked by the main thread - that's the only thread which should be sending - * actual data to console in order to avoid concurrent access to serial hardware. - */ -void printPending(void) { - lockOutputBuffer(); - /** - * we cannot output under syslock, we simply rotate which buffer is which - */ - char *temp = outputBuffer; - - int expectedOutputSize = accumulatedSize; - outputBuffer = accumulationBuffer; - - accumulationBuffer = temp; - accumulatedSize = 0; - accumulationBuffer[0] = 0; - - unlockOutputBuffer(); - - int actualOutputBuffer = efiStrlen(outputBuffer); - efiAssertVoid(actualOutputBuffer == expectedOutputSize, "out constr"); - - if (actualOutputBuffer > 0) { - printWithLength(outputBuffer); - } -} - void initIntermediateLoggingBuffer(void) { - pendingBuffers0[0] = 0; - pendingBuffers1[0] = 0; - accumulationBuffer = pendingBuffers0; - outputBuffer = pendingBuffers1; - accumulatedSize = 0; + initLoggingCentral(); msObjectInit(&intermediateLoggingBuffer, intermediateLoggingBufferData, INTERMEDIATE_LOGGING_BUFFER_SIZE, 0); intermediateLoggingBufferInited = TRUE; diff --git a/firmware/util/datalogging.h b/firmware/util/datalogging.h index 7cb83dac58..b486e9234e 100644 --- a/firmware/util/datalogging.h +++ b/firmware/util/datalogging.h @@ -44,18 +44,7 @@ public: char DEFAULT_BUFFER[200]; }; -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -bool lockOutputBuffer(void); -void unlockOutputBuffer(void); - void initIntermediateLoggingBuffer(void); -uint32_t remainingSize(Logging *logging); - -#define loggingSize(logging) ((int) (logging)->linePointer - (int) ((logging)->buffer)) int isInitialized(Logging *logging); @@ -74,6 +63,20 @@ void appendMsgPostfix(Logging *logging); void scheduleMsg(Logging *logging, const char *fmt, ...); + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +bool lockOutputBuffer(void); +void unlockOutputBuffer(void); + +uint32_t remainingSize(Logging *logging); + +#define loggingSize(logging) ((int) (logging)->linePointer - (int) ((logging)->buffer)) + + void printMsg(Logging *logging, const char *fmt, ...); void appendPrintf(Logging *logging, const char *fmt, ...); void vappendPrintf(Logging *logging, const char *fmt, va_list arg); @@ -100,4 +103,6 @@ void printPending(void); } #endif /* __cplusplus */ +void printWithLength(char *line); + #endif /* DATALOGGING_H_ */ diff --git a/firmware/util/efilib.cpp b/firmware/util/efilib.cpp index af61e378fc..89cbfeb561 100644 --- a/firmware/util/efilib.cpp +++ b/firmware/util/efilib.cpp @@ -1,5 +1,5 @@ /** - * @file efilib.c + * @file efilib.cpp * * We cannot use stdlib because we do not have malloc - so, we have to implement these functions * diff --git a/firmware/util/loggingcentral.cpp b/firmware/util/loggingcentral.cpp new file mode 100644 index 0000000000..8a9d282bcd --- /dev/null +++ b/firmware/util/loggingcentral.cpp @@ -0,0 +1,101 @@ +/** + * @file loggingcentral.cpp + * + * @date Mar 8, 2015 + * @author Andrey Belomutskiy, (c) 2012-2015 + */ + +#include "main.h" +#include "efilib.h" + +typedef char log_buf_t[DL_OUTPUT_BUFFER]; + +/** + * we need to leave a byte for zero terminator, also two bytes for the \r\n in + * printWithLength, also couple of bytes just in case + */ +#define MAX_DL_CAPACITY (DL_OUTPUT_BUFFER - 5) + +/** + * This is the buffer into which all the data providers write + */ +static char *accumulationBuffer; + +static log_buf_t pendingBuffers0 CCM_OPTIONAL; +static log_buf_t pendingBuffers1; + +/** + * amount of data accumulated so far + */ +static uint32_t accumulatedSize; + +/** + * We copy all the pending data into this buffer once we are ready to push it out + */ +static char * outputBuffer; + +/** + * This method appends the content of this thread-local logger into the global buffer + * of logging content + */ +void scheduleLogging(Logging *logging) { + // this could be done without locking + int newLength = efiStrlen(logging->buffer); + + bool alreadyLocked = lockOutputBuffer(); + if (accumulatedSize + newLength >= MAX_DL_CAPACITY) { + /** + * if no one is consuming the data we have to drop it + * this happens in case of serial-over-USB, todo: find a better solution? + */ + if (!alreadyLocked) { + unlockOutputBuffer(); + } + resetLogging(logging); + return; + } + // memcpy is faster then strcpy because it is not looking for line terminator + memcpy(accumulationBuffer + accumulatedSize, logging->buffer, newLength + 1); + accumulatedSize += newLength; + if (!alreadyLocked) { + unlockOutputBuffer(); + } + resetLogging(logging); +} + +/** + * This method actually sends all the pending data to the communication layer. + * This method is invoked by the main thread - that's the only thread which should be sending + * actual data to console in order to avoid concurrent access to serial hardware. + */ +void printPending(void) { + lockOutputBuffer(); + /** + * we cannot output under syslock, we simply rotate which buffer is which + */ + char *temp = outputBuffer; + + int expectedOutputSize = accumulatedSize; + outputBuffer = accumulationBuffer; + + accumulationBuffer = temp; + accumulatedSize = 0; + accumulationBuffer[0] = 0; + + unlockOutputBuffer(); + + int actualOutputBuffer = efiStrlen(outputBuffer); + efiAssertVoid(actualOutputBuffer == expectedOutputSize, "out constr"); + + if (actualOutputBuffer > 0) { + printWithLength(outputBuffer); + } +} + +void initLoggingCentral(void) { + pendingBuffers0[0] = 0; + pendingBuffers1[0] = 0; + accumulationBuffer = pendingBuffers0; + outputBuffer = pendingBuffers1; + accumulatedSize = 0; +} diff --git a/firmware/util/loggingcentral.h b/firmware/util/loggingcentral.h new file mode 100644 index 0000000000..bac7d1918d --- /dev/null +++ b/firmware/util/loggingcentral.h @@ -0,0 +1,12 @@ +/** + * @file loggingcentral.h + * + * @date Mar 8, 2015 + * @author Andrey Belomutskiy, (c) 2012-2015 + */ +#ifndef UTIL_LOGGINGCENTRAL_H_ +#define UTIL_LOGGINGCENTRAL_H_ + +void initLoggingCentral(void); + +#endif /* UTIL_LOGGINGCENTRAL_H_ */