New Comms change to prevent lockup during large table writes

This commit is contained in:
Josh Stewart 2022-01-07 16:49:04 +11:00
parent 76f6a7f1d5
commit 300c8699cc
5 changed files with 101 additions and 55 deletions

View File

@ -90,7 +90,7 @@
#define fullStatus_def_6= "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
#define fullStatus_def_7= "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
;Rules start at index 240
#define fullStatus_def_8= "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "running seconds x10", "Rule 1", "Rule 2", "Rule 3", "Rule 4", "Rule 5", "Rule 6", "Rule 7", "Rule 8", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
#define fullStatus_def_8= "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "running seconds x10", "Rule 1", "Rule 2", "Rule 3", "Rule 4", "Rule 5", "Rule 6", "Rule 7", "Rule 8", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
#define fullStatus_def = $fullStatus_def_1, $fullStatus_def_2, $fullStatus_def_3, $fullStatus_def_4, $fullStatus_def_5, $fullStatus_def_6, $fullStatus_def_7, $fullStatus_def_8
boostTableLabels = bits, U08, [0:1], "Duty Cycle %", "kPa"
@ -215,14 +215,14 @@
pageChunkWrite = "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v"
crc32CheckCommand = "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i"
blockingFactor = 256
blockingFactor = 251 ; Serial buffer is 257 bytes and there are 6 bytes of overhead (2 for the size and 4 for the CRC). Total paload is therefore 257-6=251.
;tableBlockingFactor = 2048
tableBlockingFactor = 256
tableBlockingFactor = 244 ; Serial buffer is 257 bytes. There are 7 bytes overhead for the M command + 2 bytes for the size + 4 bytes for the CRC. 257 - 7 - 2 - 4 = 244 bytes.
delayAfterPortOpen=1000
;validateArrayBounds = true
blockReadTimeout = 2000
tsWriteBlocks = on
interWriteDelay = 1 ;Ignored when tsWriteBlocks is on
interWriteDelay = 10 ;Ignored when tsWriteBlocks is on
pageActivationDelay = 10
restrictSquirtRelationship = false ;This requires TS 3.1 or above
#if NEW_COMMS
@ -1251,7 +1251,7 @@ page = 13
outputPin6 = bits, U08, 8, [0:7], $comp_IO_Pins
outputPin7 = bits, U08, 9, [0:7], $comp_IO_Pins
outputDelay = array, U08, 10, [ 8], "S", 0.1, 0.0, 0.0, 25.5, 1
firstDataIn = array, U08, 18, [ 8], "", 1.0, 0.0, 0.0, 65535.0, 0
firstDataIn = array, U08, 18, [ 8], "", 1.0, 0.0, 0.0, 255.0, 0
firstDataIn0= bits, U08, 18, [0:7], $fullStatus_def
firstDataIn1= bits, U08, 19, [0:7], $fullStatus_def
firstDataIn2= bits, U08, 20, [0:7], $fullStatus_def
@ -1260,7 +1260,7 @@ page = 13
firstDataIn5= bits, U08, 23, [0:7], $fullStatus_def
firstDataIn6= bits, U08, 24, [0:7], $fullStatus_def
firstDataIn7= bits, U08, 25, [0:7], $fullStatus_def
secondDataIn = array, U08, 26, [ 8], "", 1.0, 0.0, 0.0, 65535.0, 0
secondDataIn = array, U08, 26, [ 8], "", 1.0, 0.0, 0.0, 255.0, 0
secondDataIn0= bits, U08, 26, [0:7], $fullStatus_def
secondDataIn1= bits, U08, 27, [0:7], $fullStatus_def
secondDataIn2= bits, U08, 28, [0:7], $fullStatus_def

View File

@ -547,6 +547,8 @@ void command()
break;
default:
Serial.println(F("Err: Unknown cmd"));
cmdPending = false;
break;
}
}

View File

@ -234,6 +234,14 @@ void processSerialCommand()
break;
case 'b': // New EEPROM burn command to only burn a single page at a time
if(isEepromWritePending())
{
//There is already a write pending, so we can't do anything
sendSerialReturnCode(SERIAL_RC_BUSY_ERR);
break;
}
writeConfig(serialPayload[2]); //Read the table number and perform burn. Note that byte 1 in the array is unused
sendSerialReturnCode(SERIAL_RC_BURN_OK);
break;
@ -245,6 +253,25 @@ void processSerialCommand()
break;
}
case 'd': // Send a CRC32 hash of a given page
{
uint32_t CRC32_val = calculatePageCRC32( serialPayload[2] );
uint8_t payloadCRC32[5];
//First byte is the flag
payloadCRC32[0] = SERIAL_RC_OK;
//Split the 4 bytes of the CRC32 value into individual bytes and send
payloadCRC32[1] = ((CRC32_val >> 24) & 255);
payloadCRC32[2] = ((CRC32_val >> 16) & 255);
payloadCRC32[3] = ((CRC32_val >> 8) & 255);
payloadCRC32[4] = (CRC32_val & 255);
sendSerialPayload( &payloadCRC32, 5);
break;
}
case 'E': // receive command button commands
{
uint16_t cmdCombined = word(serialPayload[1], serialPayload[2]);
@ -309,6 +336,13 @@ void processSerialCommand()
sendSerialReturnCode(SERIAL_RC_OK);
break;
case 'I': // send CAN ID
{
byte serialVersion[] = {SERIAL_RC_OK, 0};
sendSerialPayload(&serialVersion, 2);
break;
}
case 'J': //Start the composite logger
currentStatus.compositeLogEnabled = true;
currentStatus.toothLogEnabled = false; //Safety first (Should never be required)
@ -337,25 +371,54 @@ void processSerialCommand()
sendSerialReturnCode(SERIAL_RC_OK);
break;
case 'd': // Send a CRC32 hash of a given page
case 'M':
{
uint32_t CRC32_val = calculatePageCRC32( serialPayload[2] );
uint8_t payloadCRC32[5];
//First byte is the flag
payloadCRC32[0] = SERIAL_RC_OK;
//New write command
//7 bytes required:
//2 - Page identifier
//2 - offset
//2 - Length
//1 - 1st New value
byte offset1, offset2, length1, length2;
//Split the 4 bytes of the CRC32 value into individual bytes and send
payloadCRC32[1] = ((CRC32_val >> 24) & 255);
payloadCRC32[2] = ((CRC32_val >> 16) & 255);
payloadCRC32[3] = ((CRC32_val >> 8) & 255);
payloadCRC32[4] = (CRC32_val & 255);
sendSerialPayload( &payloadCRC32, 5);
uint8_t currentPage = serialPayload[2]; //Page ID is 2 bytes, but as the first byte is always 0 it can be ignored
offset1 = serialPayload[3];
offset2 = serialPayload[4];
uint16_t valueOffset = word(offset2, offset1);
length1 = serialPayload[5];
length2 = serialPayload[6];
uint16_t chunkSize = word(length2, length1);
if( (valueOffset + chunkSize) > getPageSize(currentPage))
{
//This should never happen, but just incase
sendSerialReturnCode(SERIAL_RC_RANGE_ERR);
break;
}
if(isEepromWritePending())
{
enableForceBurn();
writeConfig(currentPage);
disableForceBurn();
}
//page_iterator_t entity = map_page_offset_to_entity(currentPage, valueOffset);
for(uint16_t i = 0; i < chunkSize; i++)
{
setPageValue(currentPage, (valueOffset + i), serialPayload[7 + i]);
}
{
//enableForceBurn();
writeConfig(currentPage);
//disableForceBurn();
}
sendSerialReturnCode(SERIAL_RC_OK);
break;
}
}
/*
* New method for sending page values (MS command equivalent is 'r')
@ -661,33 +724,6 @@ void processSerialCommand()
}
break;
case 'M':
{
//New write command
//7 bytes required:
//2 - Page identifier
//2 - offset
//2 - Length
//1 - 1st New value
byte offset1, offset2, length1, length2;
uint8_t currentPage = serialPayload[2];
offset1 = serialPayload[3];
offset2 = serialPayload[4];
uint16_t valueOffset = word(offset2, offset1);
length1 = serialPayload[5];
length2 = serialPayload[6];
uint16_t chunkSize = word(length2, length1);
for(uint16_t i = 0; i < chunkSize; i++)
{
setPageValue(currentPage, (valueOffset + i), serialPayload[7 + i]);
}
sendSerialReturnCode(SERIAL_RC_OK);
break;
}
case 'w':
{
#ifdef RTC_ENABLED
@ -808,6 +844,8 @@ void processSerialCommand()
}
default:
//Unknown command
sendSerialReturnCode(SERIAL_RC_UKWN_ERR);
break;
}
}

View File

@ -32,6 +32,7 @@ A full copy of the license may be found in the projects root directory
#define EEPROM_LAST_BARO (EEPROM_CALIBRATION_O2_BINS-1)
static bool eepromWritesPending = false;
static bool forceBurn = false;
bool isEepromWritePending()
{
@ -45,18 +46,20 @@ void writeAllConfig()
uint8_t pageCount = getPageCount();
uint8_t page = 1U;
writeConfig(page++);
while (page<pageCount && !eepromWritesPending)
while (page<pageCount && ( !eepromWritesPending || forceBurn ) )
{
writeConfig(page++);
}
}
void enableForceBurn() { forceBurn = true; }
void disableForceBurn() { forceBurn = false; }
// ================================= Internal write support ===============================
struct write_location {
eeprom_address_t address;
uint8_t counter;
uint16_t counter;
/** Update byte to EEPROM by first comparing content and the need to write it.
We only ever write to the EEPROM where the new value is different from the currently stored byte
@ -79,13 +82,14 @@ struct write_location {
bool can_write() const
{
return counter<=EEPROM_MAX_WRITE_BLOCK;
//return true;
return (counter<=EEPROM_MAX_WRITE_BLOCK);
}
};
static inline write_location write_range(const byte *pStart, const byte *pEnd, write_location location)
{
while (location.can_write() && pStart!=pEnd)
while ( (location.can_write() || forceBurn) && pStart!=pEnd)
{
location.update(*pStart);
++pStart;
@ -101,7 +105,7 @@ static inline write_location write(const table_row_iterator &row, write_location
static inline write_location write(table_value_iterator it, write_location location)
{
while (location.can_write() && !it.at_end())
while ((location.can_write() || forceBurn) && !it.at_end())
{
location = write(*it, location);
++it;
@ -111,7 +115,7 @@ static inline write_location write(table_value_iterator it, write_location locat
static inline write_location write(table_axis_iterator it, write_location location)
{
while (location.can_write() && !it.at_end())
while ((location.can_write() || forceBurn) && !it.at_end())
{
location.update((byte)*it);
++location;

View File

@ -114,6 +114,8 @@ void loadConfig();
void loadCalibration();
void writeCalibration();
void resetConfigPages();
void enableForceBurn();
void disableForceBurn();
//These are utility functions that prevent other files from having to use EEPROM.h directly
byte readLastBaro();