mirror of https://github.com/rusefi/wideband.git
Ts dev (#175)
* Remove pageValueWrite command support Move advanced pageChunkWrite is used * Straight logic in validateOffsetCount(), simplify, move to tunerstudio.cpp * Remove some more unused commands * More unused defines * Command defines cleanup * Test command * TS: fix signature * pageIdentifier is optional * pageActivate command is not used * TS: extract offset and size from incoming packet only for packets with such data * TS: cast to packet header * TS: use page in commands * TS: support scatteredOchGetCommand * TS: incapsulation * TS: scatter: optimization for CPU load * More CPU load optimization * Update libfirmware
This commit is contained in:
parent
4d8ee933e6
commit
e5a7952db0
|
@ -85,8 +85,8 @@ static void printErrorCounters() {
|
||||||
// efiPrintf("TunerStudio size=%d / total=%d / errors=%d / H=%d / O=%d / P=%d / B=%d",
|
// efiPrintf("TunerStudio size=%d / total=%d / errors=%d / H=%d / O=%d / P=%d / B=%d",
|
||||||
// sizeof(engine->outputChannels), tsState.totalCounter, tsState.errorCounter, tsState.queryCommandCounter,
|
// sizeof(engine->outputChannels), tsState.totalCounter, tsState.errorCounter, tsState.queryCommandCounter,
|
||||||
// tsState.outputChannelsCommandCounter, tsState.readPageCommandsCounter, tsState.burnCommandCounter);
|
// tsState.outputChannelsCommandCounter, tsState.readPageCommandsCounter, tsState.burnCommandCounter);
|
||||||
// efiPrintf("TunerStudio W=%d / C=%d / P=%d", tsState.writeValueCommandCounter,
|
// efiPrintf("TunerStudio W=%d / C=%d", tsState.writeValueCommandCounter,
|
||||||
// tsState.writeChunkCommandCounter, tsState.pageCommandCounter);
|
// tsState.writeChunkCommandCounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TunerStudio repeats connection attempts at ~1Hz rate.
|
/* TunerStudio repeats connection attempts at ~1Hz rate.
|
||||||
|
@ -117,13 +117,17 @@ void TunerStudio::sendErrorCode(TsChannelBase* tsChannel, uint8_t code) {
|
||||||
::sendErrorCode(tsChannel, code);
|
::sendErrorCode(tsChannel, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TunerStudio::handlePageSelectCommand(TsChannelBase *tsChannel, ts_response_format_e mode) {
|
size_t getTunerStudioPageSize() {
|
||||||
tsState.pageCommandCounter++;
|
return GetConfigurationSize();
|
||||||
|
|
||||||
sendOkResponse(tsChannel, mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool validateOffsetCount(size_t offset, size_t count, TsChannelBase* tsChannel);
|
// Validate whether the specified offset and count would cause an overrun in the tune.
|
||||||
|
// Returns true if offset and count are in valid range
|
||||||
|
bool validateOffsetCount(size_t offset, size_t count) {
|
||||||
|
if (offset + count > getTunerStudioPageSize())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This command is needed to make the whole transfer a bit faster
|
* This command is needed to make the whole transfer a bit faster
|
||||||
|
@ -135,7 +139,9 @@ void TunerStudio::handleWriteChunkCommand(TsChannelBase* tsChannel, ts_response_
|
||||||
|
|
||||||
tsState.writeChunkCommandCounter++;
|
tsState.writeChunkCommandCounter++;
|
||||||
|
|
||||||
if (validateOffsetCount(offset, count, tsChannel)) {
|
if (!validateOffsetCount(offset, count)) {
|
||||||
|
tunerStudioError(tsChannel, "ERROR: out of range");
|
||||||
|
sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +155,9 @@ void TunerStudio::handleCrc32Check(TsChannelBase *tsChannel, ts_response_format_
|
||||||
tsState.crc32CheckCommandCounter++;
|
tsState.crc32CheckCommandCounter++;
|
||||||
|
|
||||||
// Ensure we are reading from in bounds
|
// Ensure we are reading from in bounds
|
||||||
if (validateOffsetCount(offset, count, tsChannel)) {
|
if (!validateOffsetCount(offset, count)) {
|
||||||
|
tunerStudioError(tsChannel, "ERROR: out of range");
|
||||||
|
sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,28 +167,12 @@ void TunerStudio::handleCrc32Check(TsChannelBase *tsChannel, ts_response_format_
|
||||||
tsChannel->sendResponse(mode, (const uint8_t *) &crc, 4);
|
tsChannel->sendResponse(mode, (const uint8_t *) &crc, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 'Write' command receives a single value at a given offset
|
|
||||||
* @note Writing values one by one is pretty slow
|
|
||||||
*/
|
|
||||||
void TunerStudio::handleWriteValueCommand(TsChannelBase* tsChannel, ts_response_format_e mode, uint16_t offset, uint8_t value) {
|
|
||||||
(void)tsChannel;
|
|
||||||
(void)mode;
|
|
||||||
(void)value;
|
|
||||||
|
|
||||||
tsState.writeValueCommandCounter++;
|
|
||||||
|
|
||||||
tunerStudioDebug(tsChannel, "got W (Write)"); // we can get a lot of these
|
|
||||||
|
|
||||||
if (validateOffsetCount(offset, 1, tsChannel)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TunerStudio::handlePageReadCommand(TsChannelBase* tsChannel, ts_response_format_e mode, uint16_t offset, uint16_t count) {
|
void TunerStudio::handlePageReadCommand(TsChannelBase* tsChannel, ts_response_format_e mode, uint16_t offset, uint16_t count) {
|
||||||
tsState.readPageCommandsCounter++;
|
tsState.readPageCommandsCounter++;
|
||||||
|
|
||||||
if (validateOffsetCount(offset, count, tsChannel)) {
|
if (!validateOffsetCount(offset, count)) {
|
||||||
|
tunerStudioError(tsChannel, "ERROR: out of range");
|
||||||
|
sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,11 +203,11 @@ static void handleBurnCommand(TsChannelBase* tsChannel, ts_response_format_e mod
|
||||||
|
|
||||||
static bool isKnownCommand(char command) {
|
static bool isKnownCommand(char command) {
|
||||||
return command == TS_HELLO_COMMAND || command == TS_READ_COMMAND || command == TS_OUTPUT_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_BURN_COMMAND
|
||||||
|| command == TS_CHUNK_WRITE_COMMAND
|
|| command == TS_CHUNK_WRITE_COMMAND
|
||||||
|
|| command == TS_GET_SCATTERED_GET_COMMAND
|
||||||
|| command == TS_CRC_CHECK_COMMAND
|
|| command == TS_CRC_CHECK_COMMAND
|
||||||
|| command == TS_GET_FIRMWARE_VERSION
|
|| command == TS_GET_FIRMWARE_VERSION;
|
||||||
|| command == TS_GET_CONFIG_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -232,7 +224,8 @@ static void handleTestCommand(TsChannelBase* tsChannel) {
|
||||||
* extension of the protocol to simplify troubleshooting
|
* extension of the protocol to simplify troubleshooting
|
||||||
*/
|
*/
|
||||||
tunerStudioDebug(tsChannel, "got T (Test)");
|
tunerStudioDebug(tsChannel, "got T (Test)");
|
||||||
tsChannel->write((const uint8_t*)VCS_VERSION, sizeof(VCS_VERSION));
|
chsnprintf(testOutputBuffer, sizeof(testOutputBuffer), VCS_VERSION "\r\n");
|
||||||
|
tsChannel->write((const uint8_t*)testOutputBuffer, strlen(testOutputBuffer));
|
||||||
|
|
||||||
chsnprintf(testOutputBuffer, sizeof(testOutputBuffer), __DATE__ "\r\n");
|
chsnprintf(testOutputBuffer, sizeof(testOutputBuffer), __DATE__ "\r\n");
|
||||||
tsChannel->write((const uint8_t*)testOutputBuffer, strlen(testOutputBuffer));
|
tsChannel->write((const uint8_t*)testOutputBuffer, strlen(testOutputBuffer));
|
||||||
|
@ -463,22 +456,17 @@ static void handleGetVersion(TsChannelBase* tsChannel) {
|
||||||
tsChannel->sendResponse(TS_CRC, (const uint8_t *) versionBuffer, strlen(versionBuffer) + 1);
|
tsChannel->sendResponse(TS_CRC, (const uint8_t *) versionBuffer, strlen(versionBuffer) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TunerStudio::handleCrcCommand(TsChannelBase* tsChannel, char *data, int incomingPacketSize) {
|
int TunerStudio::handleCrcCommand(TsChannelBase* tsChannel, char *data, size_t incomingPacketSize) {
|
||||||
|
bool handled = true;
|
||||||
(void)incomingPacketSize;
|
(void)incomingPacketSize;
|
||||||
|
|
||||||
char command = data[0];
|
char command = data[0];
|
||||||
data++;
|
|
||||||
|
|
||||||
const uint16_t* data16 = reinterpret_cast<uint16_t*>(data);
|
|
||||||
|
|
||||||
uint16_t offset = data16[0];
|
|
||||||
uint16_t count = data16[1];
|
|
||||||
|
|
||||||
|
/* commands with no arguments */
|
||||||
switch(command)
|
switch(command)
|
||||||
{
|
{
|
||||||
case TS_OUTPUT_COMMAND:
|
case TS_GET_SCATTERED_GET_COMMAND:
|
||||||
tsState.outputChannelsCommandCounter++;
|
handleScatteredReadCommand(tsChannel);
|
||||||
cmdOutputChannels(tsChannel, offset, count);
|
|
||||||
break;
|
break;
|
||||||
case TS_HELLO_COMMAND:
|
case TS_HELLO_COMMAND:
|
||||||
tunerStudioDebug(tsChannel, "got Query command");
|
tunerStudioDebug(tsChannel, "got Query command");
|
||||||
|
@ -487,29 +475,55 @@ int TunerStudio::handleCrcCommand(TsChannelBase* tsChannel, char *data, int inco
|
||||||
case TS_GET_FIRMWARE_VERSION:
|
case TS_GET_FIRMWARE_VERSION:
|
||||||
handleGetVersion(tsChannel);
|
handleGetVersion(tsChannel);
|
||||||
break;
|
break;
|
||||||
case TS_PAGE_COMMAND:
|
|
||||||
handlePageSelectCommand(tsChannel, TS_CRC);
|
|
||||||
break;
|
|
||||||
case TS_CHUNK_WRITE_COMMAND:
|
|
||||||
handleWriteChunkCommand(tsChannel, TS_CRC, offset, count, data + sizeof(TunerStudioWriteChunkRequest));
|
|
||||||
break;
|
|
||||||
case TS_SINGLE_WRITE_COMMAND:
|
|
||||||
handleWriteValueCommand(tsChannel, TS_CRC, offset, data[4]);
|
|
||||||
break;
|
|
||||||
case TS_CRC_CHECK_COMMAND:
|
|
||||||
handleCrc32Check(tsChannel, TS_CRC, offset, count);
|
|
||||||
break;
|
|
||||||
case TS_BURN_COMMAND:
|
case TS_BURN_COMMAND:
|
||||||
handleBurnCommand(tsChannel, TS_CRC);
|
handleBurnCommand(tsChannel, TS_CRC);
|
||||||
break;
|
break;
|
||||||
case TS_READ_COMMAND:
|
|
||||||
handlePageReadCommand(tsChannel, TS_CRC, offset, count);
|
|
||||||
break;
|
|
||||||
case TS_TEST_COMMAND:
|
case TS_TEST_COMMAND:
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
case 'T':
|
case 'T':
|
||||||
handleTestCommand(tsChannel);
|
handleTestCommand(tsChannel);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
/* noone of simple commands */
|
||||||
|
handled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handled)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* check if we can extract page, offset and count */
|
||||||
|
if (incomingPacketSize < sizeof(TunerStudioDataPacketHeader)) {
|
||||||
|
sendErrorCode(tsChannel, TS_RESPONSE_UNDERRUN);
|
||||||
|
tunerStudioError(tsChannel, "ERROR: underrun");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TunerStudioDataPacketHeader* header = reinterpret_cast<TunerStudioDataPacketHeader*>(data);
|
||||||
|
|
||||||
|
switch(command)
|
||||||
|
{
|
||||||
|
case TS_OUTPUT_COMMAND:
|
||||||
|
tsState.outputChannelsCommandCounter++;
|
||||||
|
cmdOutputChannels(tsChannel, header->offset, header->count);
|
||||||
|
break;
|
||||||
|
case TS_CHUNK_WRITE_COMMAND:
|
||||||
|
if (header->page == 0)
|
||||||
|
handleWriteChunkCommand(tsChannel, TS_CRC, header->offset, header->count, data + sizeof(TunerStudioDataPacketHeader));
|
||||||
|
else
|
||||||
|
handleScatterListWriteCommand(tsChannel, header->offset, header->count, data + sizeof(TunerStudioDataPacketHeader));
|
||||||
|
break;
|
||||||
|
case TS_CRC_CHECK_COMMAND:
|
||||||
|
if (header->page == 0)
|
||||||
|
handleCrc32Check(tsChannel, TS_CRC, header->offset, header->count);
|
||||||
|
else
|
||||||
|
handleScatterListCrc32Check(tsChannel, header->offset, header->count);
|
||||||
|
break;
|
||||||
|
case TS_READ_COMMAND:
|
||||||
|
if (header->page == 0)
|
||||||
|
handlePageReadCommand(tsChannel, TS_CRC, header->offset, header->count);
|
||||||
|
else
|
||||||
|
handleScatterListReadCommand(tsChannel, header->offset, header->count);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
sendErrorCode(tsChannel, TS_RESPONSE_UNRECOGNIZED_COMMAND);
|
sendErrorCode(tsChannel, TS_RESPONSE_UNRECOGNIZED_COMMAND);
|
||||||
tunerStudioError(tsChannel, "ERROR: ignoring unexpected command");
|
tunerStudioError(tsChannel, "ERROR: ignoring unexpected command");
|
||||||
|
|
|
@ -16,8 +16,6 @@ typedef struct {
|
||||||
int outputChannelsCommandCounter;
|
int outputChannelsCommandCounter;
|
||||||
int readPageCommandsCounter;
|
int readPageCommandsCounter;
|
||||||
int burnCommandCounter;
|
int burnCommandCounter;
|
||||||
int pageCommandCounter;
|
|
||||||
int writeValueCommandCounter;
|
|
||||||
int crc32CheckCommandCounter;
|
int crc32CheckCommandCounter;
|
||||||
int writeChunkCommandCounter;
|
int writeChunkCommandCounter;
|
||||||
int errorCounter;
|
int errorCounter;
|
||||||
|
@ -36,9 +34,11 @@ void requestBurn(void);
|
||||||
void startTunerStudioConnectivity(void);
|
void startTunerStudioConnectivity(void);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
short int offset;
|
uint8_t cmd;
|
||||||
short int count;
|
uint16_t page;
|
||||||
} TunerStudioWriteChunkRequest;
|
uint16_t offset;
|
||||||
|
uint16_t count;
|
||||||
|
} __attribute__((packed)) TunerStudioDataPacketHeader;
|
||||||
|
|
||||||
#define CONNECTIVITY_THREAD_STACK (512)
|
#define CONNECTIVITY_THREAD_STACK (512)
|
||||||
#define CONNECTIVITY_THREAD_PRIO (NORMALPRIO + 1)
|
#define CONNECTIVITY_THREAD_PRIO (NORMALPRIO + 1)
|
||||||
|
|
|
@ -1,29 +1,18 @@
|
||||||
#include "tunerstudio_impl.h"
|
#include "tunerstudio_impl.h"
|
||||||
#include "tunerstudio.h"
|
#include "tunerstudio.h"
|
||||||
#include "tunerstudio_io.h"
|
#include "tunerstudio_io.h"
|
||||||
|
#include "byteswap.h"
|
||||||
|
|
||||||
/* configuration */
|
/* configuration */
|
||||||
#include "port.h"
|
#include "port.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include <rusefi/crc.h>
|
||||||
#include <rusefi/fragments.h>
|
#include <rusefi/fragments.h>
|
||||||
|
|
||||||
void sendErrorCode(TsChannelBase *tsChannel, uint8_t code);
|
void sendErrorCode(TsChannelBase *tsChannel, uint8_t code);
|
||||||
|
void sendOkResponse(TsChannelBase *tsChannel, ts_response_format_e mode);
|
||||||
size_t getTunerStudioPageSize() {
|
|
||||||
return GetConfigurationSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate whether the specified offset and count would cause an overrun in the tune.
|
|
||||||
// Returns true if an overrun would occur.
|
|
||||||
bool validateOffsetCount(size_t offset, size_t count, TsChannelBase* tsChannel) {
|
|
||||||
if (offset + count > getTunerStudioPageSize()) {
|
|
||||||
tunerStudioError(tsChannel, "ERROR: out of range");
|
|
||||||
sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
FragmentList getFragments();
|
FragmentList getFragments();
|
||||||
|
|
||||||
|
@ -48,3 +37,115 @@ void TunerStudio::cmdOutputChannels(TsChannelBase* tsChannel, uint16_t offset, u
|
||||||
|
|
||||||
tsChannel->crcAndWriteBuffer(TS_RESPONSE_OK, count);
|
tsChannel->crcAndWriteBuffer(TS_RESPONSE_OK, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate whether the specified offset and count would cause an overrun in the tune.
|
||||||
|
// Returns true if offset and count are in valid range
|
||||||
|
bool TunerStudio::validateScatterOffsetCount(size_t offset, size_t count) {
|
||||||
|
if (offset + count > sizeof(highSpeedOffsets))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TunerStudio::handleScatteredReadCommand(TsChannelBase* tsChannel) {
|
||||||
|
#ifdef HIGH_SPEED_OPTIMIZED
|
||||||
|
uint8_t *buffer = (uint8_t *)tsChannel->scratchBuffer;
|
||||||
|
tsChannel->writeHeader(TS_RESPONSE_OK, highSpeedTotalSize);
|
||||||
|
for (size_t i = 0; i < highSpeedChunks; i++) {
|
||||||
|
chDbgAssert(NULL != highSpeedPtrs[i], "NULL pointer in scatter list");
|
||||||
|
// copy to temp buffer to avoid changes before transmission, couse it can affect CRC
|
||||||
|
memcpy(buffer, highSpeedPtrs[i], highSpeedSizes[i]);
|
||||||
|
tsChannel->writeBody(buffer, highSpeedSizes[i]);
|
||||||
|
}
|
||||||
|
tsChannel->writeTail();
|
||||||
|
#else
|
||||||
|
size_t count = 0;
|
||||||
|
uint8_t *buffer = (uint8_t *)tsChannel->scratchBuffer + 3; /* reserve 3 bytes for header */
|
||||||
|
|
||||||
|
for (size_t i = 0; i < HIGH_SPEED_COUNT; i++) {
|
||||||
|
int packed = highSpeedOffsets[i];
|
||||||
|
int type = packed >> 13;
|
||||||
|
|
||||||
|
if (type == 0)
|
||||||
|
continue;
|
||||||
|
int size = 1 << (type - 1);
|
||||||
|
|
||||||
|
int offset = packed & 0x1FFF;
|
||||||
|
// write each data point and CRC incrementally
|
||||||
|
copyRange(buffer + count, getFragments(), offset, size);
|
||||||
|
count += size;
|
||||||
|
}
|
||||||
|
tsChannel->crcAndWriteBuffer(TS_RESPONSE_OK, count);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void TunerStudio::handleScatterListWriteCommand(TsChannelBase* tsChannel, uint16_t offset, uint16_t count, void *content)
|
||||||
|
{
|
||||||
|
uint8_t * addr = (uint8_t *)highSpeedOffsets + offset;
|
||||||
|
memcpy(addr, content, count);
|
||||||
|
|
||||||
|
#ifdef HIGH_SPEED_OPTIMIZED
|
||||||
|
highSpeedChunks = 0;
|
||||||
|
highSpeedTotalSize = 0;
|
||||||
|
/* translate to CPU pointers */
|
||||||
|
for (int i = 0; i < HIGH_SPEED_COUNT; i++) {
|
||||||
|
int packed = highSpeedOffsets[i];
|
||||||
|
int type = packed >> 13;
|
||||||
|
|
||||||
|
if (type == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int size = 1 << (type - 1);
|
||||||
|
int offset = packed & 0x1FFF;
|
||||||
|
highSpeedTotalSize += size;
|
||||||
|
|
||||||
|
uint8_t *ptr;
|
||||||
|
|
||||||
|
do {
|
||||||
|
size_t availSize = getRangePtr(&ptr, getFragments(), offset, size);
|
||||||
|
|
||||||
|
/* note: no need to check ptr for NULL */
|
||||||
|
if ((highSpeedChunks == 0) || /* first chunk */
|
||||||
|
((highSpeedChunks > 0) &&
|
||||||
|
(highSpeedPtrs[highSpeedChunks - 1] + highSpeedSizes[highSpeedChunks - 1] != ptr))) /* or not contiguous chunks */ {
|
||||||
|
highSpeedPtrs[highSpeedChunks] = ptr;
|
||||||
|
highSpeedSizes[highSpeedChunks] = size;
|
||||||
|
highSpeedChunks++;
|
||||||
|
} else {
|
||||||
|
/* unite */
|
||||||
|
highSpeedSizes[highSpeedChunks - 1] += size;
|
||||||
|
}
|
||||||
|
size -= availSize;
|
||||||
|
offset += availSize;
|
||||||
|
} while (size);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sendOkResponse(tsChannel, TS_CRC);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TunerStudio::handleScatterListReadCommand(TsChannelBase* tsChannel, uint16_t offset, uint16_t count)
|
||||||
|
{
|
||||||
|
if (!validateScatterOffsetCount(offset, count)) {
|
||||||
|
tunerStudioError(tsChannel, "ERROR: out of range");
|
||||||
|
sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t * addr = (uint8_t *)highSpeedOffsets + offset;
|
||||||
|
tsChannel->sendResponse(TS_CRC, addr, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TunerStudio::handleScatterListCrc32Check(TsChannelBase *tsChannel, uint16_t offset, uint16_t count)
|
||||||
|
{
|
||||||
|
// Ensure we are reading from in bounds
|
||||||
|
if (!validateScatterOffsetCount(offset, count)) {
|
||||||
|
tunerStudioError(tsChannel, "ERROR: out of range");
|
||||||
|
sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t* start = (uint8_t *)highSpeedOffsets + offset;
|
||||||
|
|
||||||
|
uint32_t crc = SWAP_UINT32(crc32(start, count));
|
||||||
|
tsChannel->sendResponse(TS_CRC, (const uint8_t *) &crc, 4);
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,10 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
|
#define HIGH_SPEED_COUNT 32
|
||||||
|
|
||||||
|
#define HIGH_SPEED_OPTIMIZED
|
||||||
|
|
||||||
struct TsChannelBase;
|
struct TsChannelBase;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -23,7 +27,7 @@ protected:
|
||||||
|
|
||||||
class TunerStudio : public TunerStudioBase {
|
class TunerStudio : public TunerStudioBase {
|
||||||
public:
|
public:
|
||||||
int handleCrcCommand(TsChannelBase* tsChannel, char *data, int incomingPacketSize);
|
int handleCrcCommand(TsChannelBase* tsChannel, char *data, size_t incomingPacketSize);
|
||||||
bool handlePlainCommand(TsChannelBase* tsChannel, uint8_t command);
|
bool handlePlainCommand(TsChannelBase* tsChannel, uint8_t command);
|
||||||
|
|
||||||
void cmdOutputChannels(TsChannelBase* tsChannel, uint16_t offset, uint16_t count) override;
|
void cmdOutputChannels(TsChannelBase* tsChannel, uint16_t offset, uint16_t count) override;
|
||||||
|
@ -35,7 +39,21 @@ public:
|
||||||
void handleCrc32Check(TsChannelBase *tsChannel, ts_response_format_e mode, uint16_t offset, uint16_t count);
|
void handleCrc32Check(TsChannelBase *tsChannel, ts_response_format_e mode, uint16_t offset, uint16_t count);
|
||||||
void handleWriteValueCommand(TsChannelBase* tsChannel, ts_response_format_e mode, uint16_t offset, uint8_t value);
|
void handleWriteValueCommand(TsChannelBase* tsChannel, ts_response_format_e mode, uint16_t offset, uint8_t value);
|
||||||
void handlePageReadCommand(TsChannelBase* tsChannel, ts_response_format_e mode, uint16_t offset, uint16_t count);
|
void handlePageReadCommand(TsChannelBase* tsChannel, ts_response_format_e mode, uint16_t offset, uint16_t count);
|
||||||
|
// Scatter mode support
|
||||||
|
void handleScatteredReadCommand(TsChannelBase* tsChannel);
|
||||||
|
void handleScatterListWriteCommand(TsChannelBase* tsChannel, uint16_t offset, uint16_t count, void *content);
|
||||||
|
void handleScatterListReadCommand(TsChannelBase* tsChannel, uint16_t offset, uint16_t count);
|
||||||
|
void handleScatterListCrc32Check(TsChannelBase *tsChannel, uint16_t offset, uint16_t count);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void sendErrorCode(TsChannelBase* tsChannel, uint8_t code);
|
void sendErrorCode(TsChannelBase* tsChannel, uint8_t code);
|
||||||
|
|
||||||
|
bool validateScatterOffsetCount(size_t offset, size_t count);
|
||||||
|
uint16_t highSpeedOffsets[HIGH_SPEED_COUNT];
|
||||||
|
#ifdef HIGH_SPEED_OPTIMIZED
|
||||||
|
uint8_t *highSpeedPtrs[HIGH_SPEED_COUNT];
|
||||||
|
size_t highSpeedSizes[HIGH_SPEED_COUNT];
|
||||||
|
size_t highSpeedChunks;
|
||||||
|
size_t highSpeedTotalSize;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
@ -56,6 +56,56 @@ void TsChannelBase::crcAndWriteBuffer(uint8_t responseCode, size_t size) {
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int TsChannelBase::writeHeader(uint8_t responseCode, size_t size)
|
||||||
|
{
|
||||||
|
uint8_t buffer[3];
|
||||||
|
|
||||||
|
// Index 0/1 = packet size (big endian)
|
||||||
|
*(uint16_t*)buffer = SWAP_UINT16(size + 1);
|
||||||
|
// Index 2 = response code
|
||||||
|
buffer[2] = responseCode;
|
||||||
|
|
||||||
|
// start calculating CRC
|
||||||
|
// CRC is computed on the responseCode and payload but not length
|
||||||
|
crcAcc = crc32(&buffer[2], sizeof(buffer) - 2);
|
||||||
|
// save packet size
|
||||||
|
packetSize = size; /* + 3 bytes for head + 4 bytes of CRC */
|
||||||
|
|
||||||
|
// Write to the underlying stream
|
||||||
|
write(buffer, sizeof(buffer), false);
|
||||||
|
|
||||||
|
return sizeof(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int TsChannelBase::writeBody(uint8_t *buffer, size_t size)
|
||||||
|
{
|
||||||
|
chDbgAssert(size <= packetSize, "writeBody packet size is more than provided in header");
|
||||||
|
// append CRC
|
||||||
|
crcAcc = crc32inc(buffer, crcAcc, size);
|
||||||
|
// adjust packet size
|
||||||
|
packetSize -= size;
|
||||||
|
|
||||||
|
// Write to the underlying stream
|
||||||
|
write(buffer, size, false);
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TsChannelBase::writeTail(void)
|
||||||
|
{
|
||||||
|
chDbgAssert(0 == packetSize, "writeTail unexpecded packet end");
|
||||||
|
|
||||||
|
uint8_t buffer[4];
|
||||||
|
|
||||||
|
// Place the CRC at the end
|
||||||
|
*(uint32_t*)buffer = SWAP_UINT32(crcAcc);
|
||||||
|
|
||||||
|
// Write to the underlying stream
|
||||||
|
write(buffer, sizeof(buffer), true);
|
||||||
|
|
||||||
|
return sizeof(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
void TsChannelBase::writeCrcPacketLarge(uint8_t responseCode, const uint8_t* buf, size_t size) {
|
void TsChannelBase::writeCrcPacketLarge(uint8_t responseCode, const uint8_t* buf, size_t size) {
|
||||||
uint8_t headerBuffer[3];
|
uint8_t headerBuffer[3];
|
||||||
uint8_t crcBuffer[4];
|
uint8_t crcBuffer[4];
|
||||||
|
|
|
@ -16,72 +16,19 @@
|
||||||
/* TODO: find better place */
|
/* TODO: find better place */
|
||||||
#define BLOCKING_FACTOR 256
|
#define BLOCKING_FACTOR 256
|
||||||
|
|
||||||
/* TODO: From autogenerated, rework! */
|
|
||||||
#define TS_BURN_COMMAND 'B'
|
#define TS_BURN_COMMAND 'B'
|
||||||
#define TS_BURN_COMMAND_char B
|
|
||||||
#define TS_CHUNK_WRITE_COMMAND 'C'
|
#define TS_CHUNK_WRITE_COMMAND 'C'
|
||||||
#define TS_CHUNK_WRITE_COMMAND_char C
|
|
||||||
#define ts_command_e_TS_BENCH_CATEGORY 22
|
|
||||||
#define ts_command_e_TS_CLEAR_WARNINGS 17
|
|
||||||
#define ts_command_e_TS_COMMAND_1 1
|
|
||||||
#define ts_command_e_TS_COMMAND_11 11
|
|
||||||
#define ts_command_e_TS_COMMAND_12 12
|
|
||||||
#define ts_command_e_TS_COMMAND_13 13
|
|
||||||
#define ts_command_e_TS_COMMAND_14 14
|
|
||||||
#define ts_command_e_TS_COMMAND_15 15
|
|
||||||
#define ts_command_e_TS_COMMAND_16 16
|
|
||||||
#define ts_command_e_TS_COMMAND_4 4
|
|
||||||
#define ts_command_e_TS_COMMAND_5 5
|
|
||||||
#define ts_command_e_TS_COMMAND_9 9
|
|
||||||
#define ts_command_e_TS_CRAZY 32
|
|
||||||
#define ts_command_e_TS_DEBUG_MODE 0
|
|
||||||
#define ts_command_e_TS_GRAB_PEDAL_UP 6
|
|
||||||
#define ts_command_e_TS_GRAB_PEDAL_WOT 7
|
|
||||||
#define ts_command_e_TS_GRAB_TPS_CLOSED 2
|
|
||||||
#define ts_command_e_TS_GRAB_TPS_WOT 3
|
|
||||||
#define ts_command_e_TS_IGNITION_CATEGORY 18
|
|
||||||
#define ts_command_e_TS_INJECTOR_CATEGORY 19
|
|
||||||
#define ts_command_e_TS_RESET_TLE8888 8
|
|
||||||
#define ts_command_e_TS_UNUSED_23 23
|
|
||||||
#define ts_command_e_TS_UNUSED_25 25
|
|
||||||
#define ts_command_e_TS_UNUSED_26 26
|
|
||||||
#define ts_command_e_TS_UNUSED_27 27
|
|
||||||
#define ts_command_e_TS_UNUSED_28 28
|
|
||||||
#define ts_command_e_TS_UNUSED_29 29
|
|
||||||
#define ts_command_e_TS_UNUSED_30 30
|
|
||||||
#define ts_command_e_TS_UNUSED_31 31
|
|
||||||
#define ts_command_e_TS_UNUSED_CJ125_CALIB 24
|
|
||||||
#define ts_command_e_TS_WIDEBAND 21
|
|
||||||
#define ts_command_e_TS_WRITE_FLASH 10
|
|
||||||
#define ts_command_e_TS_X14 20
|
|
||||||
#define TS_COMMAND_F 'F'
|
#define TS_COMMAND_F 'F'
|
||||||
#define TS_COMMAND_F_char F
|
|
||||||
#define TS_COMPOSITE_DISABLE 2
|
|
||||||
#define TS_COMPOSITE_ENABLE 1
|
|
||||||
#define TS_CRC_CHECK_COMMAND 'k'
|
#define TS_CRC_CHECK_COMMAND 'k'
|
||||||
#define TS_CRC_CHECK_COMMAND_char k
|
|
||||||
#define TS_FILE_VERSION 20210312
|
|
||||||
#define TS_GET_CONFIG_ERROR 'e'
|
|
||||||
#define TS_GET_CONFIG_ERROR_char e
|
|
||||||
#define TS_GET_FIRMWARE_VERSION 'V'
|
#define TS_GET_FIRMWARE_VERSION 'V'
|
||||||
#define TS_GET_FIRMWARE_VERSION_char V
|
|
||||||
#define TS_GET_LOGGER_GET_BUFFER 'L'
|
|
||||||
#define TS_GET_LOGGER_GET_BUFFER_char L
|
|
||||||
#define TS_GET_OUTPUTS_SIZE '4'
|
|
||||||
#define TS_GET_OUTPUTS_SIZE_char 4
|
|
||||||
#define TS_HELLO_COMMAND 'S'
|
#define TS_HELLO_COMMAND 'S'
|
||||||
#define TS_HELLO_COMMAND_char S
|
|
||||||
#define TS_ONLINE_PROTOCOL 'z'
|
|
||||||
#define TS_ONLINE_PROTOCOL_char z
|
|
||||||
#define TS_OUTPUT_COMMAND 'O'
|
#define TS_OUTPUT_COMMAND 'O'
|
||||||
#define TS_OUTPUT_COMMAND_char O
|
|
||||||
#define TS_PAGE_COMMAND 'P'
|
|
||||||
#define TS_PAGE_COMMAND_char P
|
|
||||||
#define TS_PROTOCOL "001"
|
#define TS_PROTOCOL "001"
|
||||||
#define TS_QUERY_COMMAND 'Q'
|
#define TS_QUERY_COMMAND 'Q'
|
||||||
#define TS_QUERY_COMMAND_char Q
|
|
||||||
#define TS_READ_COMMAND 'R'
|
#define TS_READ_COMMAND 'R'
|
||||||
#define TS_READ_COMMAND_char R
|
#define TS_TEST_COMMAND 't'
|
||||||
|
#define TS_GET_SCATTERED_GET_COMMAND '9'
|
||||||
|
|
||||||
#define TS_RESPONSE_BURN_OK 4
|
#define TS_RESPONSE_BURN_OK 4
|
||||||
#define TS_RESPONSE_COMMAND_OK 7
|
#define TS_RESPONSE_COMMAND_OK 7
|
||||||
#define TS_RESPONSE_CRC_FAILURE 0x82
|
#define TS_RESPONSE_CRC_FAILURE 0x82
|
||||||
|
@ -90,10 +37,6 @@
|
||||||
#define TS_RESPONSE_OUT_OF_RANGE 0x84
|
#define TS_RESPONSE_OUT_OF_RANGE 0x84
|
||||||
#define TS_RESPONSE_UNDERRUN 0x80
|
#define TS_RESPONSE_UNDERRUN 0x80
|
||||||
#define TS_RESPONSE_UNRECOGNIZED_COMMAND 0x83
|
#define TS_RESPONSE_UNRECOGNIZED_COMMAND 0x83
|
||||||
#define TS_SINGLE_WRITE_COMMAND 'W'
|
|
||||||
#define TS_SINGLE_WRITE_COMMAND_char W
|
|
||||||
#define TS_TEST_COMMAND 't'
|
|
||||||
#define TS_TEST_COMMAND_char t
|
|
||||||
|
|
||||||
class TsChannelBase {
|
class TsChannelBase {
|
||||||
public:
|
public:
|
||||||
|
@ -127,8 +70,16 @@ public:
|
||||||
void crcAndWriteBuffer(uint8_t responseCode, size_t size);
|
void crcAndWriteBuffer(uint8_t responseCode, size_t size);
|
||||||
void copyAndWriteSmallCrcPacket(uint8_t responseCode, const uint8_t* buf, size_t size);
|
void copyAndWriteSmallCrcPacket(uint8_t responseCode, const uint8_t* buf, size_t size);
|
||||||
|
|
||||||
|
int writeHeader(uint8_t responseCode, size_t size);
|
||||||
|
int writeBody(uint8_t *buffer, size_t size);
|
||||||
|
int writeTail(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void writeCrcPacketLarge(uint8_t responseCode, const uint8_t* buf, size_t size);
|
void writeCrcPacketLarge(uint8_t responseCode, const uint8_t* buf, size_t size);
|
||||||
|
// CRC accumulator
|
||||||
|
uint32_t crcAcc;
|
||||||
|
// total size expected
|
||||||
|
size_t packetSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This class represents a channel for a physical async serial poart
|
// This class represents a channel for a physical async serial poart
|
||||||
|
|
|
@ -30,15 +30,14 @@ enable2ndByteCanID = false
|
||||||
messageEnvelopeFormat = msEnvelope_1.0
|
messageEnvelopeFormat = msEnvelope_1.0
|
||||||
|
|
||||||
endianness = little
|
endianness = little
|
||||||
nPages = 1
|
nPages = 2
|
||||||
|
pageSize = 256, 64
|
||||||
|
pageIdentifier = "\x00\x00", "\x00\x01"
|
||||||
|
|
||||||
pageIdentifier = "\x00\x00"
|
pageReadCommand = "R%2i%2o%2c", "R%2i%2o%2c"
|
||||||
pageReadCommand = "R%2o%2c"
|
burnCommand = "B%2i"
|
||||||
burnCommand = "B"
|
pageChunkWrite = "C%2i%2o%2c%v", "C%2i%2o%2c%v"
|
||||||
pageActivate = "P"
|
crc32CheckCommand = "k%2i%2o%2c", "k%2i%2o%2c"
|
||||||
pageValueWrite = "W%2o%v"
|
|
||||||
pageChunkWrite = "C%2o%2c%v"
|
|
||||||
crc32CheckCommand = "k%2o%2c"
|
|
||||||
retrieveConfigError = "e"
|
retrieveConfigError = "e"
|
||||||
|
|
||||||
; communication settings
|
; communication settings
|
||||||
|
@ -57,13 +56,16 @@ enable2ndByteCanID = false
|
||||||
|
|
||||||
; CONFIG_DEFINITION_START
|
; CONFIG_DEFINITION_START
|
||||||
|
|
||||||
pageSize = 256
|
|
||||||
page = 1
|
page = 1
|
||||||
|
|
||||||
; name = class, type, offset, [shape], units, scale, translate, min, max, digits
|
; name = class, type, offset, [shape], units, scale, translate, min, max, digits
|
||||||
; First four bytes are used for internal tag. Should not be accessable from TS
|
; First four bytes are used for internal tag. Should not be accessable from TS
|
||||||
LsuSensorType = bits, U08, 135, [0:2], "LSU 4.9", "LSU 4.2", "LSU ADV"
|
LsuSensorType = bits, U08, 135, [0:2], "LSU 4.9", "LSU 4.2", "LSU ADV"
|
||||||
|
|
||||||
|
page = 2 ; this is a RAM only page with no burnable flash
|
||||||
|
; name = class, type, offset, [shape], units, scale, translate, min, max, digits
|
||||||
|
highSpeedOffsets = array, U16, 0, [32], "", 1, 0, 0, 65535, 0, noMsqSave
|
||||||
|
|
||||||
[SettingContextHelp]
|
[SettingContextHelp]
|
||||||
|
|
||||||
[Tuning]
|
[Tuning]
|
||||||
|
@ -71,10 +73,16 @@ LsuSensorType = bits, U08, 135, [0:2], "LSU 4.9", "LSU 4.2", "LSU ADV"
|
||||||
[LoggerDefinition]
|
[LoggerDefinition]
|
||||||
|
|
||||||
[OutputChannels]
|
[OutputChannels]
|
||||||
ochGetCommand = "O%2o%2c"
|
; two zero bytes added after cmd byte to align with page read/write format
|
||||||
|
ochGetCommand = "O\x00\x00%2o%2c"
|
||||||
; see TS_OUTPUT_SIZE in console source code
|
; see TS_OUTPUT_SIZE in console source code
|
||||||
ochBlockSize = 256
|
ochBlockSize = 256
|
||||||
|
|
||||||
|
; 11.2.3 Full Optimized – High Speed
|
||||||
|
scatteredOchGetCommand = "9"
|
||||||
|
scatteredOffsetArray = highSpeedOffsets
|
||||||
|
scatteredGetEnabled = { 1 }
|
||||||
|
|
||||||
; Common
|
; Common
|
||||||
VBatt = scalar, F32, 0, "V", 1, 0
|
VBatt = scalar, F32, 0, "V", 1, 0
|
||||||
|
|
||||||
|
|
|
@ -30,15 +30,14 @@ enable2ndByteCanID = false
|
||||||
messageEnvelopeFormat = msEnvelope_1.0
|
messageEnvelopeFormat = msEnvelope_1.0
|
||||||
|
|
||||||
endianness = little
|
endianness = little
|
||||||
nPages = 1
|
nPages = 2
|
||||||
|
pageSize = 256, 64
|
||||||
|
pageIdentifier = "\x00\x00", "\x00\x01"
|
||||||
|
|
||||||
pageIdentifier = "\x00\x00"
|
pageReadCommand = "R%2i%2o%2c", "R%2i%2o%2c"
|
||||||
pageReadCommand = "R%2o%2c"
|
burnCommand = "B%2i"
|
||||||
burnCommand = "B"
|
pageChunkWrite = "C%2i%2o%2c%v", "C%2i%2o%2c%v"
|
||||||
pageActivate = "P"
|
crc32CheckCommand = "k%2i%2o%2c", "k%2i%2o%2c"
|
||||||
pageValueWrite = "W%2o%v"
|
|
||||||
pageChunkWrite = "C%2o%2c%v"
|
|
||||||
crc32CheckCommand = "k%2o%2c"
|
|
||||||
retrieveConfigError = "e"
|
retrieveConfigError = "e"
|
||||||
|
|
||||||
; communication settings
|
; communication settings
|
||||||
|
@ -57,7 +56,6 @@ enable2ndByteCanID = false
|
||||||
|
|
||||||
; CONFIG_DEFINITION_START
|
; CONFIG_DEFINITION_START
|
||||||
|
|
||||||
pageSize = 256
|
|
||||||
page = 1
|
page = 1
|
||||||
|
|
||||||
; name = class, type, offset, [shape], units, scale, translate, min, max, digits
|
; name = class, type, offset, [shape], units, scale, translate, min, max, digits
|
||||||
|
@ -71,6 +69,10 @@ Aux0InputSel = bits, U08, 133, [0:3], "AFR 0", "AFR 1", "Lambda 0", "L
|
||||||
Aux1InputSel = bits, U08, 134, [0:3], "AFR 0", "AFR 1", "Lambda 0", "Lambda 1", "EGT 0", "EGT 1"
|
Aux1InputSel = bits, U08, 134, [0:3], "AFR 0", "AFR 1", "Lambda 0", "Lambda 1", "EGT 0", "EGT 1"
|
||||||
LsuSensorType = bits, U08, 135, [0:2], "LSU 4.9", "LSU 4.2", "LSU ADV"
|
LsuSensorType = bits, U08, 135, [0:2], "LSU 4.9", "LSU 4.2", "LSU ADV"
|
||||||
|
|
||||||
|
page = 2 ; this is a RAM only page with no burnable flash
|
||||||
|
; name = class, type, offset, [shape], units, scale, translate, min, max, digits
|
||||||
|
highSpeedOffsets = array, U16, 0, [32], "", 1, 0, 0, 65535, 0, noMsqSave
|
||||||
|
|
||||||
[SettingContextHelp]
|
[SettingContextHelp]
|
||||||
|
|
||||||
[Tuning]
|
[Tuning]
|
||||||
|
@ -78,10 +80,16 @@ LsuSensorType = bits, U08, 135, [0:2], "LSU 4.9", "LSU 4.2", "LSU ADV"
|
||||||
[LoggerDefinition]
|
[LoggerDefinition]
|
||||||
|
|
||||||
[OutputChannels]
|
[OutputChannels]
|
||||||
ochGetCommand = "O%2o%2c"
|
; two zero bytes added after cmd byte to align with page read/write format
|
||||||
|
ochGetCommand = "O\x00\x00%2o%2c"
|
||||||
; see TS_OUTPUT_SIZE in console source code
|
; see TS_OUTPUT_SIZE in console source code
|
||||||
ochBlockSize = 256
|
ochBlockSize = 256
|
||||||
|
|
||||||
|
; 11.2.3 Full Optimized – High Speed
|
||||||
|
scatteredOchGetCommand = "9"
|
||||||
|
scatteredOffsetArray = highSpeedOffsets
|
||||||
|
scatteredGetEnabled = { 1 }s
|
||||||
|
|
||||||
; Common
|
; Common
|
||||||
VBatt = scalar, F32, 0, "V", 1, 0
|
VBatt = scalar, F32, 0, "V", 1, 0
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 16a8e0b636f0a8d5f88dfdd6a1a4639ad90da936
|
Subproject commit 39b3a04dab617e7ff24577e99d0d7fac2ce44c9f
|
Loading…
Reference in New Issue