auto-sync

This commit is contained in:
rusEfi 2015-03-08 19:05:03 -05:00
parent ebe8ed0c4b
commit 4261c0b416
9 changed files with 160 additions and 122 deletions

View File

@ -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) {

View File

@ -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);
}

View File

@ -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

View File

@ -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'

View File

@ -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;

View File

@ -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_ */

View File

@ -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
*

View File

@ -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;
}

View File

@ -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_ */