Fix & optimize FW version parsing and checking

PFW-1433
This commit is contained in:
D.R.racer 2022-11-23 11:59:10 +01:00 committed by DRracer
parent 12f6f34cf4
commit a03183723c
2 changed files with 151 additions and 124 deletions

View file

@ -10,7 +10,24 @@
// Allocate the version string in the program memory. Otherwise the string lands either on the stack or in the global RAM.
static const char FW_VERSION_STR[] PROGMEM = FW_VERSION;
static const uint16_t FW_VERSION_NR[4] PROGMEM = { FW_MAJOR, FW_MINOR, FW_REVISION, FW_COMMIT_NR };
static const uint16_t FW_VERSION_NR[4] PROGMEM = {
FW_MAJOR,
FW_MINOR,
FW_REVISION,
#ifndef FW_FLAVOR
FW_COMMIT_NR
#else
# if FW_DEV_VERSION == FW_VERSION_ALPHA
FIRMWARE_REVISION_ALPHA + FW_FLAVERSION
# elif FW_DEV_VERSION == FW_VERSION_BETA
FIRMWARE_REVISION_BETA + FW_FLAVERSION
# elif FW_DEV_VERSION == FW_VERSION_RC
FIRMWARE_REVISION_RC + FW_FLAVERSION
# elif FW_DEV_VERSION == FW_VERSION_GOLD
0
# endif
#endif
};
const char* FW_VERSION_STR_P()
{
@ -24,10 +41,10 @@ const char* FW_PRUSA3D_MAGIC_STR_P()
return FW_PRUSA3D_MAGIC_STR;
}
const char STR_REVISION_DEV [] PROGMEM = "dev";
const char STR_REVISION_ALPHA[] PROGMEM = "alpha";
const char STR_REVISION_BETA [] PROGMEM = "beta";
const char STR_REVISION_RC [] PROGMEM = "rc";
const char STR_REVISION_DEV [] PROGMEM = "DEV";
const char STR_REVISION_ALPHA[] PROGMEM = "ALPHA";
const char STR_REVISION_BETA [] PROGMEM = "BETA";
const char STR_REVISION_RC [] PROGMEM = "RC";
inline bool is_whitespace_or_nl(char c)
{
@ -44,78 +61,84 @@ inline bool is_digit(char c)
return c >= '0' && c <= '9';
}
char const * __attribute__((noinline)) Number(char const *str, uint16_t *v){
*v = 0;
while(is_digit(*str)){
*v *= 10;
*v += *str - '0';
++str;
}
return str;
}
bool __attribute__((noinline)) Tag(const char *str, const char *tag_P, uint8_t tagSize, uint16_t tagMask, uint16_t *v){
if( ! strncmp_P(str, tag_P, tagSize) ){
Number(str + tagSize, v);
*v |= tagMask;
return true;
}
return false;
}
// Parse a major.minor.revision version number.
// Return true if valid.
inline bool parse_version(const char *str, uint16_t version[4])
{
#if 0
SERIAL_ECHOPGM("Parsing version string ");
SERIAL_ECHO(str);
SERIAL_ECHOLNPGM("");
#endif
const char *major = str;
const char *p = str;
while (is_digit(*p)) ++ p;
if (*p != '.')
return false;
const char *minor = ++ p;
while (is_digit(*p)) ++ p;
if (*p != '.')
return false;
const char *rev = ++ p;
while (is_digit(*p)) ++ p;
if (! is_whitespace_or_nl_or_eol(*p) && *p != '-')
return false;
char *endptr = NULL;
version[0] = strtol(major, &endptr, 10);
if (endptr != minor - 1)
return false;
version[1] = strtol(minor, &endptr, 10);
if (endptr != rev - 1)
return false;
version[2] = strtol(rev, &endptr, 10);
if (endptr != p)
return false;
bool parse_version(const char *str, uint16_t version[4]) {
for(uint8_t i = 0; i < 2; ++i){
str = Number(str, version + i);
if (*str != '.')
return false;
++str;
}
str = Number(str, version + 2);
version[3] = FIRMWARE_REVISION_RELEASED;
if (*p ++ == '-') {
const char *q = p;
while (! is_whitespace_or_nl_or_eol(*q))
++ q;
uint8_t n = q - p;
if (n == strlen_P(STR_REVISION_DEV) && strncmp_P(p, STR_REVISION_DEV, n) == 0)
version[3] = FIRMWARE_REVISION_DEV;
else if (n == strlen_P(STR_REVISION_ALPHA) && strncmp_P(p, STR_REVISION_ALPHA, n) == 0)
version[3] = FIRMWARE_REVISION_ALPHA;
else if (n == strlen_P(STR_REVISION_BETA) && strncmp_P(p, STR_REVISION_BETA, n) == 0)
version[3] = FIRMWARE_REVISION_BETA;
else if ((n == 2 || n == 3) && (p[0] == 'r' || p[0] == 'R') && (p[1] == 'c' || p[1] == 'C')) {
if (n == 2)
version[3] = FIRMWARE_REVISION_RC;
else {
if (is_digit(p[2]))
version[3] = FIRMWARE_REVISION_RC + p[2] - '1';
else
return false;
}
} else
return false;
// skip everything else until eol or '-'
for(;;){
if(is_whitespace_or_nl_or_eol(*str)){
// speculatively reached the end of line, silently ignoring anything which is not a '-'
return true;
}
if( *str == '-'){
break; // tag expected
}
++str;
}
#if 0
SERIAL_ECHOPGM("Version parsed, major: ");
SERIAL_ECHO(version[0]);
SERIAL_ECHOPGM(", minor: ");
SERIAL_ECHO(version[1]);
SERIAL_ECHOPGM(", revision: ");
SERIAL_ECHO(version[2]);
SERIAL_ECHOPGM(", flavor: ");
SERIAL_ECHO(version[3]);
SERIAL_ECHOLNPGM("");
#endif
return true;
// SERIAL_ECHOPGM("parse_version: ");
// SERIAL_ECHO(version[0]);
// SERIAL_ECHO('.');
// SERIAL_ECHO(version[1]);
// SERIAL_ECHO('.');
// SERIAL_ECHO(version[2]);
// SERIAL_ECHO('.');
// SERIAL_ECHOLN(version[3]);
if (*str++ == '-') {
switch(*str){
case 'A': // expect ALPHA
static_assert(sizeof(STR_REVISION_ALPHA) == 6);
return Tag( str, STR_REVISION_ALPHA, sizeof(STR_REVISION_ALPHA) - 1, FIRMWARE_REVISION_ALPHA, version + 3);
case 'B': // expect BETA
static_assert(sizeof(STR_REVISION_BETA) == 5);
return Tag( str, STR_REVISION_BETA, sizeof(STR_REVISION_BETA) - 1, FIRMWARE_REVISION_BETA, version + 3);
case 'D': // expect DEV
static_assert(sizeof(STR_REVISION_DEV) == 4);
return Tag( str, STR_REVISION_DEV, sizeof(STR_REVISION_DEV) - 1, FIRMWARE_REVISION_DEV, version + 3);
case 'R': // expect RC
static_assert(sizeof(STR_REVISION_RC) == 3);
return Tag( str, STR_REVISION_RC, sizeof(STR_REVISION_RC) - 1, FIRMWARE_REVISION_RC, version + 3);
default: return false; // fail everything else
}
}
// SERIAL_ECHOPGM("parse_version with tag: ");
// SERIAL_ECHO(version[0]);
// SERIAL_ECHO('.');
// SERIAL_ECHO(version[1]);
// SERIAL_ECHO('.');
// SERIAL_ECHO(version[2]);
// SERIAL_ECHO('.');
// SERIAL_ECHOLN(version[3]);
return false;
}
inline bool strncmp_PP(const char *p1, const char *p2, uint8_t n)
@ -227,7 +250,6 @@ void update_current_firmware_version_to_eeprom()
}
//-//
#define MSG_PRINT_CHECKING_FAILED_TIMEOUT 30
ClNozzleDiameter oNozzleDiameter=ClNozzleDiameter::_Diameter_400;
@ -347,8 +369,7 @@ lcd_update_enable(true); // display / status-line recovery
}
}
uint8_t mCompareValue(uint16_t nX,uint16_t nY)
{
uint8_t mCompareValue(uint16_t nX, uint16_t nY) {
if(nX>nY)
return((uint8_t)ClCompareValue::_Greater);
if(nX<nY)
@ -356,45 +377,57 @@ if(nX<nY)
return((uint8_t)ClCompareValue::_Equal);
}
void fw_version_check(const char *pVersion)
{
uint16_t aVersion[4];
uint8_t nCompareValueResult;
void fw_version_check(const char *pVersion) {
uint16_t aVersion[4];
uint8_t nCompareValueResult;
if(oCheckVersion==ClCheckVersion::_None)
return;
parse_version(pVersion,aVersion);
nCompareValueResult=mCompareValue(aVersion[0],eeprom_read_word((uint16_t*)EEPROM_FIRMWARE_VERSION_MAJOR))<<6;
nCompareValueResult+=mCompareValue(aVersion[1],eeprom_read_word((uint16_t*)EEPROM_FIRMWARE_VERSION_MINOR))<<4;
nCompareValueResult+=mCompareValue(aVersion[2],eeprom_read_word((uint16_t*)EEPROM_FIRMWARE_VERSION_REVISION))<<2;
nCompareValueResult+=mCompareValue(aVersion[3],eeprom_read_word((uint16_t*)EEPROM_FIRMWARE_VERSION_FLAVOR));
if(nCompareValueResult==COMPARE_VALUE_EQUAL)
return;
if((nCompareValueResult<COMPARE_VALUE_EQUAL)&&oCheckVersion==ClCheckVersion::_Warn)
return;
//SERIAL_ECHO_START;
//SERIAL_ECHOLNPGM("Printer FW version differs from the G-code ...");
//SERIAL_ECHOPGM("actual : ");
//SERIAL_ECHOLN(FW_VERSION);
//SERIAL_ECHOPGM("expected: ");
//SERIAL_ECHOLN(pVersion);
switch(oCheckVersion)
{
case ClCheckVersion::_Warn:
// lcd_show_fullscreen_message_and_wait_P(_i("Printer FW version differs from the G-code. Continue?"));
lcd_display_message_fullscreen_P(_i("G-code sliced for a newer firmware. Continue?"));////MSG_GCODE_NEWER_FIRMWARE_CONTINUE c=20 r=5
lcd_wait_for_click_delay(MSG_PRINT_CHECKING_FAILED_TIMEOUT);
//???custom_message_type=CUSTOM_MSG_TYPE_STATUS; // display / status-line recovery
lcd_update_enable(true); // display / status-line recovery
break;
case ClCheckVersion::_Strict:
lcd_show_fullscreen_message_and_wait_P(_i("G-code sliced for a newer firmware. Please update the firmware. Print cancelled."));////MSG_GCODE_NEWER_FIRMWARE_CANCELLED c=20 r=8
lcd_print_stop();
break;
case ClCheckVersion::_None:
case ClCheckVersion::_Undef:
break;
}
if (oCheckVersion == ClCheckVersion::_None)
return;
parse_version(pVersion, aVersion);
nCompareValueResult = mCompareValue(aVersion[0], eeprom_read_word((uint16_t *)EEPROM_FIRMWARE_VERSION_MAJOR)) << 6;
nCompareValueResult += mCompareValue(aVersion[1], eeprom_read_word((uint16_t *)EEPROM_FIRMWARE_VERSION_MINOR)) << 4;
nCompareValueResult += mCompareValue(aVersion[2], eeprom_read_word((uint16_t *)EEPROM_FIRMWARE_VERSION_REVISION)) << 2;
nCompareValueResult += mCompareValue(aVersion[3], eeprom_read_word((uint16_t *)EEPROM_FIRMWARE_VERSION_FLAVOR));
if (nCompareValueResult == COMPARE_VALUE_EQUAL)
return;
if ((nCompareValueResult < COMPARE_VALUE_EQUAL) && oCheckVersion == ClCheckVersion::_Warn)
return;
// SERIAL_ECHO_START;
// SERIAL_ECHOLNPGM("Printer FW version differs from the G-code ...");
// SERIAL_ECHOPGM("actual : ");
// SERIAL_ECHO(eeprom_read_word((uint16_t *)EEPROM_FIRMWARE_VERSION_MAJOR));
// SERIAL_ECHO('.');
// SERIAL_ECHO(eeprom_read_word((uint16_t *)EEPROM_FIRMWARE_VERSION_MINOR));
// SERIAL_ECHO('.');
// SERIAL_ECHO(eeprom_read_word((uint16_t *)EEPROM_FIRMWARE_VERSION_REVISION));
// SERIAL_ECHO('.');
// SERIAL_ECHO(eeprom_read_word((uint16_t *)EEPROM_FIRMWARE_VERSION_FLAVOR));
// SERIAL_ECHOPGM("\nexpected: ");
// SERIAL_ECHO(aVersion[0]);
// SERIAL_ECHO('.');
// SERIAL_ECHO(aVersion[1]);
// SERIAL_ECHO('.');
// SERIAL_ECHO(aVersion[2]);
// SERIAL_ECHO('.');
// SERIAL_ECHOLN(aVersion[3]);
switch (oCheckVersion) {
case ClCheckVersion::_Warn:
// lcd_show_fullscreen_message_and_wait_P(_i("Printer FW version differs from the G-code. Continue?"));
lcd_display_message_fullscreen_P(_i("G-code sliced for a newer firmware. Continue?")); ////MSG_GCODE_NEWER_FIRMWARE_CONTINUE c=20 r=5
lcd_wait_for_click_delay(MSG_PRINT_CHECKING_FAILED_TIMEOUT);
//???custom_message_type=CUSTOM_MSG_TYPE_STATUS; // display / status-line recovery
lcd_update_enable(true); // display / status-line recovery
break;
case ClCheckVersion::_Strict:
lcd_show_fullscreen_message_and_wait_P(
_i("G-code sliced for a newer firmware. Please update the firmware. Print cancelled.")); ////MSG_GCODE_NEWER_FIRMWARE_CANCELLED c=20 r=8
lcd_print_stop();
break;
case ClCheckVersion::_None:
case ClCheckVersion::_Undef:
break;
}
}
void gcode_level_check(uint16_t nGcodeLevel)
@ -496,7 +529,6 @@ else {
}
}
void ip4_to_str(char* dest, uint8_t* IP)
{
sprintf_P(dest, PSTR("%u.%u.%u.%u"), IP[0], IP[1], IP[2], IP[3]);

View file

@ -4,17 +4,12 @@
extern const char* FW_VERSION_STR_P();
// Definition of a firmware flavor numerical values.
enum FirmwareRevisionFlavorType
{
FIRMWARE_REVISION_DEV = 0,
FIRMWARE_REVISION_ALPHA = 1,
FIRMWARE_REVISION_BETA = 2,
FIRMWARE_REVISION_RC,
FIRMWARE_REVISION_RC2,
FIRMWARE_REVISION_RC3,
FIRMWARE_REVISION_RC4,
FIRMWARE_REVISION_RC5,
FIRMWARE_REVISION_RELEASED = 127
enum FirmwareRevisionFlavorType : uint16_t {
FIRMWARE_REVISION_RELEASED = 0,
FIRMWARE_REVISION_DEV = 0x0100,
FIRMWARE_REVISION_ALPHA = 0x0200,
FIRMWARE_REVISION_BETA = 0x0300,
FIRMWARE_REVISION_RC = 0x0400
};
extern bool show_upgrade_dialog_if_version_newer(const char *version_string);