From 3c63ddaafd3e5c946a87b78251cc0cfb87b5b380 Mon Sep 17 00:00:00 2001 From: Panayiotis-git <32783577+Panayiotis-git@users.noreply.github.com> Date: Sat, 22 May 2021 17:09:55 +0300 Subject: [PATCH 01/72] Fix the eeprom address documentation --- Firmware/eeprom.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/eeprom.h b/Firmware/eeprom.h index 1db8a4066..56aed4898 100644 --- a/Firmware/eeprom.h +++ b/Firmware/eeprom.h @@ -325,8 +325,8 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP | 0x0D0D 3341 | float | EEPROM_UVLO_RETRACT_ACCELL | ??? | ff ff ff ffh | Power panic saved retract acceleration | ??? | D3 Ax0d0d C4 | 0x0D09 3337 | float | EEPROM_UVLO_TRAVEL_ACCELL | ??? | ff ff ff ffh | Power panic saved travel acceleration | ??? | D3 Ax0d09 C4 | 0x0D05 3333 | uint32_t | EEPROM_JOB_ID | ??? | 00 00 00 00h | Job ID used by host software | D3 only | D3 Ax0d05 C4 -| 0x0D01 3329 | uint8_t | EEPROM_ECOOL_ENABLE | ffh 255 | ^ | Disable extruder motor scaling for non-farm print | LCD menu | D3 Ax0d01 FF -| ^ | ^ | ^ | 2ah 42 | ^ | Enable extruder motor scaling for non-farm print | ^ | D3 Ax0d01 42 +| 0x0D04 3332 | uint8_t | EEPROM_ECOOL_ENABLE | ffh 255 | ^ | Disable extruder motor scaling for non-farm print | LCD menu | D3 Ax0d04 C1 +| ^ | ^ | ^ | 2ah 42 | ^ | Enable extruder motor scaling for non-farm print | ^ | D3 Ax0d04 C1 | Address begin | Bit/Type | Name | Valid values | Default/FactoryReset | Description | Gcode/Function| Debug code | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: From 62f496e1d6fc220e3ad7e35ddd06523e0c52035e Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sat, 22 May 2021 15:03:26 +0200 Subject: [PATCH 02/72] Allow D2 to be enabled selectively --- Firmware/Dcodes.cpp | 4 ++++ Firmware/Dcodes.h | 3 +++ Firmware/Marlin_main.cpp | 2 ++ 3 files changed, 9 insertions(+) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index dace219f6..9a353be81 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -239,7 +239,9 @@ void dcode_1() eeprom_write_byte((unsigned char*)i, (unsigned char)0xff); softReset(); } +#endif +#if defined DEBUG_DCODE2 || defined DEBUG_DCODES /*! ### D2 - Read/Write RAM D3: Read/Write RAM This command can be used without any additional parameters. It will read the entire RAM. @@ -300,7 +302,9 @@ void dcode_2() putchar('\n'); }*/ } +#endif +#ifdef DEBUG_DCODES /*! ### D4 - Read/Write PIN D4: Read/Write PIN diff --git a/Firmware/Dcodes.h b/Firmware/Dcodes.h index 856d04ad0..02ef74222 100644 --- a/Firmware/Dcodes.h +++ b/Firmware/Dcodes.h @@ -4,7 +4,10 @@ extern void dcode__1(); //D-1 - Endless loop (to simulate deadlock) extern void dcode_0(); //D0 - Reset extern void dcode_1(); //D1 - Clear EEPROM + +#if defined DEBUG_DCODE2 || defined DEBUG_DCODES extern void dcode_2(); //D2 - Read/Write RAM +#endif #if defined DEBUG_DCODE3 || defined DEBUG_DCODES extern void dcode_3(); //D3 - Read/Write EEPROM diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 92df0122d..b2bb36bb1 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -9053,7 +9053,9 @@ Sigma_Exit: */ case 1: dcode_1(); break; +#endif +#if defined DEBUG_DCODE2 || defined DEBUG_DCODES /*! ### D2 - Read/Write RAM D3: Read/Write RAM This command can be used without any additional parameters. It will read the entire RAM. From 2d25a5705fb2f326a04c7f2ea012f2c74d578959 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sat, 22 May 2021 15:04:27 +0200 Subject: [PATCH 03/72] Fix D2 to read the entire SRAM content Allow to read up to 0x21ff, which is the last byte of SRAM. Set default starting address to 0x200, which is the first true byte. 0x0-200 is mapped to register/io space and could cause issues when read from bi-directional registers. --- Firmware/Dcodes.cpp | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index 9a353be81..5af12e2e1 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -246,32 +246,31 @@ void dcode_1() ### D2 - Read/Write RAM D3: Read/Write RAM This command can be used without any additional parameters. It will read the entire RAM. #### Usage - + D2 [ A | C | X ] - + #### Parameters - - `A` - Address (x0000-x1fff) - - `C` - Count (1-8192) + - `A` - Address (x0000-x21ff) + - `C` - Count (1-8704) - `X` - Data #### Notes - The hex address needs to be lowercase without the 0 before the x - - Count is decimal + - Count is decimal - The hex data needs to be lowercase - + */ void dcode_2() { - LOG("D2 - Read/Write RAM\n"); - uint16_t address = 0x0000; //default 0x0000 - uint16_t count = 0x2000; //default 0x2000 (entire ram) - if (code_seen('A')) // Address (0x0000-0x1fff) + DBG(_N("D2 - Read/Write RAM\n")); + uint16_t address = 0x200; // default to start of sram + uint16_t count = 0x2200; // entire addressable space + if (code_seen('A')) // Address (0x0000-0x21ff) address = (strchr_pointer[1] == 'x')?strtol(strchr_pointer + 2, 0, 16):(int)code_value(); - if (code_seen('C')) // Count (0x0001-0x2000) + if (code_seen('C')) // Count (0x0000-0x2200) count = (int)code_value(); - address &= 0x1fff; - if (count > 0x2000) count = 0x2000; - if ((address + count) > 0x2000) count = 0x2000 - address; + if (address > 0x2200) address = 0x2200; + if ((address + count) > 0x2200) count = 0x2200 - address; if (code_seen('X')) // Data { uint8_t data[16]; @@ -280,7 +279,7 @@ void dcode_2() { for (uint16_t i = 0; i < count; i++) *((uint8_t*)(address + i)) = data[i]; - LOG("%d bytes written to RAM at address %04x", count, address); + DBG(_N("%d bytes written to RAM at address 0x%04x\n"), count, address); } else count = 0; From 915f5a7692ffda330b39d0b57c9e9745ad34a547 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 24 May 2021 22:49:28 +0200 Subject: [PATCH 04/72] Unify D2 and D3 handling Handle reading/writing memory using the same base functions in order to save space. --- Firmware/Dcodes.cpp | 148 ++++++++++++++------------------------------ 1 file changed, 46 insertions(+), 102 deletions(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index 5af12e2e1..d550afeba 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -29,24 +29,6 @@ void print_hex_word(uint16_t val) print_hex_byte(val & 255); } -void print_eeprom(uint16_t address, uint16_t count, uint8_t countperline = 16) -{ - while (count) - { - print_hex_word(address); - putchar(' '); - uint8_t count_line = countperline; - while (count && count_line) - { - putchar(' '); - print_hex_byte(eeprom_read_byte((uint8_t*)address++)); - count_line--; - count--; - } - putchar('\n'); - } -} - int parse_hex(char* hex, uint8_t* data, int count) { int parsed = 0; @@ -71,12 +53,12 @@ int parse_hex(char* hex, uint8_t* data, int count) } -void print_mem(uint32_t address, uint16_t count, uint8_t type, uint8_t countperline = 16) +enum class dcode_mem_t:uint8_t { sram, eeprom, progmem }; + +void print_mem(uint16_t address, uint16_t count, dcode_mem_t type, uint8_t countperline = 16) { while (count) { - if (type == 2) - print_hex_nibble(address >> 16); print_hex_word(address); putchar(' '); uint8_t count_line = countperline; @@ -85,10 +67,11 @@ void print_mem(uint32_t address, uint16_t count, uint8_t type, uint8_t countperl uint8_t data = 0; switch (type) { - case 0: data = *((uint8_t*)address++); break; - case 1: data = eeprom_read_byte((uint8_t*)address++); break; - case 2: data = pgm_read_byte_far((uint8_t*)address++); break; + case dcode_mem_t::sram: data = *((uint8_t*)address); break; + case dcode_mem_t::eeprom: data = eeprom_read_byte((uint8_t*)address); break; + case dcode_mem_t::progmem: data = pgm_read_byte_far((uint8_t*)address); break; } + ++address; putchar(' '); print_hex_byte(data); count_line--; @@ -98,6 +81,43 @@ void print_mem(uint32_t address, uint16_t count, uint8_t type, uint8_t countperl } } +void write_mem(uint16_t address, uint16_t count, const uint8_t* data, const dcode_mem_t type) +{ + for (uint16_t i = 0; i < count; i++) + { + switch (type) + { + case dcode_mem_t::sram: *((uint8_t*)address) = data[i]; break; + case dcode_mem_t::eeprom: eeprom_write_byte((uint8_t*)address, data[i]); break; + case dcode_mem_t::progmem: break; + } + ++address; + } +} + +void dcode_core(uint16_t addr_start, const uint16_t addr_end, const dcode_mem_t type, + uint8_t dcode, const char* type_desc) +{ + DBG(_N("D%d - Read/Write %S\n"), dcode, type_desc); + uint16_t count = -1; // RW the entire space by default + if (code_seen('A')) + addr_start = (strchr_pointer[1] == 'x')?strtol(strchr_pointer + 2, 0, 16):(int)code_value(); + if (code_seen('C')) + count = (int)code_value(); + if (addr_start > addr_end) + addr_start = addr_end; + if ((addr_start + count) > addr_end || (addr_start + count) < addr_start) + count = addr_end - addr_start; + if (code_seen('X')) + { + uint8_t data[16]; + count = parse_hex(strchr_pointer + 1, data, 16); + write_mem(addr_start, count, data, type); + DBG(_N("%d bytes written to %S at address 0x%04x\n"), count, type_desc, addr_start); + } + print_mem(addr_start, count, type); +} + #if defined DEBUG_DCODE3 || defined DEBUG_DCODES #define EEPROM_SIZE 0x1000 /*! @@ -120,46 +140,7 @@ void print_mem(uint32_t address, uint16_t count, uint8_t type, uint8_t countperl */ void dcode_3() { - DBG(_N("D3 - Read/Write EEPROM\n")); - uint16_t address = 0x0000; //default 0x0000 - uint16_t count = EEPROM_SIZE; //default 0x1000 (entire eeprom) - if (code_seen('A')) // Address (0x0000-0x0fff) - address = (strchr_pointer[1] == 'x')?strtol(strchr_pointer + 2, 0, 16):(int)code_value(); - if (code_seen('C')) // Count (0x0001-0x1000) - count = (int)code_value(); - address &= 0x1fff; - if (count > EEPROM_SIZE) count = EEPROM_SIZE; - if ((address + count) > EEPROM_SIZE) count = EEPROM_SIZE - address; - if (code_seen('X')) // Data - { - uint8_t data[16]; - count = parse_hex(strchr_pointer + 1, data, 16); - if (count > 0) - { - for (uint16_t i = 0; i < count; i++) - eeprom_write_byte((uint8_t*)(address + i), data[i]); - printf_P(_N("%d bytes written to EEPROM at address 0x%04x"), count, address); - putchar('\n'); - } - else - count = 0; - } - print_mem(address, count, 1); -/* while (count) - { - print_hex_word(address); - putchar(' '); - uint8_t countperline = 16; - while (count && countperline) - { - uint8_t data = eeprom_read_byte((uint8_t*)address++); - putchar(' '); - print_hex_byte(data); - countperline--; - count--; - } - putchar('\n'); - }*/ + dcode_core(0, EEPROM_SIZE, dcode_mem_t::eeprom, 3, _N("EEPROM")); } #endif //DEBUG_DCODE3 @@ -262,44 +243,7 @@ void dcode_1() */ void dcode_2() { - DBG(_N("D2 - Read/Write RAM\n")); - uint16_t address = 0x200; // default to start of sram - uint16_t count = 0x2200; // entire addressable space - if (code_seen('A')) // Address (0x0000-0x21ff) - address = (strchr_pointer[1] == 'x')?strtol(strchr_pointer + 2, 0, 16):(int)code_value(); - if (code_seen('C')) // Count (0x0000-0x2200) - count = (int)code_value(); - if (address > 0x2200) address = 0x2200; - if ((address + count) > 0x2200) count = 0x2200 - address; - if (code_seen('X')) // Data - { - uint8_t data[16]; - count = parse_hex(strchr_pointer + 1, data, 16); - if (count > 0) - { - for (uint16_t i = 0; i < count; i++) - *((uint8_t*)(address + i)) = data[i]; - DBG(_N("%d bytes written to RAM at address 0x%04x\n"), count, address); - } - else - count = 0; - } - print_mem(address, count, 0); -/* while (count) - { - print_hex_word(address); - putchar(' '); - uint8_t countperline = 16; - while (count && countperline) - { - uint8_t data = *((uint8_t*)address++); - putchar(' '); - print_hex_byte(data); - countperline--; - count--; - } - putchar('\n'); - }*/ + dcode_core(0x200, 0x2200, dcode_mem_t::sram, 2, _N("SRAM")); } #endif From f9371146d098277071f63b7393a18521505af8fe Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 7 Jun 2021 11:21:33 +0200 Subject: [PATCH 05/72] Implement reading XFLASH with D6 This requires expanding the dcode_core address type to 32bit type, thus enlarges the D2/D3 implementation as a result. Still allow to save all the original space if D6 is disabled, for now. --- Firmware/Dcodes.cpp | 53 +++++++++++++++++++++++++++++++--------- Firmware/Marlin_main.cpp | 4 ++- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index d550afeba..b3bdbdcad 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -3,6 +3,7 @@ #include "Configuration.h" #include "language.h" #include "cmdqueue.h" +#include "xflash.h" #include #include @@ -23,10 +24,22 @@ void print_hex_byte(uint8_t val) print_hex_nibble(val & 15); } -void print_hex_word(uint16_t val) +// debug range address type (fits all SRAM/PROGMEM/XFLASH memory ranges) +#if defined(DEBUG_DCODE6) || defined(DEBUG_DCODES) +#define DADDR_SIZE 32 +typedef uint32_t daddr_t; // XFLASH requires 24 bits +#else +#define DADDR_SIZE 16 +typedef uint16_t daddr_t; +#endif + +void print_hex_word(daddr_t val) { - print_hex_byte(val >> 8); - print_hex_byte(val & 255); +#if DADDR_SIZE > 16 + print_hex_byte((val >> 16) & 0xFF); +#endif + print_hex_byte((val >> 8) & 0xFF); + print_hex_byte(val & 0xFF); } int parse_hex(char* hex, uint8_t* data, int count) @@ -53,10 +66,14 @@ int parse_hex(char* hex, uint8_t* data, int count) } -enum class dcode_mem_t:uint8_t { sram, eeprom, progmem }; +enum class dcode_mem_t:uint8_t { sram, eeprom, progmem, xflash }; -void print_mem(uint16_t address, uint16_t count, dcode_mem_t type, uint8_t countperline = 16) +void print_mem(daddr_t address, daddr_t count, dcode_mem_t type, uint8_t countperline = 16) { +#if defined(DEBUG_DCODE6) || defined(DEBUG_DCODES) + if(type == dcode_mem_t::xflash) + XFLASH_SPI_ENTER(); +#endif while (count) { print_hex_word(address); @@ -70,6 +87,11 @@ void print_mem(uint16_t address, uint16_t count, dcode_mem_t type, uint8_t count case dcode_mem_t::sram: data = *((uint8_t*)address); break; case dcode_mem_t::eeprom: data = eeprom_read_byte((uint8_t*)address); break; case dcode_mem_t::progmem: data = pgm_read_byte_far((uint8_t*)address); break; +#if defined(DEBUG_DCODE6) || defined(DEBUG_DCODES) + case dcode_mem_t::xflash: xflash_rd_data(address, &data, 1); break; +#else + case dcode_mem_t::xflash: break; +#endif } ++address; putchar(' '); @@ -81,6 +103,7 @@ void print_mem(uint16_t address, uint16_t count, dcode_mem_t type, uint8_t count } } +// TODO: this only handles SRAM/EEPROM 16bit addresses void write_mem(uint16_t address, uint16_t count, const uint8_t* data, const dcode_mem_t type) { for (uint16_t i = 0; i < count; i++) @@ -90,20 +113,21 @@ void write_mem(uint16_t address, uint16_t count, const uint8_t* data, const dcod case dcode_mem_t::sram: *((uint8_t*)address) = data[i]; break; case dcode_mem_t::eeprom: eeprom_write_byte((uint8_t*)address, data[i]); break; case dcode_mem_t::progmem: break; + case dcode_mem_t::xflash: break; } ++address; } } -void dcode_core(uint16_t addr_start, const uint16_t addr_end, const dcode_mem_t type, +void dcode_core(daddr_t addr_start, const daddr_t addr_end, const dcode_mem_t type, uint8_t dcode, const char* type_desc) { DBG(_N("D%d - Read/Write %S\n"), dcode, type_desc); - uint16_t count = -1; // RW the entire space by default + daddr_t count = -1; // RW the entire space by default if (code_seen('A')) addr_start = (strchr_pointer[1] == 'x')?strtol(strchr_pointer + 2, 0, 16):(int)code_value(); if (code_seen('C')) - count = (int)code_value(); + count = code_value_long(); if (addr_start > addr_end) addr_start = addr_end; if ((addr_start + count) > addr_end || (addr_start + count) < addr_start) @@ -113,7 +137,11 @@ void dcode_core(uint16_t addr_start, const uint16_t addr_end, const dcode_mem_t uint8_t data[16]; count = parse_hex(strchr_pointer + 1, data, 16); write_mem(addr_start, count, data, type); - DBG(_N("%d bytes written to %S at address 0x%04x\n"), count, type_desc, addr_start); +#if DADDR_SIZE > 16 + DBG(_N("%u bytes written to %S at address 0x%08x\n"), count, type_desc, addr_start); +#else + DBG(_N("%lu bytes written to %S at address 0x%04lx\n"), count, type_desc, addr_start); +#endif } print_mem(addr_start, count, type); } @@ -372,17 +400,18 @@ void dcode_5() } #endif //DEBUG_DCODE5 -#ifdef DEBUG_DCODES - +#if defined DEBUG_DCODE6 || defined DEBUG_DCODES /*! ### D6 - Read/Write external FLASH D6: Read/Write external Flash Reserved */ void dcode_6() { - LOG("D6 - Read/Write external FLASH\n"); + dcode_core(0x0, 0x40000, dcode_mem_t::xflash, 6, _N("XFLASH")); } +#endif +#ifdef DEBUG_DCODES /*! ### D7 - Read/Write Bootloader D7: Read/Write Bootloader Reserved diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index b2bb36bb1..01ef1ef9e 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -9142,7 +9142,7 @@ Sigma_Exit: case 5: dcode_5(); break; #endif //DEBUG_DCODE5 -#ifdef DEBUG_DCODES +#if defined DEBUG_DCODE6 || defined DEBUG_DCODES /*! ### D6 - Read/Write external FLASH D6: Read/Write external Flash @@ -9150,6 +9150,8 @@ Sigma_Exit: */ case 6: dcode_6(); break; +#endif +#ifdef DEBUG_DCODES /*! ### D7 - Read/Write Bootloader D7: Read/Write Bootloader From 12e124324f0c081503bccf0ef78e5665b50bf72e Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 7 Jun 2021 11:29:53 +0200 Subject: [PATCH 06/72] Remove PROGMEM handling from print_mem until D5 uses dcode_core Handling PROGMEM also requires a 32bit address type. --- Firmware/Dcodes.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index b3bdbdcad..7585af0bf 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -86,7 +86,7 @@ void print_mem(daddr_t address, daddr_t count, dcode_mem_t type, uint8_t countpe { case dcode_mem_t::sram: data = *((uint8_t*)address); break; case dcode_mem_t::eeprom: data = eeprom_read_byte((uint8_t*)address); break; - case dcode_mem_t::progmem: data = pgm_read_byte_far((uint8_t*)address); break; + case dcode_mem_t::progmem: break; #if defined(DEBUG_DCODE6) || defined(DEBUG_DCODES) case dcode_mem_t::xflash: xflash_rd_data(address, &data, 1); break; #else From db096557d44eb5980e4699444acc531fe6f9b134 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 7 Jun 2021 16:08:03 +0200 Subject: [PATCH 07/72] D[236]: remove "busy" messages while dumping, avoid WDT --- Firmware/Dcodes.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index 7585af0bf..9603dc62f 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -98,6 +98,10 @@ void print_mem(daddr_t address, daddr_t count, dcode_mem_t type, uint8_t countpe print_hex_byte(data); count_line--; count--; + + // sporadically call manage heaters to avoid wdt + if(!((uint16_t)count % 8192)) + manage_heater(); } putchar('\n'); } @@ -122,6 +126,7 @@ void write_mem(uint16_t address, uint16_t count, const uint8_t* data, const dcod void dcode_core(daddr_t addr_start, const daddr_t addr_end, const dcode_mem_t type, uint8_t dcode, const char* type_desc) { + KEEPALIVE_STATE(NOT_BUSY); DBG(_N("D%d - Read/Write %S\n"), dcode, type_desc); daddr_t count = -1; // RW the entire space by default if (code_seen('A')) From ed9f52dd8504abd94aa04037ea1d8e3bfefe49a6 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 7 Jun 2021 18:50:45 +0200 Subject: [PATCH 08/72] D6: also hide declaration behind conditional --- Firmware/Dcodes.cpp | 2 +- Firmware/Dcodes.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index 9603dc62f..319223145 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -405,7 +405,7 @@ void dcode_5() } #endif //DEBUG_DCODE5 -#if defined DEBUG_DCODE6 || defined DEBUG_DCODES +#if defined(XFLASH) && (defined DEBUG_DCODE6 || defined DEBUG_DCODES) /*! ### D6 - Read/Write external FLASH D6: Read/Write external Flash Reserved diff --git a/Firmware/Dcodes.h b/Firmware/Dcodes.h index 02ef74222..c019c9817 100644 --- a/Firmware/Dcodes.h +++ b/Firmware/Dcodes.h @@ -19,7 +19,10 @@ extern void dcode_4(); //D4 - Read/Write PIN extern void dcode_5(); //D5 - Read/Write FLASH #endif //DEBUG_DCODE5 +#if defined DEBUG_DCODE6 || defined DEBUG_DCODES extern void dcode_6(); //D6 - Read/Write external FLASH +#endif + extern void dcode_7(); //D7 - Read/Write Bootloader extern void dcode_8(); //D8 - Read/Write PINDA extern void dcode_9(); //D9 - Read/Write ADC (Write=enable simulated, Read=disable simulated) From 0fcdada5798be1fdb62091e1f294776889fa78d2 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 7 Jun 2021 19:58:18 +0200 Subject: [PATCH 09/72] D6: add documentation --- Firmware/Dcodes.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index 319223145..d6ab3d995 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -408,7 +408,21 @@ void dcode_5() #if defined(XFLASH) && (defined DEBUG_DCODE6 || defined DEBUG_DCODES) /*! ### D6 - Read/Write external FLASH D6: Read/Write external Flash - Reserved + This command can be used without any additional parameters. It will read the entire XFLASH. + #### Usage + + D6 [ A | C | X ] + + #### Parameters + - `A` - Address (x0000-x3ffff) + - `C` - Count (1-262144) + - `X` - Data + + #### Notes + - The hex address needs to be lowercase without the 0 before the x + - Count is decimal + - The hex data needs to be lowercase + - Writing is currently not implemented */ void dcode_6() { From af636c7f2ac7a80e71d998871484db6c4761b547 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 8 Jun 2021 15:18:33 +0200 Subject: [PATCH 10/72] Move "xflash" include inside the conditional --- Firmware/Dcodes.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index d6ab3d995..9de93f770 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -3,7 +3,6 @@ #include "Configuration.h" #include "language.h" #include "cmdqueue.h" -#include "xflash.h" #include #include @@ -26,6 +25,8 @@ void print_hex_byte(uint8_t val) // debug range address type (fits all SRAM/PROGMEM/XFLASH memory ranges) #if defined(DEBUG_DCODE6) || defined(DEBUG_DCODES) +#include "xflash.h" + #define DADDR_SIZE 32 typedef uint32_t daddr_t; // XFLASH requires 24 bits #else From 5ae8bad0bae0d33fb624064b4297011d6601adce Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 8 Jun 2021 15:20:23 +0200 Subject: [PATCH 11/72] Introduce "xflash_layout" to organize XFLASH's content Update the language code to use the new LANG_OFFSET definition and remove hard-coded flash sizes. --- Firmware/Dcodes.cpp | 3 ++- Firmware/language.c | 7 ++++--- Firmware/xflash_layout.h | 8 ++++++++ 3 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 Firmware/xflash_layout.h diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index 9de93f770..e1b38ad46 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -26,6 +26,7 @@ void print_hex_byte(uint8_t val) // debug range address type (fits all SRAM/PROGMEM/XFLASH memory ranges) #if defined(DEBUG_DCODE6) || defined(DEBUG_DCODES) #include "xflash.h" +#include "xflash_layout.h" #define DADDR_SIZE 32 typedef uint32_t daddr_t; // XFLASH requires 24 bits @@ -427,7 +428,7 @@ void dcode_5() */ void dcode_6() { - dcode_core(0x0, 0x40000, dcode_mem_t::xflash, 6, _N("XFLASH")); + dcode_core(0x0, XFLASH_SIZE, dcode_mem_t::xflash, 6, _N("XFLASH")); } #endif diff --git a/Firmware/language.c b/Firmware/language.c index 01a396523..9a1113b96 100644 --- a/Firmware/language.c +++ b/Firmware/language.c @@ -9,6 +9,7 @@ #ifdef XFLASH #include "xflash.h" +#include "xflash_layout.h" #endif //XFLASH // Currently active language selection. @@ -110,7 +111,7 @@ uint8_t lang_get_count() #ifdef XFLASH XFLASH_SPI_ENTER(); uint8_t count = 2; //count = 1+n (primary + secondary + all in xflash) - uint32_t addr = 0x00000; //start of xflash + uint32_t addr = LANG_OFFSET; lang_table_header_t header; //table header structure while (1) { @@ -143,7 +144,7 @@ uint8_t lang_get_header(uint8_t lang, lang_table_header_t* header, uint32_t* off return (header->magic == LANG_MAGIC)?1:0; //return 1 if magic valid } XFLASH_SPI_ENTER(); - uint32_t addr = 0x00000; //start of xflash + uint32_t addr = LANG_OFFSET; lang--; while (1) { @@ -176,7 +177,7 @@ uint16_t lang_get_code(uint8_t lang) return pgm_read_word(((uint32_t*)(ui + 10))); //return lang code from progmem } XFLASH_SPI_ENTER(); - uint32_t addr = 0x00000; //start of xflash + uint32_t addr = LANG_OFFSET; lang_table_header_t header; //table header structure lang--; while (1) diff --git a/Firmware/xflash_layout.h b/Firmware/xflash_layout.h new file mode 100644 index 000000000..39b5f26c4 --- /dev/null +++ b/Firmware/xflash_layout.h @@ -0,0 +1,8 @@ +// XFLASH memory layout +#pragma once +#include +#include "config.h" + +#define XFLASH_SIZE 0x40000ul // size of XFLASH +#define LANG_OFFSET 0x0 // offset for language data +#define LANG_SIZE XFLASH_SIZE From 86e753fe376e661b96f3e36cccb2f3a50e3bf840 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 8 Jun 2021 15:24:46 +0200 Subject: [PATCH 12/72] xflash: remove some duplication --- Firmware/xflash.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/Firmware/xflash.c b/Firmware/xflash.c index e9d894a5b..43680b2ec 100644 --- a/Firmware/xflash.c +++ b/Firmware/xflash.c @@ -90,13 +90,18 @@ void w25x20cl_wr_status_reg(uint8_t val) } #endif -void xflash_rd_data(uint32_t addr, uint8_t* data, uint16_t cnt) +static void xflash_send_cmdaddr(uint8_t cmd, uint32_t addr) { - _CS_LOW(); - _SPI_TX(_CMD_RD_DATA); // send command 0x03 + _SPI_TX(cmd); // send command 0x03 _SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23 _SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15 _SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7 +} + +void xflash_rd_data(uint32_t addr, uint8_t* data, uint16_t cnt) +{ + _CS_LOW(); + xflash_send_cmdaddr(_CMD_RD_DATA, addr); while (cnt--) // receive data *(data++) = _SPI_RX(); _CS_HIGH(); @@ -105,10 +110,7 @@ void xflash_rd_data(uint32_t addr, uint8_t* data, uint16_t cnt) void xflash_page_program(uint32_t addr, uint8_t* data, uint16_t cnt) { _CS_LOW(); - _SPI_TX(_CMD_PAGE_PROGRAM); // send command 0x02 - _SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23 - _SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15 - _SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7 + xflash_send_cmdaddr(_CMD_PAGE_PROGRAM, addr); while (cnt--) // send data _SPI_TX(*(data++)); _CS_HIGH(); @@ -117,10 +119,7 @@ void xflash_page_program(uint32_t addr, uint8_t* data, uint16_t cnt) void xflash_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt) { _CS_LOW(); - _SPI_TX(_CMD_PAGE_PROGRAM); // send command 0x02 - _SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23 - _SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15 - _SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7 + xflash_send_cmdaddr(_CMD_PAGE_PROGRAM, addr); while (cnt--) // send data _SPI_TX(pgm_read_byte(data++)); _CS_HIGH(); @@ -129,10 +128,7 @@ void xflash_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt) void xflash_erase(uint8_t cmd, uint32_t addr) { _CS_LOW(); - _SPI_TX(cmd); // send command 0x20 - _SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23 - _SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15 - _SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7 + xflash_send_cmdaddr(cmd, addr); _CS_HIGH(); } From b398a09a4f5c2437a3c170bd688ae64765d53621 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 8 Jun 2021 15:25:16 +0200 Subject: [PATCH 13/72] xflash: add xflash_multipage_program and documentation Add a new high-level command to perform multipage writes quickly. --- Firmware/xflash.c | 22 ++++++++++++++++++++++ Firmware/xflash.h | 15 ++++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/Firmware/xflash.c b/Firmware/xflash.c index 43680b2ec..cc758ebf5 100644 --- a/Firmware/xflash.c +++ b/Firmware/xflash.c @@ -116,6 +116,28 @@ void xflash_page_program(uint32_t addr, uint8_t* data, uint16_t cnt) _CS_HIGH(); } +void xflash_multipage_program(uint32_t addr, uint8_t* data, uint16_t cnt) +{ + while(cnt) + { + xflash_enable_wr(); + _CS_LOW(); + xflash_send_cmdaddr(_CMD_PAGE_PROGRAM, addr); + while(1) + { + // send data + _SPI_TX(*(data++)); + if(!--cnt || !(++addr & 0xFF)) + { + // on a page boundary or end of write + _CS_HIGH(); + xflash_wait_busy(); + break; + } + } + } +} + void xflash_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt) { _CS_LOW(); diff --git a/Firmware/xflash.h b/Firmware/xflash.h index c9ad5275c..a75abb183 100644 --- a/Firmware/xflash.h +++ b/Firmware/xflash.h @@ -34,16 +34,25 @@ extern uint8_t xflash_rd_status_reg(void); extern void w25x20cl_wr_status_reg(uint8_t val); #endif extern void xflash_rd_data(uint32_t addr, uint8_t* data, uint16_t cnt); -extern void xflash_page_program(uint32_t addr, uint8_t* data, uint16_t cnt); -extern void xflash_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt); + extern void xflash_sector_erase(uint32_t addr); extern void xflash_block32_erase(uint32_t addr); extern void xflash_block64_erase(uint32_t addr); extern void xflash_chip_erase(void); -extern void xflash_page_program(uint32_t addr, uint8_t* data, uint16_t cnt); extern void xflash_rd_uid(uint8_t* uid); extern void xflash_wait_busy(void); +// write up to a single page of data (256bytes) +extern void xflash_page_program(uint32_t addr, uint8_t* data, uint16_t cnt); + +// write up to a single page of data from program memory +extern void xflash_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt); + +// xflash_multipage_program: high-level interface for multi-page writes. +// Write any amount of data, chunking writes to page boundaries as needed. +// Automatically enables writes and waits for completion. +extern void xflash_multipage_program(uint32_t addr, uint8_t* data, uint16_t cnt); + #if defined(__cplusplus) } #endif //defined(__cplusplus) From 6dfef763467af6ec944d45084a97cc3cc8f1f23f Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 8 Jun 2021 15:28:02 +0200 Subject: [PATCH 14/72] xfdump: implement dump-to-xflash functionality Update xflash_layout to include information about the dump, which sits at the end of xflash. --- Firmware/Dcodes.cpp | 2 +- Firmware/xflash_dump.cpp | 106 +++++++++++++++++++++++++++++++++++++++ Firmware/xflash_dump.h | 14 ++++++ Firmware/xflash_layout.h | 42 ++++++++++++++++ 4 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 Firmware/xflash_dump.cpp create mode 100644 Firmware/xflash_dump.h diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index e1b38ad46..475714c2a 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -278,7 +278,7 @@ void dcode_1() */ void dcode_2() { - dcode_core(0x200, 0x2200, dcode_mem_t::sram, 2, _N("SRAM")); + dcode_core(SRAM_START, SRAM_START + SRAM_SIZE, dcode_mem_t::sram, 2, _N("SRAM")); } #endif diff --git a/Firmware/xflash_dump.cpp b/Firmware/xflash_dump.cpp new file mode 100644 index 000000000..7c44e5776 --- /dev/null +++ b/Firmware/xflash_dump.cpp @@ -0,0 +1,106 @@ +#include + +#include +#include + +#include "xflash_dump.h" +#include "xflash.h" + + +bool xfdump_check_state() +{ + uint32_t magic; + + XFLASH_SPI_ENTER(); + xflash_rd_data(DUMP_OFFSET + offsetof(dump_t, header.magic), + (uint8_t*)&magic, sizeof(magic)); + + return magic == DUMP_MAGIC; +} + + +bool xfdump_check_crash() +{ + // check_state with SPI_ENTER for us + if(!xfdump_check_state()) + return false; + + uint8_t crash; + xflash_rd_data(DUMP_OFFSET + offsetof(dump_t, header.crash), + (uint8_t*)&crash, sizeof(crash)); + return crash; +} + + +void xfdump_reset() +{ + XFLASH_SPI_ENTER(); + xflash_enable_wr(); + xflash_sector_erase(DUMP_OFFSET + offsetof(dump_t, header.magic)); + xflash_wait_busy(); +} + + +static void xfdump_erase() +{ + XFLASH_SPI_ENTER(); + for(uint32_t addr = DUMP_OFFSET; + addr < DUMP_OFFSET + DUMP_SIZE; + addr += 4096) + { + xflash_enable_wr(); + xflash_sector_erase(DUMP_OFFSET); + xflash_wait_busy(); + } +} + + +static void xfdump_dump_core(dump_header_t& hdr, uint32_t addr, uint8_t* buf, uint16_t cnt) +{ + XFLASH_SPI_ENTER(); + + // start by clearing all sectors (we need all of them in any case) + xfdump_erase(); + + // write header + static_assert(sizeof(hdr) < 256, "header is larger than a single page write"); + xflash_enable_wr(); + xflash_page_program(DUMP_OFFSET, (uint8_t*)&hdr, sizeof(hdr)); + xflash_wait_busy(); + + // write data + xflash_multipage_program(addr, buf, cnt); +} + + +void xfdump_dump() +{ + dump_header_t buf; + buf.magic = DUMP_MAGIC; + buf.regs_present = false; + buf.crash = false; + + // write sram only + xfdump_dump_core(buf, DUMP_OFFSET + offsetof(dump_t, data.sram), + (uint8_t*)SRAM_START, SRAM_SIZE); +} + + +void xfdump_full_dump_and_reset(bool crash) +{ + dump_header_t buf; + buf.magic = DUMP_MAGIC; + buf.regs_present = true; + buf.crash = crash; + + // disable interrupts for a cleaner register dump + cli(); + + // write all addressable ranges (this will trash bidirectional registers) + xfdump_dump_core(buf, DUMP_OFFSET + offsetof(dump_t, data), + 0, SRAM_START + SRAM_SIZE); + + // force a reset soon + wdt_enable(0); + while(true); +} diff --git a/Firmware/xflash_dump.h b/Firmware/xflash_dump.h new file mode 100644 index 000000000..8492523c3 --- /dev/null +++ b/Firmware/xflash_dump.h @@ -0,0 +1,14 @@ +// XFLASH dumper +#pragma once +#include "xflash_layout.h" +#ifdef XFLASH_DUMP + +void xfdump_reset(); // reset XFLASH dump state +bool xfdump_check_state(); // return true if a dump is present +bool xfdump_check_crash(); // return true if a dump is present and is a crash dump +void xfdump_dump(); // create a new SRAM memory dump + +// create a new dump containing registers and SRAM, then reset +void xfdump_full_dump_and_reset(bool crash = false); + +#endif diff --git a/Firmware/xflash_layout.h b/Firmware/xflash_layout.h index 39b5f26c4..a5e5559cd 100644 --- a/Firmware/xflash_layout.h +++ b/Firmware/xflash_layout.h @@ -4,5 +4,47 @@ #include "config.h" #define XFLASH_SIZE 0x40000ul // size of XFLASH +#define SRAM_SIZE 0x2000u // size of SRAM +#define SRAM_START 0x200u // start of SRAM + #define LANG_OFFSET 0x0 // offset for language data + +#ifndef XFLASH_DUMP #define LANG_SIZE XFLASH_SIZE +#else + +#define DUMP_MAGIC 0x47555255ul + +struct dump_header_t +{ + // start with a magic value to indicate the presence of a dump, so that clearing + // a single page is sufficient for resetting the state + uint32_t magic; + + uint8_t regs_present; // true when the lower segment containing registers is present + uint8_t crash; // true if triggered by EMERGENCY_DUMP +}; + +struct dump_data_t +{ + // contiguous region containing all addressable ranges + uint8_t regs[SRAM_START]; + uint8_t sram[SRAM_SIZE]; +}; + +struct dump_t +{ + struct dump_header_t header; + + // data is page aligned (no real space waste, due to the larger + // alignment required for the whole dump) + struct dump_data_t __attribute__((aligned(256))) data; +}; + +// dump offset must be aligned to lower 4kb sector boundary +#define DUMP_OFFSET ((XFLASH_SIZE - sizeof(dump_t)) & ~0xFFFul) + +#define DUMP_SIZE (XFLASH_SIZE - DUMP_OFFSET) // effective dump size area +#define LANG_SIZE DUMP_OFFSET // available language space + +#endif From 8417083b1381ab1ff269d83c4a703f59c420cf57 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 8 Jun 2021 15:30:05 +0200 Subject: [PATCH 15/72] lang/fw-build.sh: check for language data size during build Ensure the language data always fits the reserved space in the XFLASH. The script *should* use the LANG_SIZE definition from "xflash_layout", which can be obtained by preprocessing the source code. At the moment though this step has been omitted since running arduino-builder to preprocess the source requires extra flags passed by build.sh. The size has been hard-coded (and it's unlikely to change given the content size is constant for the architecture). --- lang/fw-build.sh | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lang/fw-build.sh b/lang/fw-build.sh index 12a9ed512..2ba732282 100755 --- a/lang/fw-build.sh +++ b/lang/fw-build.sh @@ -198,6 +198,21 @@ if [ -e lang_nl.bin ]; then cat lang_nl.bin >> lang.bin; fi ## New language #if [ -e lang_qr.bin ]; then cat lang_qr.bin >> lang.bin; fi +# Check that the language data doesn't exceed the reserved XFLASH space +echo " checking language data size:" +lang_size=$(wc -c lang.bin | cut -f1 -d' ') +lang_size_pad=$(($lang_size / 4096 * 4096 + 4096)) + +# TODO: hard-coded! get value by preprocessing LANG_SIZE from xflash_layout.h! +lang_reserved=249856 + +echo " total size usage: $lang_size_pad ($lang_size)" +echo " reserved size: $lang_reserved" +if [ $lang_size_pad -gt $lang_reserved ]; then + echo "NG! - language data too large" >&2 + finish 1 +fi + #convert lang.bin to lang.hex echo -n " converting to hex..." >&2 $OBJCOPY -I binary -O ihex ./lang.bin ./lang.hex From 30402e040458d9c6f70a7ed1a10a170932cec163 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 8 Jun 2021 15:34:39 +0200 Subject: [PATCH 16/72] Dcodes: add D20/D21/D22 to generate/read/clear dumps --- Firmware/Dcodes.cpp | 42 ++++++++++++++++++++++++++++++++- Firmware/Dcodes.h | 6 +++++ Firmware/Marlin_main.cpp | 50 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 96 insertions(+), 2 deletions(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index 475714c2a..bbe397759 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -924,5 +924,45 @@ void dcode_9125() } #endif //PAT9125 - #endif //DEBUG_DCODES + +#ifdef XFLASH_DUMP +#include "xflash_dump.h" + +void dcode_20() +{ + if(code_seen('E')) + xfdump_full_dump_and_reset(); + else + { + unsigned long ts = millis(); + xfdump_dump(); + ts = millis() - ts; + DBG(_N("dump completed in %lums\n"), ts); + } +} + +void dcode_21() +{ + if(!xfdump_check_state()) + DBG(_N("no dump available\n")); + else + { + KEEPALIVE_STATE(NOT_BUSY); + DBG(_N("D21 - read crash dump\n")); + print_mem(DUMP_OFFSET + offsetof(dump_t, data), + DUMP_SIZE, dcode_mem_t::xflash); + } +} + +void dcode_22() +{ + if(!xfdump_check_state()) + DBG(_N("no dump available\n")); + else + { + xfdump_reset(); + DBG(_N("dump cleared\n")); + } +} +#endif diff --git a/Firmware/Dcodes.h b/Firmware/Dcodes.h index c019c9817..4e37cc243 100644 --- a/Firmware/Dcodes.h +++ b/Firmware/Dcodes.h @@ -29,6 +29,12 @@ extern void dcode_9(); //D9 - Read/Write ADC (Write=enable simulated, Read=disab extern void dcode_10(); //D10 - XYZ calibration = OK extern void dcode_12(); //D12 - Log time. Writes the current time in the log file. +#ifdef XFLASH_DUMP +extern void dcode_20(); //D20 - Generate an offline crash dump +extern void dcode_21(); //D21 - Print crash dump to serial +extern void dcode_22(); //D22 - Clear crash dump state +#endif + #ifdef HEATBED_ANALYSIS extern void dcode_80(); //D80 - Bed check. This command will log data to SD card file "mesh.txt". extern void dcode_81(); //D81 - Bed analysis. This command will log data to SD card file "wldsd.txt". diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 01ef1ef9e..4f95ed7ac 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -9205,8 +9205,56 @@ Sigma_Exit: ### D12 - Time D12: Time Writes the current time in the log file. */ - #endif //DEBUG_DCODES + +#ifdef XFLASH_DUMP + /*! + ### D20 - Generate an offline crash dump + Generate a crash dump for later retrival. + #### Usage + + D20 [E] + + ### Parameters + - `E` - Perform an emergency crash dump (resets the printer). + ### Notes + - A crash dump can be later recovered with D21, or cleared with D22. + - An emergency crash dump includes register data, but will cause the printer to reset after the dump + is completed. + */ + case 20: { + dcode_20(); + break; + }; + + /*! + ### D21 - Print crash dump to serial + Output the complete crash dump (if present) to the serial. + #### Usage + + D21 + + ### Notes + - The starting address can vary between builds, but it's always at the beginning of the data section. + */ + case 21: { + dcode_21(); + break; + }; + + /*! + ### D22 - Clear crash dump state + Clear an existing internal crash dump. + #### Usage + + D22 + */ + case 22: { + dcode_22(); + break; + }; +#endif + #ifdef HEATBED_ANALYSIS /*! From c089ac53413075fd18cba58c8808c2d4871695b5 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 8 Jun 2021 16:42:43 +0200 Subject: [PATCH 17/72] Implement EMERGENCY_DUMP for offline analysis If EMERGENCY_DUMP is defined, crash and dump using the new xflash dump functionality instead of just continuing with an error message. When an emergency crash is stored, the first restart after a crash displays a message that debug data is available and to contact support to submit the crash for analysis. --- Firmware/Marlin_main.cpp | 16 ++++++++++++++++ Firmware/eeprom.h | 4 +++- Firmware/ultralcd.cpp | 10 ++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 4f95ed7ac..2048b416d 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -108,6 +108,10 @@ #include "optiboot_xflash.h" #endif //XFLASH +#ifdef EMERGENCY_DUMP +#include "xflash_dump.h" +#endif + #ifdef BLINKM #include "BlinkM.h" #include "Wire.h" @@ -1606,6 +1610,18 @@ void setup() if (tmc2130_home_enabled == 0xff) tmc2130_home_enabled = 0; #endif //TMC2130 +#ifdef EMERGENCY_DUMP + if(xfdump_check_crash() && eeprom_read_byte((uint8_t*)EEPROM_CRASH_ACKNOWLEDGED) != 1) + { + // prevent the prompt to reappear once acknowledged + eeprom_update_byte((uint8_t*)EEPROM_CRASH_ACKNOWLEDGED, 1); + lcd_show_fullscreen_message_and_wait_P( + _i("!!!FIRMWARE CRASH!!!\n" + "Debug data available for analysis. " + "Contact support to submit details.")); + } +#endif + #ifdef UVLO_SUPPORT if (eeprom_read_byte((uint8_t*)EEPROM_UVLO) != 0) { //previous print was terminated by UVLO /* diff --git a/Firmware/eeprom.h b/Firmware/eeprom.h index 56aed4898..e70227c05 100644 --- a/Firmware/eeprom.h +++ b/Firmware/eeprom.h @@ -327,6 +327,7 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP | 0x0D05 3333 | uint32_t | EEPROM_JOB_ID | ??? | 00 00 00 00h | Job ID used by host software | D3 only | D3 Ax0d05 C4 | 0x0D04 3332 | uint8_t | EEPROM_ECOOL_ENABLE | ffh 255 | ^ | Disable extruder motor scaling for non-farm print | LCD menu | D3 Ax0d04 C1 | ^ | ^ | ^ | 2ah 42 | ^ | Enable extruder motor scaling for non-farm print | ^ | D3 Ax0d04 C1 +| 0x0D03 3321 | uint8_t | EEPROM_CRASH_ACKNOWLEDGED | 01h 1 | ff/00 | Disable crash report after first acknowledgment | D21/D22 | D3 Ax0d03 C1 | Address begin | Bit/Type | Name | Valid values | Default/FactoryReset | Description | Gcode/Function| Debug code | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: @@ -541,9 +542,10 @@ static Sheets * const EEPROM_Sheets_base = (Sheets*)(EEPROM_SHEETS_BASE); #define EEPROM_JOB_ID (EEPROM_UVLO_TRAVEL_ACCELL-4) //uint32_t #define EEPROM_ECOOL_ENABLE (EEPROM_JOB_ID-1) // uint8_t +#define EEPROM_CRASH_ACKNOWLEDGED (EEPROM_ECOOL_ENABLE-1) // uint8_t //This is supposed to point to last item to allow EEPROM overrun check. Please update when adding new items. -#define EEPROM_LAST_ITEM EEPROM_ECOOL_ENABLE +#define EEPROM_LAST_ITEM EEPROM_CRASH_ACKNOWLEDGED // !!!!! // !!!!! this is end of EEPROM section ... all updates MUST BE inserted before this mark !!!!! // !!!!! diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 02b9d3080..39eb0a03c 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -6683,12 +6683,22 @@ static void lcd_main_menu() } +#ifdef EMERGENCY_DUMP +#include "xflash_dump.h" + +void stack_error() { + WRITE(BEEPER, HIGH); + eeprom_update_byte((uint8_t*)EEPROM_CRASH_ACKNOWLEDGED, 0); + xfdump_full_dump_and_reset(true); +} +#else void stack_error() { Sound_MakeCustom(1000,0,true); lcd_display_message_fullscreen_P(_i("Error - static memory has been overwritten"));////MSG_STACK_ERROR c=20 r=4 //err_triggered = 1; while (1) delay_keep_alive(1000); } +#endif #ifdef DEBUG_STEPPER_TIMER_MISSED bool stepper_timer_overflow_state = false; From c31109c750ece65fc30084e3f083e98c19392e34 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 8 Jun 2021 16:56:58 +0200 Subject: [PATCH 18/72] Implement MENU_DUMP: offline memory dump from "Support" If MENU_DUMP is enabled, a new entry at the end of the "Support" menu is added that allows to dump memory for offline use. This allows to trigger a memory dump at any moment during regular usage (either idling or printing) and to recover the dump later even after a hardware reset. --- Firmware/ultralcd.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 39eb0a03c..8edcf7070 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -1801,6 +1801,19 @@ static void lcd_preheat_menu() lcd_generic_preheat_menu(); } + +#ifdef MENU_DUMP +#include "xflash_dump.h" + +static void lcd_dump_memory() +{ + lcd_beeper_quick_feedback(); + xfdump_dump(); + lcd_return_to_status(); +} +#endif + + //! @brief Show Support Menu //! //! @code{.unparsed} @@ -1992,7 +2005,9 @@ static void lcd_support_menu() MENU_ITEM_SUBMENU_P(_i("Voltages"), lcd_menu_voltages);////MSG_MENU_VOLTAGES c=18 #endif //defined VOLT_BED_PIN || defined VOLT_PWR_PIN - +#ifdef MENU_DUMP + MENU_ITEM_FUNCTION_P(_i("Dump memory"), lcd_dump_memory); +#endif #ifdef DEBUG_BUILD MENU_ITEM_SUBMENU_P(PSTR("Debug"), lcd_menu_debug);////MSG_DEBUG c=18 #endif /* DEBUG_BUILD */ From a6e372e6962961ecaf0fe23d695068b0fe44ad50 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 8 Jun 2021 17:14:22 +0200 Subject: [PATCH 19/72] Typo --- Firmware/xflash_dump.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/xflash_dump.cpp b/Firmware/xflash_dump.cpp index 7c44e5776..519ecf1bd 100644 --- a/Firmware/xflash_dump.cpp +++ b/Firmware/xflash_dump.cpp @@ -21,7 +21,7 @@ bool xfdump_check_state() bool xfdump_check_crash() { - // check_state with SPI_ENTER for us + // check_state will call SPI_ENTER for us if(!xfdump_check_state()) return false; From 1a88e339bfefefbad6fc9321177c15b2a63cd41f Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 8 Jun 2021 17:17:18 +0200 Subject: [PATCH 20/72] xfdump: fix build with XFLASH_DUMP disabled --- Firmware/xflash_dump.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Firmware/xflash_dump.cpp b/Firmware/xflash_dump.cpp index 519ecf1bd..f1ff9dede 100644 --- a/Firmware/xflash_dump.cpp +++ b/Firmware/xflash_dump.cpp @@ -4,6 +4,7 @@ #include #include "xflash_dump.h" +#ifdef XFLASH_DUMP #include "xflash.h" @@ -104,3 +105,4 @@ void xfdump_full_dump_and_reset(bool crash) wdt_enable(0); while(true); } +#endif From 0e75bc9d8e79edbfc1b9dd222428a7805c9cbbc1 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 8 Jun 2021 17:24:10 +0200 Subject: [PATCH 21/72] lang/fw-build.sh: fix padding calculation --- lang/fw-build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/fw-build.sh b/lang/fw-build.sh index 2ba732282..ecd2df2c2 100755 --- a/lang/fw-build.sh +++ b/lang/fw-build.sh @@ -201,7 +201,7 @@ if [ -e lang_nl.bin ]; then cat lang_nl.bin >> lang.bin; fi # Check that the language data doesn't exceed the reserved XFLASH space echo " checking language data size:" lang_size=$(wc -c lang.bin | cut -f1 -d' ') -lang_size_pad=$(($lang_size / 4096 * 4096 + 4096)) +lang_size_pad=$(( ($lang_size+4096-1) / 4096 * 4096 )) # TODO: hard-coded! get value by preprocessing LANG_SIZE from xflash_layout.h! lang_reserved=249856 From 520f7a2e26d5a7d098117bcd2fb6e1edf59c24d7 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 8 Jun 2021 17:32:14 +0200 Subject: [PATCH 22/72] config: add sanity checks for XFLASH_DUMP options --- Firmware/config.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Firmware/config.h b/Firmware/config.h index 2ec2077e6..fa86f4567 100644 --- a/Firmware/config.h +++ b/Firmware/config.h @@ -68,4 +68,12 @@ #define COMMUNITY_LANG_SUPPORT #endif +// Sanity checks for correct configuration of XFLASH_DUMP options +#if defined(XFLASH_DUMP) && !defined(XFLASH) +#error "XFLASH_DUMP requires XFLASH support" +#endif +#if (defined(MENU_DUMP) || defined(EMERGENCY_DUMP)) && !defined(XFLASH_DUMP) +#error "MENU_DUMP and EMERGENCY_DUMP require XFLASH_DUMP" +#endif + #endif //_CONFIG_H From c331c07b1623388e4d7afe9bd77d50053fe94698 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 8 Jun 2021 17:53:06 +0200 Subject: [PATCH 23/72] xfdump: reuse standard definitions for SRAM size/offset --- Firmware/Dcodes.cpp | 2 +- Firmware/bootapp.h | 3 ++- Firmware/xflash_dump.cpp | 5 ++--- Firmware/xflash_layout.h | 8 +++----- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index bbe397759..48f67cb3b 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -278,7 +278,7 @@ void dcode_1() */ void dcode_2() { - dcode_core(SRAM_START, SRAM_START + SRAM_SIZE, dcode_mem_t::sram, 2, _N("SRAM")); + dcode_core(RAMSTART, RAMEND, dcode_mem_t::sram, 2, _N("SRAM")); } #endif diff --git a/Firmware/bootapp.h b/Firmware/bootapp.h index 6ff086f46..44e1d16d2 100644 --- a/Firmware/bootapp.h +++ b/Firmware/bootapp.h @@ -3,10 +3,11 @@ #define BOOTAPP_H #include "config.h" +#include #include -#define RAMSIZE 0x2000 +#define RAMSIZE (RAMEND-RAMSTART) #define boot_src_addr (*((uint32_t*)(RAMSIZE - 16))) #define boot_dst_addr (*((uint32_t*)(RAMSIZE - 12))) #define boot_copy_size (*((uint16_t*)(RAMSIZE - 8))) diff --git a/Firmware/xflash_dump.cpp b/Firmware/xflash_dump.cpp index f1ff9dede..65722b1c0 100644 --- a/Firmware/xflash_dump.cpp +++ b/Firmware/xflash_dump.cpp @@ -83,7 +83,7 @@ void xfdump_dump() // write sram only xfdump_dump_core(buf, DUMP_OFFSET + offsetof(dump_t, data.sram), - (uint8_t*)SRAM_START, SRAM_SIZE); + (uint8_t*)RAMSTART, RAMSIZE); } @@ -98,8 +98,7 @@ void xfdump_full_dump_and_reset(bool crash) cli(); // write all addressable ranges (this will trash bidirectional registers) - xfdump_dump_core(buf, DUMP_OFFSET + offsetof(dump_t, data), - 0, SRAM_START + SRAM_SIZE); + xfdump_dump_core(buf, DUMP_OFFSET + offsetof(dump_t, data), 0, RAMEND); // force a reset soon wdt_enable(0); diff --git a/Firmware/xflash_layout.h b/Firmware/xflash_layout.h index a5e5559cd..f44b9c806 100644 --- a/Firmware/xflash_layout.h +++ b/Firmware/xflash_layout.h @@ -1,12 +1,10 @@ // XFLASH memory layout #pragma once #include +#include "bootapp.h" #include "config.h" #define XFLASH_SIZE 0x40000ul // size of XFLASH -#define SRAM_SIZE 0x2000u // size of SRAM -#define SRAM_START 0x200u // start of SRAM - #define LANG_OFFSET 0x0 // offset for language data #ifndef XFLASH_DUMP @@ -28,8 +26,8 @@ struct dump_header_t struct dump_data_t { // contiguous region containing all addressable ranges - uint8_t regs[SRAM_START]; - uint8_t sram[SRAM_SIZE]; + uint8_t regs[RAMSTART]; + uint8_t sram[RAMSIZE]; }; struct dump_t From c072fbbf028d0632a892e5df458846763c14d389 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 8 Jun 2021 18:14:49 +0200 Subject: [PATCH 24/72] Dcodes: fix daddr_t type when only XFLASH_DUMP is enabled --- Firmware/Dcodes.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index 48f67cb3b..9a78f296d 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -24,7 +24,7 @@ void print_hex_byte(uint8_t val) } // debug range address type (fits all SRAM/PROGMEM/XFLASH memory ranges) -#if defined(DEBUG_DCODE6) || defined(DEBUG_DCODES) +#if defined(DEBUG_DCODE6) || defined(DEBUG_DCODES) || defined(XFLASH_DUMP) #include "xflash.h" #include "xflash_layout.h" From dcfdce87c7934961848b4a52bf595cf52cbe91f3 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 8 Jun 2021 18:15:44 +0200 Subject: [PATCH 25/72] Document new applicable build options in the variant files Document, but don't enable them. Leave exiting functionality unchanged for now. --- Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h | 3 ++- Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h | 3 ++- Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h | 3 ++- Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h | 3 ++- Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h | 7 +++++++ Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h | 7 +++++++ 6 files changed, 22 insertions(+), 4 deletions(-) diff --git a/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h index acd7883dd..f49f5e1c8 100644 --- a/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h @@ -123,8 +123,9 @@ #define FILAMENT_SENSOR #define PAT9125 - +//#define DEBUG_DCODE2 #define DEBUG_DCODE3 +//#define DEBUG_DCODE6 //#define DEBUG_BUILD #ifdef DEBUG_BUILD diff --git a/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h index ddf7e77a0..0d900508a 100644 --- a/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h @@ -124,8 +124,9 @@ #define FILAMENT_SENSOR #define PAT9125 - +//#define DEBUG_DCODE2 #define DEBUG_DCODE3 +//#define DEBUG_DCODE6 //#define DEBUG_BUILD #ifdef DEBUG_BUILD diff --git a/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h index e7b114d96..73eb52f69 100644 --- a/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h @@ -123,8 +123,9 @@ #define FILAMENT_SENSOR #define IR_SENSOR - +//#define DEBUG_DCODE2 #define DEBUG_DCODE3 +//#define DEBUG_DCODE6 //#define DEBUG_BUILD #ifdef DEBUG_BUILD diff --git a/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h index cde812498..738f421e2 100644 --- a/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h @@ -124,8 +124,9 @@ #define FILAMENT_SENSOR #define IR_SENSOR - +//#define DEBUG_DCODE2 #define DEBUG_DCODE3 +//#define DEBUG_DCODE6 //#define DEBUG_BUILD #ifdef DEBUG_BUILD diff --git a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h index 16fba5d71..ab65d0245 100644 --- a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h @@ -139,6 +139,11 @@ #define DEFAULT_SAFETYTIMER_TIME_MINS 30 #define FARM_DEFAULT_SAFETYTIMER_TIME_ms (45*60*1000ul) +// Offline crash dumper +//#define XFLASH_DUMP // enable dump functionality (including D20/D21/D22) +//#define MENU_DUMP // enable "Memory dump" in Settings menu +//#define EMERGENCY_DUMP // trigger crash on stack corruption + // Filament sensor #define FILAMENT_SENSOR #define PAT9125 @@ -155,7 +160,9 @@ #define MINTEMP_MINAMBIENT 10 #define MINTEMP_MINAMBIENT_RAW 1002 +//#define DEBUG_DCODE2 #define DEBUG_DCODE3 +//#define DEBUG_DCODE6 //#define DEBUG_BUILD //#define DEBUG_SEC_LANG //secondary language debug output at startup diff --git a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h index 13fc2a796..48154903e 100644 --- a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h @@ -141,6 +141,11 @@ #define DEFAULT_SAFETYTIMER_TIME_MINS 30 #define FARM_DEFAULT_SAFETYTIMER_TIME_ms (45*60*1000ul) +// Offline crash dumper +//#define XFLASH_DUMP // enable dump functionality (including D20/D21/D22) +//#define MENU_DUMP // enable "Memory dump" in Settings menu +//#define EMERGENCY_DUMP // trigger crash on stack corruption + // Filament sensor #define FILAMENT_SENSOR #define IR_SENSOR @@ -157,7 +162,9 @@ #define MINTEMP_MINAMBIENT 10 #define MINTEMP_MINAMBIENT_RAW 1002 +//#define DEBUG_DCODE2 #define DEBUG_DCODE3 +//#define DEBUG_DCODE6 //#define DEBUG_BUILD //#define DEBUG_SEC_LANG //secondary language debug output at startup From 9d3b19b637fb621fc010853a4372cce760653c9c Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 8 Jun 2021 18:29:55 +0200 Subject: [PATCH 26/72] xfdump: defensive static checks to ensure dump location always fits --- Firmware/xflash_dump.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/xflash_dump.cpp b/Firmware/xflash_dump.cpp index 65722b1c0..74b049f8f 100644 --- a/Firmware/xflash_dump.cpp +++ b/Firmware/xflash_dump.cpp @@ -7,7 +7,6 @@ #ifdef XFLASH_DUMP #include "xflash.h" - bool xfdump_check_state() { uint32_t magic; @@ -70,6 +69,7 @@ static void xfdump_dump_core(dump_header_t& hdr, uint32_t addr, uint8_t* buf, ui xflash_wait_busy(); // write data + static_assert(sizeof(dump_t::data) < RAMEND, "dump area size insufficient"); xflash_multipage_program(addr, buf, cnt); } From 56d0848ea9f776a36f0c2d300ef216b91ee53d47 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 8 Jun 2021 18:43:32 +0200 Subject: [PATCH 27/72] xfdump: fix size check --- Firmware/xflash_dump.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/xflash_dump.cpp b/Firmware/xflash_dump.cpp index 74b049f8f..655765b86 100644 --- a/Firmware/xflash_dump.cpp +++ b/Firmware/xflash_dump.cpp @@ -69,7 +69,7 @@ static void xfdump_dump_core(dump_header_t& hdr, uint32_t addr, uint8_t* buf, ui xflash_wait_busy(); // write data - static_assert(sizeof(dump_t::data) < RAMEND, "dump area size insufficient"); + static_assert(sizeof(dump_t::data) <= RAMEND, "dump area size insufficient"); xflash_multipage_program(addr, buf, cnt); } From 378f239ff05330545e097208546880383c138db8 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 8 Jun 2021 18:57:16 +0200 Subject: [PATCH 28/72] dcode_code: fix inverted define to print larger types --- Firmware/Dcodes.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index 9a78f296d..dc92d1433 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -145,9 +145,9 @@ void dcode_core(daddr_t addr_start, const daddr_t addr_end, const dcode_mem_t ty count = parse_hex(strchr_pointer + 1, data, 16); write_mem(addr_start, count, data, type); #if DADDR_SIZE > 16 - DBG(_N("%u bytes written to %S at address 0x%08x\n"), count, type_desc, addr_start); -#else DBG(_N("%lu bytes written to %S at address 0x%04lx\n"), count, type_desc, addr_start); +#else + DBG(_N("%u bytes written to %S at address 0x%08x\n"), count, type_desc, addr_start); #endif } print_mem(addr_start, count, type); From c2e64c8c6e44c0dd06d5297aaac90537f4251968 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 8 Jun 2021 19:08:03 +0200 Subject: [PATCH 29/72] xfdump: fix another off-by-one static size check --- Firmware/xflash_dump.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/xflash_dump.cpp b/Firmware/xflash_dump.cpp index 655765b86..0b9883a1b 100644 --- a/Firmware/xflash_dump.cpp +++ b/Firmware/xflash_dump.cpp @@ -63,7 +63,7 @@ static void xfdump_dump_core(dump_header_t& hdr, uint32_t addr, uint8_t* buf, ui xfdump_erase(); // write header - static_assert(sizeof(hdr) < 256, "header is larger than a single page write"); + static_assert(sizeof(hdr) <= 256, "header is larger than a single page write"); xflash_enable_wr(); xflash_page_program(DUMP_OFFSET, (uint8_t*)&hdr, sizeof(hdr)); xflash_wait_busy(); From 318ee695c247ebc1489a35ee0358f66d8d31317d Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 8 Jun 2021 19:50:43 +0200 Subject: [PATCH 30/72] xfdump_layout: add some comments --- Firmware/xflash_layout.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/xflash_layout.h b/Firmware/xflash_layout.h index f44b9c806..570098bd1 100644 --- a/Firmware/xflash_layout.h +++ b/Firmware/xflash_layout.h @@ -1,7 +1,7 @@ // XFLASH memory layout #pragma once #include -#include "bootapp.h" +#include "bootapp.h" // for RAMSIZE #include "config.h" #define XFLASH_SIZE 0x40000ul // size of XFLASH From fab04dbc6c43487b37e4a4c39e719f835ca2a0ae Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 8 Jun 2021 19:53:37 +0200 Subject: [PATCH 31/72] D6: remove option for unsupported models --- Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h | 1 - Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h | 1 - Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h | 1 - Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h | 1 - 4 files changed, 4 deletions(-) diff --git a/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h index f49f5e1c8..b05475abd 100644 --- a/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h @@ -125,7 +125,6 @@ //#define DEBUG_DCODE2 #define DEBUG_DCODE3 -//#define DEBUG_DCODE6 //#define DEBUG_BUILD #ifdef DEBUG_BUILD diff --git a/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h index 0d900508a..0750bc5c5 100644 --- a/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h @@ -126,7 +126,6 @@ //#define DEBUG_DCODE2 #define DEBUG_DCODE3 -//#define DEBUG_DCODE6 //#define DEBUG_BUILD #ifdef DEBUG_BUILD diff --git a/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h index 73eb52f69..d8a4158bf 100644 --- a/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h @@ -125,7 +125,6 @@ //#define DEBUG_DCODE2 #define DEBUG_DCODE3 -//#define DEBUG_DCODE6 //#define DEBUG_BUILD #ifdef DEBUG_BUILD diff --git a/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h index 738f421e2..9a25dce2f 100644 --- a/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h @@ -126,7 +126,6 @@ //#define DEBUG_DCODE2 #define DEBUG_DCODE3 -//#define DEBUG_DCODE6 //#define DEBUG_BUILD #ifdef DEBUG_BUILD From 8c3d76f85f041c604ce1c19b2bf43f7c2fde6bf7 Mon Sep 17 00:00:00 2001 From: Voinea Dragos Date: Wed, 9 Jun 2021 12:44:28 +0300 Subject: [PATCH 32/72] Fix millis reference --- Firmware/Dcodes.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index dc92d1433..69de8e111 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -935,9 +935,9 @@ void dcode_20() xfdump_full_dump_and_reset(); else { - unsigned long ts = millis(); + unsigned long ts = _millis(); xfdump_dump(); - ts = millis() - ts; + ts = _millis() - ts; DBG(_N("dump completed in %lums\n"), ts); } } From 1e786c7f55b9bdfc1c8d3daf56d10d3614bcf1ca Mon Sep 17 00:00:00 2001 From: Voinea Dragos Date: Wed, 9 Jun 2021 13:59:26 +0300 Subject: [PATCH 33/72] WDR crash initial --- Firmware/Marlin_main.cpp | 3 +++ Firmware/ultralcd.cpp | 9 ++++++++- Firmware/xflash_dump.cpp | 23 +++++++++++++++-------- Firmware/xflash_dump.h | 9 ++++++++- Firmware/xflash_layout.h | 2 +- Firmware/xyzcal.cpp | 3 +++ 6 files changed, 38 insertions(+), 11 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 2048b416d..dd7137376 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -1667,6 +1667,9 @@ void setup() KEEPALIVE_STATE(NOT_BUSY); #ifdef WATCHDOG wdt_enable(WDTO_4S); +#ifdef XFLASH_DUMP + WDTCSR |= (1 << WDIE); +#endif //XFLASH_DUMP #endif //WATCHDOG } diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 8edcf7070..3eecb7655 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -1811,6 +1811,12 @@ static void lcd_dump_memory() xfdump_dump(); lcd_return_to_status(); } + +static void lcd_wdr_crash() +{ + while (1); +} + #endif @@ -2007,6 +2013,7 @@ static void lcd_support_menu() #ifdef MENU_DUMP MENU_ITEM_FUNCTION_P(_i("Dump memory"), lcd_dump_memory); + MENU_ITEM_FUNCTION_P(PSTR("WDR crash"), lcd_wdr_crash); #endif #ifdef DEBUG_BUILD MENU_ITEM_SUBMENU_P(PSTR("Debug"), lcd_menu_debug);////MSG_DEBUG c=18 @@ -6704,7 +6711,7 @@ static void lcd_main_menu() void stack_error() { WRITE(BEEPER, HIGH); eeprom_update_byte((uint8_t*)EEPROM_CRASH_ACKNOWLEDGED, 0); - xfdump_full_dump_and_reset(true); + xfdump_full_dump_and_reset(dump_crash_source::stack_error); } #else void stack_error() { diff --git a/Firmware/xflash_dump.cpp b/Firmware/xflash_dump.cpp index 0b9883a1b..99d92b550 100644 --- a/Firmware/xflash_dump.cpp +++ b/Firmware/xflash_dump.cpp @@ -6,6 +6,14 @@ #include "xflash_dump.h" #ifdef XFLASH_DUMP #include "xflash.h" +#include "Marlin.h" + +ISR(WDT_vect) +{ + WRITE(BEEPER, 1); + eeprom_update_byte((uint8_t*)EEPROM_CRASH_ACKNOWLEDGED, 0); + xfdump_full_dump_and_reset(dump_crash_source::watchdog); +} bool xfdump_check_state() { @@ -25,10 +33,10 @@ bool xfdump_check_crash() if(!xfdump_check_state()) return false; - uint8_t crash; - xflash_rd_data(DUMP_OFFSET + offsetof(dump_t, header.crash), + dump_crash_source crash; + xflash_rd_data(DUMP_OFFSET + offsetof(dump_t, header.crash_type), (uint8_t*)&crash, sizeof(crash)); - return crash; + return (crash != dump_crash_source::manual); } @@ -79,7 +87,7 @@ void xfdump_dump() dump_header_t buf; buf.magic = DUMP_MAGIC; buf.regs_present = false; - buf.crash = false; + buf.crash_type = (uint8_t)dump_crash_source::manual; // write sram only xfdump_dump_core(buf, DUMP_OFFSET + offsetof(dump_t, data.sram), @@ -87,12 +95,12 @@ void xfdump_dump() } -void xfdump_full_dump_and_reset(bool crash) +void xfdump_full_dump_and_reset(dump_crash_source crash) { dump_header_t buf; buf.magic = DUMP_MAGIC; buf.regs_present = true; - buf.crash = crash; + buf.crash_type = (uint8_t)crash; // disable interrupts for a cleaner register dump cli(); @@ -101,7 +109,6 @@ void xfdump_full_dump_and_reset(bool crash) xfdump_dump_core(buf, DUMP_OFFSET + offsetof(dump_t, data), 0, RAMEND); // force a reset soon - wdt_enable(0); - while(true); + softReset(); } #endif diff --git a/Firmware/xflash_dump.h b/Firmware/xflash_dump.h index 8492523c3..7ad1c546b 100644 --- a/Firmware/xflash_dump.h +++ b/Firmware/xflash_dump.h @@ -8,7 +8,14 @@ bool xfdump_check_state(); // return true if a dump is present bool xfdump_check_crash(); // return true if a dump is present and is a crash dump void xfdump_dump(); // create a new SRAM memory dump +enum class dump_crash_source : uint8_t +{ + manual = 0, + stack_error, + watchdog, +}; + // create a new dump containing registers and SRAM, then reset -void xfdump_full_dump_and_reset(bool crash = false); +void xfdump_full_dump_and_reset(dump_crash_source crash = dump_crash_source::manual); #endif diff --git a/Firmware/xflash_layout.h b/Firmware/xflash_layout.h index 570098bd1..5bbe2a79d 100644 --- a/Firmware/xflash_layout.h +++ b/Firmware/xflash_layout.h @@ -20,7 +20,7 @@ struct dump_header_t uint32_t magic; uint8_t regs_present; // true when the lower segment containing registers is present - uint8_t crash; // true if triggered by EMERGENCY_DUMP + uint8_t crash_type; // uses values from dump_crash_source }; struct dump_data_t diff --git a/Firmware/xyzcal.cpp b/Firmware/xyzcal.cpp index ea92359ce..06544f196 100644 --- a/Firmware/xyzcal.cpp +++ b/Firmware/xyzcal.cpp @@ -163,6 +163,9 @@ void xyzcal_meassure_leave(void) ENABLE_STEPPER_DRIVER_INTERRUPT(); #ifdef WATCHDOG wdt_enable(WDTO_4S); +#ifdef XFLASH_DUMP + WDTCSR |= (1 << WDIE); +#endif //XFLASH_DUMP #endif //WATCHDOG sm4_stop_cb = 0; sm4_update_pos_cb = 0; From 094c577e9d8fdd88352459e7137f67cbaf200d5b Mon Sep 17 00:00:00 2001 From: Voinea Dragos Date: Wed, 9 Jun 2021 14:10:20 +0300 Subject: [PATCH 34/72] Fix XFLASH_DUMP print_mem --- Firmware/Dcodes.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index 69de8e111..f821c47fe 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -72,7 +72,7 @@ enum class dcode_mem_t:uint8_t { sram, eeprom, progmem, xflash }; void print_mem(daddr_t address, daddr_t count, dcode_mem_t type, uint8_t countperline = 16) { -#if defined(DEBUG_DCODE6) || defined(DEBUG_DCODES) +#if defined(DEBUG_DCODE6) || defined(DEBUG_DCODES) || defined(XFLASH_DUMP) if(type == dcode_mem_t::xflash) XFLASH_SPI_ENTER(); #endif @@ -89,7 +89,7 @@ void print_mem(daddr_t address, daddr_t count, dcode_mem_t type, uint8_t countpe case dcode_mem_t::sram: data = *((uint8_t*)address); break; case dcode_mem_t::eeprom: data = eeprom_read_byte((uint8_t*)address); break; case dcode_mem_t::progmem: break; -#if defined(DEBUG_DCODE6) || defined(DEBUG_DCODES) +#if defined(DEBUG_DCODE6) || defined(DEBUG_DCODES) || defined(XFLASH_DUMP) case dcode_mem_t::xflash: xflash_rd_data(address, &data, 1); break; #else case dcode_mem_t::xflash: break; From 0a77f2c02db1877e633b9092678ab61541182315 Mon Sep 17 00:00:00 2001 From: Voinea Dragos Date: Thu, 10 Jun 2021 11:58:46 +0300 Subject: [PATCH 35/72] Dump header as well --- Firmware/Dcodes.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index f821c47fe..9451308ee 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -950,8 +950,7 @@ void dcode_21() { KEEPALIVE_STATE(NOT_BUSY); DBG(_N("D21 - read crash dump\n")); - print_mem(DUMP_OFFSET + offsetof(dump_t, data), - DUMP_SIZE, dcode_mem_t::xflash); + print_mem(DUMP_OFFSET, sizeof(dump_t), dcode_mem_t::xflash); } } From 0362b6484f6295a9a38dc4c6937b7c3c48af1a0c Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Thu, 10 Jun 2021 16:24:52 +0200 Subject: [PATCH 36/72] xfdump_full_dump_and_reset: set a guaranteed minimum WDT Just prior to dumping, reset the WDT to a known-safe (and not too long) interval that guarantees a complete dump. --- Firmware/xflash_dump.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Firmware/xflash_dump.cpp b/Firmware/xflash_dump.cpp index 99d92b550..66a851128 100644 --- a/Firmware/xflash_dump.cpp +++ b/Firmware/xflash_dump.cpp @@ -105,10 +105,14 @@ void xfdump_full_dump_and_reset(dump_crash_source crash) // disable interrupts for a cleaner register dump cli(); + // ensure there's always enough time (with some margin) to dump + // dump time on w25x20cl: ~150ms + wdt_enable(WDTO_500MS); + // write all addressable ranges (this will trash bidirectional registers) xfdump_dump_core(buf, DUMP_OFFSET + offsetof(dump_t, data), 0, RAMEND); - // force a reset soon + // force a reset even sooner softReset(); } #endif From 63f870c08912f01adedf63893a37d090c9b6a384 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Thu, 10 Jun 2021 16:30:59 +0200 Subject: [PATCH 37/72] Enable the "WDR reset" menu item in DEBUG_BUILD only --- Firmware/ultralcd.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 3eecb7655..ba8f42e71 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -1812,13 +1812,15 @@ static void lcd_dump_memory() lcd_return_to_status(); } +#ifdef DEBUG_BUILD static void lcd_wdr_crash() { while (1); } - #endif +#endif //MENU_DUMP + //! @brief Show Support Menu //! @@ -2013,8 +2015,10 @@ static void lcd_support_menu() #ifdef MENU_DUMP MENU_ITEM_FUNCTION_P(_i("Dump memory"), lcd_dump_memory); +#ifdef DEBUG_BUILD MENU_ITEM_FUNCTION_P(PSTR("WDR crash"), lcd_wdr_crash); -#endif +#endif //DEBUG_BUILD +#endif //MENU_DUMP #ifdef DEBUG_BUILD MENU_ITEM_SUBMENU_P(PSTR("Debug"), lcd_menu_debug);////MSG_DEBUG c=18 #endif /* DEBUG_BUILD */ From c3756106688cae9dbb08e95ae5294e11a8cae749 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Thu, 10 Jun 2021 17:02:41 +0200 Subject: [PATCH 38/72] Move "WDR dump" inside EMERGENGENCY_DUMP --- Firmware/Marlin_main.cpp | 12 ++++++++++-- Firmware/ultralcd.cpp | 11 +++++------ Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h | 2 +- Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h | 2 +- Firmware/xflash_dump.cpp | 9 +-------- Firmware/xyzcal.cpp | 4 ++-- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index dd7137376..50d5bee3b 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -1667,12 +1667,20 @@ void setup() KEEPALIVE_STATE(NOT_BUSY); #ifdef WATCHDOG wdt_enable(WDTO_4S); -#ifdef XFLASH_DUMP +#ifdef EMERGENCY_DUMP WDTCSR |= (1 << WDIE); -#endif //XFLASH_DUMP +#endif //EMERGENCY_DUMP #endif //WATCHDOG } +#if defined(WATCHDOG) && defined(EMERGENCY_DUMP) +ISR(WDT_vect) +{ + WRITE(BEEPER, 1); + eeprom_update_byte((uint8_t*)EEPROM_CRASH_ACKNOWLEDGED, 0); + xfdump_full_dump_and_reset(dump_crash_source::watchdog); +} +#endif void trace(); diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index ba8f42e71..f9303b489 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -1811,16 +1811,15 @@ static void lcd_dump_memory() xfdump_dump(); lcd_return_to_status(); } +#endif //MENU_DUMP -#ifdef DEBUG_BUILD +#if defined(WATCHDOG) && defined(EMERGENCY_DUMP) && defined(DEBUG_BUILD) static void lcd_wdr_crash() { while (1); } #endif -#endif //MENU_DUMP - //! @brief Show Support Menu //! @@ -2015,11 +2014,11 @@ static void lcd_support_menu() #ifdef MENU_DUMP MENU_ITEM_FUNCTION_P(_i("Dump memory"), lcd_dump_memory); -#ifdef DEBUG_BUILD - MENU_ITEM_FUNCTION_P(PSTR("WDR crash"), lcd_wdr_crash); -#endif //DEBUG_BUILD #endif //MENU_DUMP #ifdef DEBUG_BUILD +#if defined(WATCHDOG) && defined(EMERGENCY_DUMP) + MENU_ITEM_FUNCTION_P(PSTR("WDR crash"), lcd_wdr_crash); +#endif MENU_ITEM_SUBMENU_P(PSTR("Debug"), lcd_menu_debug);////MSG_DEBUG c=18 #endif /* DEBUG_BUILD */ diff --git a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h index ab65d0245..b03fe7263 100644 --- a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h @@ -142,7 +142,7 @@ // Offline crash dumper //#define XFLASH_DUMP // enable dump functionality (including D20/D21/D22) //#define MENU_DUMP // enable "Memory dump" in Settings menu -//#define EMERGENCY_DUMP // trigger crash on stack corruption +//#define EMERGENCY_DUMP // trigger crash on stack corruption and WDR // Filament sensor #define FILAMENT_SENSOR diff --git a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h index 48154903e..934c0913c 100644 --- a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h @@ -144,7 +144,7 @@ // Offline crash dumper //#define XFLASH_DUMP // enable dump functionality (including D20/D21/D22) //#define MENU_DUMP // enable "Memory dump" in Settings menu -//#define EMERGENCY_DUMP // trigger crash on stack corruption +//#define EMERGENCY_DUMP // trigger crash on stack corruption and WDR // Filament sensor #define FILAMENT_SENSOR diff --git a/Firmware/xflash_dump.cpp b/Firmware/xflash_dump.cpp index 66a851128..5667e41c3 100644 --- a/Firmware/xflash_dump.cpp +++ b/Firmware/xflash_dump.cpp @@ -6,14 +6,7 @@ #include "xflash_dump.h" #ifdef XFLASH_DUMP #include "xflash.h" -#include "Marlin.h" - -ISR(WDT_vect) -{ - WRITE(BEEPER, 1); - eeprom_update_byte((uint8_t*)EEPROM_CRASH_ACKNOWLEDGED, 0); - xfdump_full_dump_and_reset(dump_crash_source::watchdog); -} +#include "Marlin.h" // for softReset bool xfdump_check_state() { diff --git a/Firmware/xyzcal.cpp b/Firmware/xyzcal.cpp index 06544f196..bc3353070 100644 --- a/Firmware/xyzcal.cpp +++ b/Firmware/xyzcal.cpp @@ -163,9 +163,9 @@ void xyzcal_meassure_leave(void) ENABLE_STEPPER_DRIVER_INTERRUPT(); #ifdef WATCHDOG wdt_enable(WDTO_4S); -#ifdef XFLASH_DUMP +#ifdef EMERGENCY_DUMP WDTCSR |= (1 << WDIE); -#endif //XFLASH_DUMP +#endif //EMERGENCY_DUMP #endif //WATCHDOG sm4_stop_cb = 0; sm4_update_pos_cb = 0; From 31f416fd5ee9070723885ea55a237455067d6fe2 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Thu, 10 Jun 2021 17:35:49 +0200 Subject: [PATCH 39/72] Rename dump_crash_source to dump_crash_reason --- Firmware/Marlin_main.cpp | 2 +- Firmware/ultralcd.cpp | 2 +- Firmware/xflash_dump.cpp | 14 +++++++------- Firmware/xflash_dump.h | 4 ++-- Firmware/xflash_layout.h | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 50d5bee3b..eec6591b9 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -1678,7 +1678,7 @@ ISR(WDT_vect) { WRITE(BEEPER, 1); eeprom_update_byte((uint8_t*)EEPROM_CRASH_ACKNOWLEDGED, 0); - xfdump_full_dump_and_reset(dump_crash_source::watchdog); + xfdump_full_dump_and_reset(dump_crash_reason::watchdog); } #endif diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index f9303b489..c07292456 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -6714,7 +6714,7 @@ static void lcd_main_menu() void stack_error() { WRITE(BEEPER, HIGH); eeprom_update_byte((uint8_t*)EEPROM_CRASH_ACKNOWLEDGED, 0); - xfdump_full_dump_and_reset(dump_crash_source::stack_error); + xfdump_full_dump_and_reset(dump_crash_reason::stack_error); } #else void stack_error() { diff --git a/Firmware/xflash_dump.cpp b/Firmware/xflash_dump.cpp index 5667e41c3..b9d2679a8 100644 --- a/Firmware/xflash_dump.cpp +++ b/Firmware/xflash_dump.cpp @@ -26,10 +26,10 @@ bool xfdump_check_crash() if(!xfdump_check_state()) return false; - dump_crash_source crash; - xflash_rd_data(DUMP_OFFSET + offsetof(dump_t, header.crash_type), - (uint8_t*)&crash, sizeof(crash)); - return (crash != dump_crash_source::manual); + dump_crash_reason reason; + xflash_rd_data(DUMP_OFFSET + offsetof(dump_t, header.crash_reason), + (uint8_t*)&reason, sizeof(reason)); + return (reason != dump_crash_reason::manual); } @@ -80,7 +80,7 @@ void xfdump_dump() dump_header_t buf; buf.magic = DUMP_MAGIC; buf.regs_present = false; - buf.crash_type = (uint8_t)dump_crash_source::manual; + buf.crash_reason = (uint8_t)dump_crash_reason::manual; // write sram only xfdump_dump_core(buf, DUMP_OFFSET + offsetof(dump_t, data.sram), @@ -88,12 +88,12 @@ void xfdump_dump() } -void xfdump_full_dump_and_reset(dump_crash_source crash) +void xfdump_full_dump_and_reset(dump_crash_reason reason) { dump_header_t buf; buf.magic = DUMP_MAGIC; buf.regs_present = true; - buf.crash_type = (uint8_t)crash; + buf.crash_reason = (uint8_t)reason; // disable interrupts for a cleaner register dump cli(); diff --git a/Firmware/xflash_dump.h b/Firmware/xflash_dump.h index 7ad1c546b..18e1c684d 100644 --- a/Firmware/xflash_dump.h +++ b/Firmware/xflash_dump.h @@ -8,7 +8,7 @@ bool xfdump_check_state(); // return true if a dump is present bool xfdump_check_crash(); // return true if a dump is present and is a crash dump void xfdump_dump(); // create a new SRAM memory dump -enum class dump_crash_source : uint8_t +enum class dump_crash_reason : uint8_t { manual = 0, stack_error, @@ -16,6 +16,6 @@ enum class dump_crash_source : uint8_t }; // create a new dump containing registers and SRAM, then reset -void xfdump_full_dump_and_reset(dump_crash_source crash = dump_crash_source::manual); +void xfdump_full_dump_and_reset(dump_crash_reason crash = dump_crash_reason::manual); #endif diff --git a/Firmware/xflash_layout.h b/Firmware/xflash_layout.h index 5bbe2a79d..31f67b7d6 100644 --- a/Firmware/xflash_layout.h +++ b/Firmware/xflash_layout.h @@ -20,7 +20,7 @@ struct dump_header_t uint32_t magic; uint8_t regs_present; // true when the lower segment containing registers is present - uint8_t crash_type; // uses values from dump_crash_source + uint8_t crash_reason; // uses values from dump_crash_source }; struct dump_data_t From 3187b96ca44498abaaf2207ad2d96ca6cdefc2b8 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Fri, 11 Jun 2021 19:21:51 +0200 Subject: [PATCH 40/72] xfdump: report to the host that a dump is available As suggested by @3d-gussner, announce to the host that a dump is available for retrieval using an action "dump_available". Any kind of dump is announced (even if manually triggered). To avoid reading from xflash twice, remove some duplication and return the crash reason directly in xfdump_check_state(). --- Firmware/Marlin_main.cpp | 30 +++++++++++++++++++++--------- Firmware/xflash_dump.cpp | 22 ++++++++-------------- Firmware/xflash_dump.h | 5 +++-- 3 files changed, 32 insertions(+), 25 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index eec6591b9..91da6cc96 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -108,7 +108,7 @@ #include "optiboot_xflash.h" #endif //XFLASH -#ifdef EMERGENCY_DUMP +#ifdef XFLASH_DUMP #include "xflash_dump.h" #endif @@ -1610,15 +1610,27 @@ void setup() if (tmc2130_home_enabled == 0xff) tmc2130_home_enabled = 0; #endif //TMC2130 -#ifdef EMERGENCY_DUMP - if(xfdump_check_crash() && eeprom_read_byte((uint8_t*)EEPROM_CRASH_ACKNOWLEDGED) != 1) +#ifdef XFLASH_DUMP { - // prevent the prompt to reappear once acknowledged - eeprom_update_byte((uint8_t*)EEPROM_CRASH_ACKNOWLEDGED, 1); - lcd_show_fullscreen_message_and_wait_P( - _i("!!!FIRMWARE CRASH!!!\n" - "Debug data available for analysis. " - "Contact support to submit details.")); + dump_crash_reason crash_reason; + if(xfdump_check_state(&crash_reason)) + { + // always signal to the host that a dump is available for retrieval + puts_P(_N("// action:dump_available")); + +#ifdef EMERGENCY_DUMP + if(crash_reason != dump_crash_reason::manual && + eeprom_read_byte((uint8_t*)EEPROM_CRASH_ACKNOWLEDGED) != 1) + { + // prevent the prompt to reappear once acknowledged + eeprom_update_byte((uint8_t*)EEPROM_CRASH_ACKNOWLEDGED, 1); + lcd_show_fullscreen_message_and_wait_P( + _i("!!!FIRMWARE CRASH!!!\n" + "Debug data available for analysis. " + "Contact support to submit details.")); + } +#endif + } } #endif diff --git a/Firmware/xflash_dump.cpp b/Firmware/xflash_dump.cpp index b9d2679a8..290a8d99a 100644 --- a/Firmware/xflash_dump.cpp +++ b/Firmware/xflash_dump.cpp @@ -8,28 +8,22 @@ #include "xflash.h" #include "Marlin.h" // for softReset -bool xfdump_check_state() +bool xfdump_check_state(dump_crash_reason* reason) { uint32_t magic; XFLASH_SPI_ENTER(); xflash_rd_data(DUMP_OFFSET + offsetof(dump_t, header.magic), (uint8_t*)&magic, sizeof(magic)); - - return magic == DUMP_MAGIC; -} - - -bool xfdump_check_crash() -{ - // check_state will call SPI_ENTER for us - if(!xfdump_check_state()) + if (magic != DUMP_MAGIC) return false; - dump_crash_reason reason; - xflash_rd_data(DUMP_OFFSET + offsetof(dump_t, header.crash_reason), - (uint8_t*)&reason, sizeof(reason)); - return (reason != dump_crash_reason::manual); + if (reason) + { + xflash_rd_data(DUMP_OFFSET + offsetof(dump_t, header.crash_reason), + (uint8_t*)reason, sizeof(*reason)); + } + return true; } diff --git a/Firmware/xflash_dump.h b/Firmware/xflash_dump.h index 18e1c684d..658ecd2dc 100644 --- a/Firmware/xflash_dump.h +++ b/Firmware/xflash_dump.h @@ -4,8 +4,6 @@ #ifdef XFLASH_DUMP void xfdump_reset(); // reset XFLASH dump state -bool xfdump_check_state(); // return true if a dump is present -bool xfdump_check_crash(); // return true if a dump is present and is a crash dump void xfdump_dump(); // create a new SRAM memory dump enum class dump_crash_reason : uint8_t @@ -15,6 +13,9 @@ enum class dump_crash_reason : uint8_t watchdog, }; +// return true if a dump is present, save type in "reason" if provided +bool xfdump_check_state(dump_crash_reason* reason = NULL); + // create a new dump containing registers and SRAM, then reset void xfdump_full_dump_and_reset(dump_crash_reason crash = dump_crash_reason::manual); From 966365367110c4a56a0ea95c3c510a2b2828faae Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sat, 12 Jun 2021 12:05:02 +0200 Subject: [PATCH 41/72] xfdump_erase: remove redundant XFLASH_SPI_ENTER() --- Firmware/xflash_dump.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Firmware/xflash_dump.cpp b/Firmware/xflash_dump.cpp index 290a8d99a..3f2938904 100644 --- a/Firmware/xflash_dump.cpp +++ b/Firmware/xflash_dump.cpp @@ -38,7 +38,6 @@ void xfdump_reset() static void xfdump_erase() { - XFLASH_SPI_ENTER(); for(uint32_t addr = DUMP_OFFSET; addr < DUMP_OFFSET + DUMP_SIZE; addr += 4096) From f18d4757c6345344df9c9112f2a37f13d8ad7365 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sat, 12 Jun 2021 12:08:53 +0200 Subject: [PATCH 42/72] Introduce STACK_GUARD_MARGIN in all variants Create a gap between the BSS and the stack guard. Set this gap (STACK_GUARD_MARGIN) to 32 bytes in all variants. The gap serves two purposes: - Detect a stack overflow earlier (falsely triggering in overtight situations is OK!), so that we can hopefully avoid smashing the heap and have a clean view during the dump. - Reserve spack space itself for the stack dumping machinery, which is going to grow the stack even further. Remove get_stack_guard_test_value() which was unused. --- Firmware/SdFatUtil.cpp | 12 ++---------- Firmware/SdFatUtil.h | 3 +-- Firmware/variants/1_75mm_MK2-RAMBo10a-E3Dv6full.h | 1 + Firmware/variants/1_75mm_MK2-RAMBo13a-E3Dv6full.h | 1 + Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h | 1 + Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h | 1 + Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h | 1 + Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h | 1 + Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h | 1 + Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h | 1 + 10 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Firmware/SdFatUtil.cpp b/Firmware/SdFatUtil.cpp index 51da4ee2b..50206ab94 100644 --- a/Firmware/SdFatUtil.cpp +++ b/Firmware/SdFatUtil.cpp @@ -48,24 +48,16 @@ void SdFatUtil::set_stack_guard() { uint32_t *stack_guard; - stack_guard = (uint32_t*)&__bss_end; + stack_guard = (uint32_t*)(&__bss_end + STACK_GUARD_MARGIN); *stack_guard = STACK_GUARD_TEST_VALUE; } bool SdFatUtil::test_stack_integrity() { - uint32_t* stack_guard = (uint32_t*)&__bss_end; + uint32_t* stack_guard = (uint32_t*)(&__bss_end + STACK_GUARD_MARGIN); return (*stack_guard == STACK_GUARD_TEST_VALUE); } -uint32_t SdFatUtil::get_stack_guard_test_value() -{ - uint32_t* stack_guard; - uint32_t output; - stack_guard = (uint32_t*)&__bss_end; - output = *stack_guard; - return(output); -} //------------------------------------------------------------------------------ /** %Print a string in flash memory. * diff --git a/Firmware/SdFatUtil.h b/Firmware/SdFatUtil.h index c42b74b1c..2a70d98a1 100644 --- a/Firmware/SdFatUtil.h +++ b/Firmware/SdFatUtil.h @@ -41,11 +41,10 @@ namespace SdFatUtil { void SerialPrintln_P(PGM_P str); void set_stack_guard(); bool test_stack_integrity(); - uint32_t get_stack_guard_test_value(); } using namespace SdFatUtil; // NOLINT #endif // #define SdFatUtil_h -#endif \ No newline at end of file +#endif diff --git a/Firmware/variants/1_75mm_MK2-RAMBo10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK2-RAMBo10a-E3Dv6full.h index 4c20082e9..7ccd9151f 100644 --- a/Firmware/variants/1_75mm_MK2-RAMBo10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK2-RAMBo10a-E3Dv6full.h @@ -418,6 +418,7 @@ THERMISTORS SETTINGS #endif #define STACK_GUARD_TEST_VALUE 0xA2A2 +#define STACK_GUARD_MARGIN 32 #define MAX_BED_TEMP_CALIBRATION 50 #define MAX_HOTEND_TEMP_CALIBRATION 50 diff --git a/Firmware/variants/1_75mm_MK2-RAMBo13a-E3Dv6full.h b/Firmware/variants/1_75mm_MK2-RAMBo13a-E3Dv6full.h index 35313a412..4686f0978 100644 --- a/Firmware/variants/1_75mm_MK2-RAMBo13a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK2-RAMBo13a-E3Dv6full.h @@ -407,6 +407,7 @@ THERMISTORS SETTINGS #endif #define STACK_GUARD_TEST_VALUE 0xA2A2 +#define STACK_GUARD_MARGIN 32 #define MAX_BED_TEMP_CALIBRATION 50 #define MAX_HOTEND_TEMP_CALIBRATION 50 diff --git a/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h index b05475abd..fa7f26902 100644 --- a/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h @@ -469,6 +469,7 @@ #define TEMP_SENSOR_PINDA 1 #define STACK_GUARD_TEST_VALUE 0xA2A2 +#define STACK_GUARD_MARGIN 32 #define MAX_BED_TEMP_CALIBRATION 50 #define MAX_HOTEND_TEMP_CALIBRATION 50 diff --git a/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h index 0750bc5c5..10aa14f90 100644 --- a/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h @@ -470,6 +470,7 @@ #define TEMP_SENSOR_PINDA 1 #define STACK_GUARD_TEST_VALUE 0xA2A2 +#define STACK_GUARD_MARGIN 32 #define MAX_BED_TEMP_CALIBRATION 50 #define MAX_HOTEND_TEMP_CALIBRATION 50 diff --git a/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h index d8a4158bf..4540fd729 100644 --- a/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h @@ -469,6 +469,7 @@ #define TEMP_SENSOR_PINDA 1 #define STACK_GUARD_TEST_VALUE 0xA2A2 +#define STACK_GUARD_MARGIN 32 #define MAX_BED_TEMP_CALIBRATION 50 #define MAX_HOTEND_TEMP_CALIBRATION 50 diff --git a/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h index 9a25dce2f..53773e97c 100644 --- a/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h @@ -470,6 +470,7 @@ #define TEMP_SENSOR_PINDA 1 #define STACK_GUARD_TEST_VALUE 0xA2A2 +#define STACK_GUARD_MARGIN 32 #define MAX_BED_TEMP_CALIBRATION 50 #define MAX_HOTEND_TEMP_CALIBRATION 50 diff --git a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h index b03fe7263..f6b178896 100644 --- a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h @@ -598,6 +598,7 @@ #define TEMP_SENSOR_AMBIENT 2000 #define STACK_GUARD_TEST_VALUE 0xA2A2 +#define STACK_GUARD_MARGIN 32 #define MAX_BED_TEMP_CALIBRATION 50 #define MAX_HOTEND_TEMP_CALIBRATION 50 diff --git a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h index 934c0913c..92698b47a 100644 --- a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h @@ -602,6 +602,7 @@ #define TEMP_SENSOR_AMBIENT 2000 #define STACK_GUARD_TEST_VALUE 0xA2A2 +#define STACK_GUARD_MARGIN 32 #define MAX_BED_TEMP_CALIBRATION 50 #define MAX_HOTEND_TEMP_CALIBRATION 50 From f7dc8dcaef7ea2c81534f6b2efbb4608da68ae18 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sat, 12 Jun 2021 13:16:12 +0200 Subject: [PATCH 43/72] Fix usage of RAMEND RAMEND is the last valid address, not one-past as I expected it to be... --- Firmware/Dcodes.cpp | 2 +- Firmware/bootapp.h | 2 +- Firmware/xflash_dump.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index 9451308ee..1fbca4c60 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -278,7 +278,7 @@ void dcode_1() */ void dcode_2() { - dcode_core(RAMSTART, RAMEND, dcode_mem_t::sram, 2, _N("SRAM")); + dcode_core(RAMSTART, RAMEND+1, dcode_mem_t::sram, 2, _N("SRAM")); } #endif diff --git a/Firmware/bootapp.h b/Firmware/bootapp.h index 44e1d16d2..9a77c5abd 100644 --- a/Firmware/bootapp.h +++ b/Firmware/bootapp.h @@ -7,7 +7,7 @@ #include -#define RAMSIZE (RAMEND-RAMSTART) +#define RAMSIZE (RAMEND+1-RAMSTART) #define boot_src_addr (*((uint32_t*)(RAMSIZE - 16))) #define boot_dst_addr (*((uint32_t*)(RAMSIZE - 12))) #define boot_copy_size (*((uint16_t*)(RAMSIZE - 8))) diff --git a/Firmware/xflash_dump.cpp b/Firmware/xflash_dump.cpp index 3f2938904..8b4ab9955 100644 --- a/Firmware/xflash_dump.cpp +++ b/Firmware/xflash_dump.cpp @@ -63,7 +63,7 @@ static void xfdump_dump_core(dump_header_t& hdr, uint32_t addr, uint8_t* buf, ui xflash_wait_busy(); // write data - static_assert(sizeof(dump_t::data) <= RAMEND, "dump area size insufficient"); + static_assert(sizeof(dump_t::data) <= RAMEND+1, "dump area size insufficient"); xflash_multipage_program(addr, buf, cnt); } @@ -96,7 +96,7 @@ void xfdump_full_dump_and_reset(dump_crash_reason reason) wdt_enable(WDTO_500MS); // write all addressable ranges (this will trash bidirectional registers) - xfdump_dump_core(buf, DUMP_OFFSET + offsetof(dump_t, data), 0, RAMEND); + xfdump_dump_core(buf, DUMP_OFFSET + offsetof(dump_t, data), 0, RAMEND+1); // force a reset even sooner softReset(); From bd57e004486a8f6b02fc5f47ae7b15096a1ec396 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sat, 12 Jun 2021 13:37:20 +0200 Subject: [PATCH 44/72] Implement an online crash dumper for MK2.5 boards When XFLASH is not available, allow users to request _online_ crash dumps by using D23 (since these require active user cooperation). Once enabled, instead of just rebooting, dump memory directly to the serial. As similarly done with EMERGENCY_DUMP, we have two features that can be enabled: EMERGENCY_SERIAL_DUMP: enables dumping on crash after being requested MENU_SERIAL_DUMP: allow triggering the same manually through the support menu. --- Firmware/Dcodes.cpp | 28 +++++++++++++++++++ Firmware/Dcodes.h | 6 ++++ Firmware/Marlin_main.cpp | 28 +++++++++++++++++-- Firmware/config.h | 13 +++++++++ Firmware/ultralcd.cpp | 28 ++++++++++++++++--- .../variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h | 4 +++ .../variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h | 4 +++ .../1_75mm_MK25S-RAMBo10a-E3Dv6full.h | 4 +++ .../1_75mm_MK25S-RAMBo13a-E3Dv6full.h | 4 +++ .../variants/1_75mm_MK3-EINSy10a-E3Dv6full.h | 4 +++ .../variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h | 4 +++ Firmware/xflash_dump.h | 9 +++--- Firmware/xyzcal.cpp | 4 +-- 13 files changed, 126 insertions(+), 14 deletions(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index 1fbca4c60..e9ba04545 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -965,3 +965,31 @@ void dcode_22() } } #endif + +#ifdef EMERGENCY_SERIAL_DUMP +#include "xflash_dump.h" + +bool emergency_serial_dump = false; + +void serial_dump_and_reset(dump_crash_reason reason) +{ + // we're being called from a live state, so shut off interrupts and heaters + cli(); + wdt_enable(WDTO_15MS); + disable_heater(); + + // this function can also be called from within a corrupted state, so not use + // printf family of functions that use the heap or grow the stack. + SERIAL_ECHOLNPGM("D23 - emergency serial dump"); + SERIAL_ECHOPGM("reason: "); + SERIAL_ECHOLN((unsigned)reason); + + // disable interrupts from now on to avoid wdt while dumping + wdt_disable(); + print_mem(0, RAMEND+1, dcode_mem_t::sram); + SERIAL_ECHOLNRPGM(MSG_OK); + + // reset soon + softReset(); +} +#endif diff --git a/Firmware/Dcodes.h b/Firmware/Dcodes.h index 4e37cc243..c4b470e4b 100644 --- a/Firmware/Dcodes.h +++ b/Firmware/Dcodes.h @@ -35,6 +35,12 @@ extern void dcode_21(); //D21 - Print crash dump to serial extern void dcode_22(); //D22 - Clear crash dump state #endif +#ifdef EMERGENCY_SERIAL_DUMP +#include "xflash_dump.h" +extern bool emergency_serial_dump; +extern void serial_dump_and_reset(dump_crash_reason); +#endif + #ifdef HEATBED_ANALYSIS extern void dcode_80(); //D80 - Bed check. This command will log data to SD card file "mesh.txt". extern void dcode_81(); //D81 - Bed analysis. This command will log data to SD card file "wldsd.txt". diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 91da6cc96..7656ddcd6 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -1679,18 +1679,24 @@ void setup() KEEPALIVE_STATE(NOT_BUSY); #ifdef WATCHDOG wdt_enable(WDTO_4S); -#ifdef EMERGENCY_DUMP +#ifdef EMERGENCY_HANDLERS WDTCSR |= (1 << WDIE); -#endif //EMERGENCY_DUMP +#endif //EMERGENCY_HANDLERS #endif //WATCHDOG } -#if defined(WATCHDOG) && defined(EMERGENCY_DUMP) +#if defined(WATCHDOG) && defined(EMERGENCY_HANDLERS) ISR(WDT_vect) { WRITE(BEEPER, 1); +#ifdef EMERGENCY_DUMP eeprom_update_byte((uint8_t*)EEPROM_CRASH_ACKNOWLEDGED, 0); xfdump_full_dump_and_reset(dump_crash_reason::watchdog); +#else //EMERGENCY_SERIAL_DUMP + if(emergency_serial_dump) + serial_dump_and_reset(dump_crash_reason::watchdog); + softReset(); +#endif } #endif @@ -9292,6 +9298,22 @@ Sigma_Exit: dcode_22(); break; }; +#endif //XFLASH_DUMP + +#ifdef EMERGENCY_SERIAL_DUMP + /*! + ### D23 - Request emergency dump on serial + On boards without offline dump support, request online dumps to the serial port on firmware faults. + When online dumps are enabled, the FW will dump memory on the serial before resetting. + #### Usage + + D23 [R] + #### Parameters + - `R` - Disable online dumps. + */ + case 23: { + emergency_serial_dump = !code_seen('R'); + }; #endif #ifdef HEATBED_ANALYSIS diff --git a/Firmware/config.h b/Firmware/config.h index fa86f4567..5adba50df 100644 --- a/Firmware/config.h +++ b/Firmware/config.h @@ -76,4 +76,17 @@ #error "MENU_DUMP and EMERGENCY_DUMP require XFLASH_DUMP" #endif +// Support for serial dumps is mutually exclusive with XFLASH_DUMP features +#if defined(EMERGENCY_DUMP) && defined(EMERGENCY_SERIAL_DUMP) +#error "EMERGENCY_DUMP and EMERGENCY_SERIAL_DUMP are mutually exclusive" +#endif +#if defined(MENU_DUMP) && defined(MENU_SERIAL_DUMP) +#error "MENU_DUMP and MENU_SERIAL_DUMP are mutually exclusive" +#endif + +// Reduce internal duplication +#if defined(EMERGENCY_DUMP) || defined(EMERGENCY_SERIAL_DUMP) +#define EMERGENCY_HANDLERS +#endif + #endif //_CONFIG_H diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index c07292456..fcf2e4584 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -1812,8 +1812,16 @@ static void lcd_dump_memory() lcd_return_to_status(); } #endif //MENU_DUMP +#ifdef MENU_SERIAL_DUMP +#include "Dcodes.h" -#if defined(WATCHDOG) && defined(EMERGENCY_DUMP) && defined(DEBUG_BUILD) +static void lcd_serial_dump() +{ + serial_dump_and_reset(dump_crash_reason::manual); +} +#endif //MENU_SERIAL_DUMP + +#if defined(WATCHDOG) && defined(DEBUG_BUILD) && defined(EMERGENCY_HANDLERS) static void lcd_wdr_crash() { while (1); @@ -2015,8 +2023,12 @@ static void lcd_support_menu() #ifdef MENU_DUMP MENU_ITEM_FUNCTION_P(_i("Dump memory"), lcd_dump_memory); #endif //MENU_DUMP +#ifdef MENU_SERIAL_DUMP + if (emergency_serial_dump) + MENU_ITEM_FUNCTION_P(_i("Dump to serial"), lcd_serial_dump); +#endif #ifdef DEBUG_BUILD -#if defined(WATCHDOG) && defined(EMERGENCY_DUMP) +#if defined(WATCHDOG) && defined(EMERGENCY_HANDLERS) MENU_ITEM_FUNCTION_P(PSTR("WDR crash"), lcd_wdr_crash); #endif MENU_ITEM_SUBMENU_P(PSTR("Debug"), lcd_menu_debug);////MSG_DEBUG c=18 @@ -6716,14 +6728,22 @@ void stack_error() { eeprom_update_byte((uint8_t*)EEPROM_CRASH_ACKNOWLEDGED, 0); xfdump_full_dump_and_reset(dump_crash_reason::stack_error); } -#else +#else //EMERGENCY_DUMP +#ifdef EMERGENCY_SERIAL_DUMP +#include "Dcodes.h" +#endif + void stack_error() { +#ifdef EMERGENCY_SERIAL_DUMP + if (emergency_serial_dump) + serial_dump_and_reset(dump_crash_reason::stack_error); +#endif Sound_MakeCustom(1000,0,true); lcd_display_message_fullscreen_P(_i("Error - static memory has been overwritten"));////MSG_STACK_ERROR c=20 r=4 //err_triggered = 1; while (1) delay_keep_alive(1000); } -#endif +#endif //EMERGENCY_DUMP #ifdef DEBUG_STEPPER_TIMER_MISSED bool stepper_timer_overflow_state = false; diff --git a/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h index fa7f26902..3cbc3829f 100644 --- a/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h @@ -119,6 +119,10 @@ #define DEFAULT_SAFETYTIMER_TIME_MINS 30 #define FARM_DEFAULT_SAFETYTIMER_TIME_ms (45*60*1000ul) +// Online crash dumper +//#define EMERGENCY_SERIAL_DUMP // Request dump via serial on stack corruption and WDR +//#define MENU_SERIAL_DUMP // Enable "Memory dump" in Settings menu + // Filament sensor #define FILAMENT_SENSOR #define PAT9125 diff --git a/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h index 10aa14f90..9b4e591ae 100644 --- a/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h @@ -120,6 +120,10 @@ #define DEFAULT_SAFETYTIMER_TIME_MINS 30 #define FARM_DEFAULT_SAFETYTIMER_TIME_ms (45*60*1000ul) +// Online crash dumper +//#define EMERGENCY_SERIAL_DUMP // Request dump via serial on stack corruption and WDR +//#define MENU_SERIAL_DUMP // Enable "Memory dump" in Settings menu + // Filament sensor #define FILAMENT_SENSOR #define PAT9125 diff --git a/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h index 4540fd729..74ef38b6e 100644 --- a/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h @@ -119,6 +119,10 @@ #define DEFAULT_SAFETYTIMER_TIME_MINS 30 #define FARM_DEFAULT_SAFETYTIMER_TIME_ms (45*60*1000ul) +// Online crash dumper +//#define EMERGENCY_SERIAL_DUMP // Request dump via serial on stack corruption and WDR +//#define MENU_SERIAL_DUMP // Enable "Memory dump" in Settings menu + // Filament sensor #define FILAMENT_SENSOR #define IR_SENSOR diff --git a/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h index 53773e97c..177586135 100644 --- a/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h @@ -120,6 +120,10 @@ #define DEFAULT_SAFETYTIMER_TIME_MINS 30 #define FARM_DEFAULT_SAFETYTIMER_TIME_ms (45*60*1000ul) +// Online crash dumper +//#define EMERGENCY_SERIAL_DUMP // Request dump via serial on stack corruption and WDR +//#define MENU_SERIAL_DUMP // Enable "Memory dump" in Settings menu + // Filament sensor #define FILAMENT_SENSOR #define IR_SENSOR diff --git a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h index f6b178896..66643556a 100644 --- a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h @@ -144,6 +144,10 @@ //#define MENU_DUMP // enable "Memory dump" in Settings menu //#define EMERGENCY_DUMP // trigger crash on stack corruption and WDR +// Online crash dumper +//#define EMERGENCY_SERIAL_DUMP // Request dump via serial on stack corruption and WDR +//#define MENU_SERIAL_DUMP // Enable "Memory dump" in Settings menu + // Filament sensor #define FILAMENT_SENSOR #define PAT9125 diff --git a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h index 92698b47a..842ff40be 100644 --- a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h @@ -146,6 +146,10 @@ //#define MENU_DUMP // enable "Memory dump" in Settings menu //#define EMERGENCY_DUMP // trigger crash on stack corruption and WDR +// Online crash dumper +//#define EMERGENCY_SERIAL_DUMP // Request dump via serial on stack corruption and WDR +//#define MENU_SERIAL_DUMP // Enable "Memory dump" in Settings menu + // Filament sensor #define FILAMENT_SENSOR #define IR_SENSOR diff --git a/Firmware/xflash_dump.h b/Firmware/xflash_dump.h index 658ecd2dc..f517a5921 100644 --- a/Firmware/xflash_dump.h +++ b/Firmware/xflash_dump.h @@ -1,10 +1,6 @@ // XFLASH dumper #pragma once #include "xflash_layout.h" -#ifdef XFLASH_DUMP - -void xfdump_reset(); // reset XFLASH dump state -void xfdump_dump(); // create a new SRAM memory dump enum class dump_crash_reason : uint8_t { @@ -13,10 +9,13 @@ enum class dump_crash_reason : uint8_t watchdog, }; +#ifdef XFLASH_DUMP +void xfdump_reset(); // reset XFLASH dump state +void xfdump_dump(); // create a new SRAM memory dump + // return true if a dump is present, save type in "reason" if provided bool xfdump_check_state(dump_crash_reason* reason = NULL); // create a new dump containing registers and SRAM, then reset void xfdump_full_dump_and_reset(dump_crash_reason crash = dump_crash_reason::manual); - #endif diff --git a/Firmware/xyzcal.cpp b/Firmware/xyzcal.cpp index bc3353070..cc2d940df 100644 --- a/Firmware/xyzcal.cpp +++ b/Firmware/xyzcal.cpp @@ -163,9 +163,9 @@ void xyzcal_meassure_leave(void) ENABLE_STEPPER_DRIVER_INTERRUPT(); #ifdef WATCHDOG wdt_enable(WDTO_4S); -#ifdef EMERGENCY_DUMP +#ifdef EMERGENCY_HANDLERS WDTCSR |= (1 << WDIE); -#endif //EMERGENCY_DUMP +#endif //EMERGENCY_HANDLERS #endif //WATCHDOG sm4_stop_cb = 0; sm4_update_pos_cb = 0; From e28301f391f4c71ec012b65dc9e2d8c02d44f920 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sat, 12 Jun 2021 14:41:54 +0200 Subject: [PATCH 45/72] Report crash also in MK2.5, fix stack_error abuse Rename EEPROM_CRASH_ACKNOWLEDGED to EEPROM_FW_CRASH_FLAG. Use EEPROM_FW_CRASH_FLAG to always set the last crash reason, which simplifies handling between the online/offline variants. Make stack_error safe, by setting the flag and restarting immediately, so that the error can be shown after restart. --- Firmware/Marlin_main.cpp | 82 +++++++++++++++++++++++++++------------- Firmware/eeprom.h | 6 +-- Firmware/ultralcd.cpp | 23 +++++------ 3 files changed, 67 insertions(+), 44 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 7656ddcd6..54d0b9c24 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -995,6 +995,55 @@ void list_sec_lang_from_external_flash() #endif //(LANG_MODE != 0) +static void fw_crash_init() +{ +#ifdef XFLASH_DUMP + dump_crash_reason crash_reason; + if(xfdump_check_state(&crash_reason)) + { + // always signal to the host that a dump is available for retrieval + puts_P(_N("// action:dump_available")); + +#ifdef EMERGENCY_DUMP + if(crash_reason != dump_crash_reason::manual && + eeprom_read_byte((uint8_t*)EEPROM_FW_CRASH_FLAG) != 0xFF) + { + lcd_show_fullscreen_message_and_wait_P( + _i("!!!FIRMWARE CRASH!!!\n" + "Debug data available for analysis. " + "Contact support to submit details.")); + } +#endif + } +#else //XFLASH_DUMP + dump_crash_reason crash_reason = (dump_crash_reason)eeprom_read_byte((uint8_t*)EEPROM_FW_CRASH_FLAG); + if(crash_reason != dump_crash_reason::manual && (uint8_t)crash_reason != 0xFF) + { + lcd_beeper_quick_feedback(); + lcd_clear(); + + lcd_puts_P(_i("!!!FIRMWARE CRASH!!!\nCrash reason:\n")); + switch(crash_reason) + { + case dump_crash_reason::stack_error: + lcd_puts_P(_i("Static memory has\nbeen overwritten")); + break; + case dump_crash_reason::watchdog: + lcd_puts_P(_i("Watchdog timeout")); + break; + default: + lcd_print((uint8_t)crash_reason); + break; + } + lcd_wait_for_click(); + } +#endif //XFLASH_DUMP + + // prevent crash prompts to reappear once acknowledged + eeprom_update_byte((uint8_t*)EEPROM_FW_CRASH_FLAG, 0xFF); +} + + static void xflash_err_msg() { lcd_clear(); @@ -1610,29 +1659,8 @@ void setup() if (tmc2130_home_enabled == 0xff) tmc2130_home_enabled = 0; #endif //TMC2130 -#ifdef XFLASH_DUMP - { - dump_crash_reason crash_reason; - if(xfdump_check_state(&crash_reason)) - { - // always signal to the host that a dump is available for retrieval - puts_P(_N("// action:dump_available")); - -#ifdef EMERGENCY_DUMP - if(crash_reason != dump_crash_reason::manual && - eeprom_read_byte((uint8_t*)EEPROM_CRASH_ACKNOWLEDGED) != 1) - { - // prevent the prompt to reappear once acknowledged - eeprom_update_byte((uint8_t*)EEPROM_CRASH_ACKNOWLEDGED, 1); - lcd_show_fullscreen_message_and_wait_P( - _i("!!!FIRMWARE CRASH!!!\n" - "Debug data available for analysis. " - "Contact support to submit details.")); - } -#endif - } - } -#endif + // report crash failures + fw_crash_init(); #ifdef UVLO_SUPPORT if (eeprom_read_byte((uint8_t*)EEPROM_UVLO) != 0) { //previous print was terminated by UVLO @@ -1688,15 +1716,15 @@ void setup() #if defined(WATCHDOG) && defined(EMERGENCY_HANDLERS) ISR(WDT_vect) { - WRITE(BEEPER, 1); + WRITE(BEEPER, HIGH); + eeprom_update_byte((uint8_t*)EEPROM_FW_CRASH_FLAG, (uint8_t)dump_crash_reason::watchdog); #ifdef EMERGENCY_DUMP - eeprom_update_byte((uint8_t*)EEPROM_CRASH_ACKNOWLEDGED, 0); xfdump_full_dump_and_reset(dump_crash_reason::watchdog); -#else //EMERGENCY_SERIAL_DUMP +#elif defined(EMERGENCY_SERIAL_DUMP) if(emergency_serial_dump) serial_dump_and_reset(dump_crash_reason::watchdog); - softReset(); #endif + softReset(); } #endif diff --git a/Firmware/eeprom.h b/Firmware/eeprom.h index e70227c05..62aafe424 100644 --- a/Firmware/eeprom.h +++ b/Firmware/eeprom.h @@ -327,7 +327,7 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP | 0x0D05 3333 | uint32_t | EEPROM_JOB_ID | ??? | 00 00 00 00h | Job ID used by host software | D3 only | D3 Ax0d05 C4 | 0x0D04 3332 | uint8_t | EEPROM_ECOOL_ENABLE | ffh 255 | ^ | Disable extruder motor scaling for non-farm print | LCD menu | D3 Ax0d04 C1 | ^ | ^ | ^ | 2ah 42 | ^ | Enable extruder motor scaling for non-farm print | ^ | D3 Ax0d04 C1 -| 0x0D03 3321 | uint8_t | EEPROM_CRASH_ACKNOWLEDGED | 01h 1 | ff/00 | Disable crash report after first acknowledgment | D21/D22 | D3 Ax0d03 C1 +| 0x0D03 3321 | uint8_t | EEPROM_FW_CRASH_FLAG | 01h 1 | ff/00 | Last FW crash reason (dump_crash_reason) | D21/D22 | D3 Ax0d03 C1 | Address begin | Bit/Type | Name | Valid values | Default/FactoryReset | Description | Gcode/Function| Debug code | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: @@ -542,10 +542,10 @@ static Sheets * const EEPROM_Sheets_base = (Sheets*)(EEPROM_SHEETS_BASE); #define EEPROM_JOB_ID (EEPROM_UVLO_TRAVEL_ACCELL-4) //uint32_t #define EEPROM_ECOOL_ENABLE (EEPROM_JOB_ID-1) // uint8_t -#define EEPROM_CRASH_ACKNOWLEDGED (EEPROM_ECOOL_ENABLE-1) // uint8_t +#define EEPROM_FW_CRASH_FLAG (EEPROM_ECOOL_ENABLE-1) // uint8_t //This is supposed to point to last item to allow EEPROM overrun check. Please update when adding new items. -#define EEPROM_LAST_ITEM EEPROM_CRASH_ACKNOWLEDGED +#define EEPROM_LAST_ITEM EEPROM_FW_CRASH_FLAG // !!!!! // !!!!! this is end of EEPROM section ... all updates MUST BE inserted before this mark !!!!! // !!!!! diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index fcf2e4584..1820d0e62 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -6720,30 +6720,25 @@ static void lcd_main_menu() } + #ifdef EMERGENCY_DUMP #include "xflash_dump.h" - -void stack_error() { - WRITE(BEEPER, HIGH); - eeprom_update_byte((uint8_t*)EEPROM_CRASH_ACKNOWLEDGED, 0); - xfdump_full_dump_and_reset(dump_crash_reason::stack_error); -} -#else //EMERGENCY_DUMP -#ifdef EMERGENCY_SERIAL_DUMP +#elif defined(EMERGENCY_SERIAL_DUMP) #include "Dcodes.h" #endif void stack_error() { -#ifdef EMERGENCY_SERIAL_DUMP + WRITE(BEEPER, HIGH); + eeprom_update_byte((uint8_t*)EEPROM_FW_CRASH_FLAG, (uint8_t)dump_crash_reason::stack_error); +#ifdef EMERGENCY_DUMP + xfdump_full_dump_and_reset(dump_crash_reason::stack_error); +#elif defined(EMERGENCY_SERIAL_DUMP) if (emergency_serial_dump) serial_dump_and_reset(dump_crash_reason::stack_error); #endif - Sound_MakeCustom(1000,0,true); - lcd_display_message_fullscreen_P(_i("Error - static memory has been overwritten"));////MSG_STACK_ERROR c=20 r=4 - //err_triggered = 1; - while (1) delay_keep_alive(1000); + softReset(); } -#endif //EMERGENCY_DUMP + #ifdef DEBUG_STEPPER_TIMER_MISSED bool stepper_timer_overflow_state = false; From 449510392d7a5b3cb87b49adfc6fbac162d599e8 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sat, 12 Jun 2021 15:09:03 +0200 Subject: [PATCH 46/72] Untangle a bit some recursive include mess --- Firmware/Marlin_main.cpp | 1 + Firmware/cardreader.cpp | 2 ++ Firmware/mmu.cpp | 1 + Firmware/temperature.cpp | 2 ++ Firmware/ultralcd.cpp | 1 + Firmware/ultralcd.h | 6 ------ Firmware/util.cpp | 1 + 7 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 54d0b9c24..afb9672d4 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -66,6 +66,7 @@ #include "menu.h" #include "ultralcd.h" +#include "conv2str.h" #include "backlight.h" #include "planner.h" diff --git a/Firmware/cardreader.cpp b/Firmware/cardreader.cpp index a86c49e16..caf759f11 100644 --- a/Firmware/cardreader.cpp +++ b/Firmware/cardreader.cpp @@ -2,6 +2,8 @@ #include "cmdqueue.h" #include "cardreader.h" #include "ultralcd.h" +#include "conv2str.h" +#include "menu.h" #include "stepper.h" #include "temperature.h" #include "language.h" diff --git a/Firmware/mmu.cpp b/Firmware/mmu.cpp index a94711395..cbaee9b8b 100755 --- a/Firmware/mmu.cpp +++ b/Firmware/mmu.cpp @@ -11,6 +11,7 @@ #include "cardreader.h" #include "cmdqueue.h" #include "ultralcd.h" +#include "menu.h" #include "sound.h" #include "printers.h" #include diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index 35b05f0e8..1d0dfdb69 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -32,6 +32,8 @@ #include "Marlin.h" #include "cmdqueue.h" #include "ultralcd.h" +#include "menu.h" +#include "conv2str.h" #include "sound.h" #include "temperature.h" #include "cardreader.h" diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 1820d0e62..c98637879 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -5,6 +5,7 @@ #include "temperature.h" #include "ultralcd.h" +#include "conv2str.h" #include "fsensor.h" #include "Marlin.h" #include "language.h" diff --git a/Firmware/ultralcd.h b/Firmware/ultralcd.h index 3aab932d8..d87810011 100755 --- a/Firmware/ultralcd.h +++ b/Firmware/ultralcd.h @@ -1,15 +1,9 @@ #ifndef ULTRALCD_H #define ULTRALCD_H -#include "Marlin.h" -#include "lcd.h" -#include "conv2str.h" -#include "menu.h" #include "mesh_bed_calibration.h" #include "config.h" -#include "config.h" - extern void menu_lcd_longpress_func(void); extern void menu_lcd_charsetup_func(void); extern void menu_lcd_lcdupdate_func(void); diff --git a/Firmware/util.cpp b/Firmware/util.cpp index cf9b05b70..5ce21cd0a 100644 --- a/Firmware/util.cpp +++ b/Firmware/util.cpp @@ -1,6 +1,7 @@ #include "Configuration.h" #include "ultralcd.h" +#include "menu.h" #include "sound.h" #include "language.h" #include "util.h" From 01934b89e931546ca9b1f54e82d12dd0461ca0b3 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sat, 12 Jun 2021 15:13:32 +0200 Subject: [PATCH 47/72] xflash_dump is now always required in all variants --- Firmware/Marlin_main.cpp | 2 -- Firmware/ultralcd.cpp | 7 ++----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index afb9672d4..56a90849e 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -109,9 +109,7 @@ #include "optiboot_xflash.h" #endif //XFLASH -#ifdef XFLASH_DUMP #include "xflash_dump.h" -#endif #ifdef BLINKM #include "BlinkM.h" diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index c98637879..caf9c47c0 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -30,6 +30,7 @@ #include "cmdqueue.h" #include "SdFatUtil.h" +#include "xflash_dump.h" #ifdef FILAMENT_SENSOR #include "pat9125.h" @@ -1804,8 +1805,6 @@ static void lcd_preheat_menu() #ifdef MENU_DUMP -#include "xflash_dump.h" - static void lcd_dump_memory() { lcd_beeper_quick_feedback(); @@ -6722,9 +6721,7 @@ static void lcd_main_menu() } -#ifdef EMERGENCY_DUMP -#include "xflash_dump.h" -#elif defined(EMERGENCY_SERIAL_DUMP) +#ifdef EMERGENCY_SERIAL_DUMP #include "Dcodes.h" #endif From 050cf72e981b7e06c46bd48a079907a176973384 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sat, 12 Jun 2021 15:21:16 +0200 Subject: [PATCH 48/72] Move stack checking to the temperature ISR Now that the stack_error function is truly minimal, we can check for stack errors much more frequently. Also move away stack_error from ultralcd to Marlin_main. --- Firmware/Marlin.h | 1 + Firmware/Marlin_main.cpp | 14 ++++++++++++++ Firmware/temperature.cpp | 5 ++++- Firmware/ultralcd.cpp | 19 ------------------- Firmware/ultralcd.h | 1 - 5 files changed, 19 insertions(+), 21 deletions(-) diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h index 98e5102c4..c2c5ca933 100755 --- a/Firmware/Marlin.h +++ b/Firmware/Marlin.h @@ -497,6 +497,7 @@ void marlin_wait_for_click(); void raise_z_above(float target, bool plan=true); extern "C" void softReset(); +void stack_error(); extern uint32_t IP_address; diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 56a90849e..6e0ddcf9b 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -1727,6 +1727,20 @@ ISR(WDT_vect) } #endif + +void stack_error() { + WRITE(BEEPER, HIGH); + eeprom_update_byte((uint8_t*)EEPROM_FW_CRASH_FLAG, (uint8_t)dump_crash_reason::stack_error); +#ifdef EMERGENCY_DUMP + xfdump_full_dump_and_reset(dump_crash_reason::stack_error); +#elif defined(EMERGENCY_SERIAL_DUMP) + if (emergency_serial_dump) + serial_dump_and_reset(dump_crash_reason::stack_error); +#endif + softReset(); +} + + void trace(); #define CHUNK_SIZE 64 // bytes diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index 1d0dfdb69..3e617a663 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -38,7 +38,7 @@ #include "temperature.h" #include "cardreader.h" -#include "Sd2PinMap.h" +#include "SdFatUtil.h" #include #include "adc.h" @@ -2065,6 +2065,9 @@ FORCE_INLINE static void temperature_isr() } #endif //BABYSTEPPING + // Check if a stack overflow happened + if (!SdFatUtil::test_stack_integrity()) stack_error(); + #if (defined(FANCHECK) && defined(TACH_0) && (TACH_0 > -1)) check_fans(); #endif //(defined(TACH_0)) diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index caf9c47c0..b277df4ce 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -29,7 +29,6 @@ //#include "Configuration.h" #include "cmdqueue.h" -#include "SdFatUtil.h" #include "xflash_dump.h" #ifdef FILAMENT_SENSOR @@ -6721,23 +6720,6 @@ static void lcd_main_menu() } -#ifdef EMERGENCY_SERIAL_DUMP -#include "Dcodes.h" -#endif - -void stack_error() { - WRITE(BEEPER, HIGH); - eeprom_update_byte((uint8_t*)EEPROM_FW_CRASH_FLAG, (uint8_t)dump_crash_reason::stack_error); -#ifdef EMERGENCY_DUMP - xfdump_full_dump_and_reset(dump_crash_reason::stack_error); -#elif defined(EMERGENCY_SERIAL_DUMP) - if (emergency_serial_dump) - serial_dump_and_reset(dump_crash_reason::stack_error); -#endif - softReset(); -} - - #ifdef DEBUG_STEPPER_TIMER_MISSED bool stepper_timer_overflow_state = false; uint16_t stepper_timer_overflow_max = 0; @@ -8961,7 +8943,6 @@ void menu_lcd_lcdupdate_func(void) if (lcd_draw_update) lcd_draw_update--; lcd_next_update_millis = _millis() + LCD_UPDATE_INTERVAL; } - if (!SdFatUtil::test_stack_integrity()) stack_error(); lcd_ping(); //check that we have received ping command if we are in farm mode lcd_send_status(); if (lcd_commands_type == LcdCommands::Layer1Cal) lcd_commands(); diff --git a/Firmware/ultralcd.h b/Firmware/ultralcd.h index d87810011..8c344d120 100755 --- a/Firmware/ultralcd.h +++ b/Firmware/ultralcd.h @@ -194,7 +194,6 @@ void mFilamentItemForce(); void lcd_generic_preheat_menu(); void unload_filament(bool automatic = false); -void stack_error(); void lcd_printer_connected(); void lcd_ping(); From 6de98f7b0d3973037e421ef410c2875613fd3948 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sat, 12 Jun 2021 15:33:18 +0200 Subject: [PATCH 49/72] Move inclusion closer to the usage point --- Firmware/ultralcd.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index b277df4ce..c2c148830 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -29,8 +29,6 @@ //#include "Configuration.h" #include "cmdqueue.h" -#include "xflash_dump.h" - #ifdef FILAMENT_SENSOR #include "pat9125.h" #include "fsensor.h" @@ -1804,6 +1802,8 @@ static void lcd_preheat_menu() #ifdef MENU_DUMP +#include "xflash_dump.h" + static void lcd_dump_memory() { lcd_beeper_quick_feedback(); From ea51d651379439c13b23981655369e78b7a97b9a Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sat, 12 Jun 2021 15:39:37 +0200 Subject: [PATCH 50/72] serial_dump_and_reset: do not completely disable WDT Set it to 8s which is long enough to complete the dump. --- Firmware/Dcodes.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index e9ba04545..dc60fcd76 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -984,8 +984,8 @@ void serial_dump_and_reset(dump_crash_reason reason) SERIAL_ECHOPGM("reason: "); SERIAL_ECHOLN((unsigned)reason); - // disable interrupts from now on to avoid wdt while dumping - wdt_disable(); + // set WDT long enough to allow writing the entire stream + wdt_enable(WDTO_8S); print_mem(0, RAMEND+1, dcode_mem_t::sram); SERIAL_ECHOLNRPGM(MSG_OK); From 7db667ca8627acc4770a40465bd422976a9e4540 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sat, 12 Jun 2021 16:43:46 +0200 Subject: [PATCH 51/72] serial_dump_and_reset: turn on print fan while dumping To avoid scorching the sheet while dumping close to the bed. --- Firmware/Dcodes.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index dc60fcd76..ea27caff6 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -976,6 +976,7 @@ void serial_dump_and_reset(dump_crash_reason reason) // we're being called from a live state, so shut off interrupts and heaters cli(); wdt_enable(WDTO_15MS); + WRITE(FAN_PIN, HIGH); disable_heater(); // this function can also be called from within a corrupted state, so not use From d2041ee2fe6bf2a39fa4d8f81351a2c37932eefb Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sun, 13 Jun 2021 22:35:43 +0200 Subject: [PATCH 52/72] Enable debugging features on all variants - XFlash crash dumper on MK3+ series - Online crash dumper on MK2.5+ series - D2/D6 on MK3+ series - D2 on MK2.5+ series --- Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h | 6 +++--- Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h | 6 +++--- Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h | 6 +++--- Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h | 6 +++--- Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h | 10 +++++----- Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h | 10 +++++----- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h index 3cbc3829f..aa625c64e 100644 --- a/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h @@ -120,14 +120,14 @@ #define FARM_DEFAULT_SAFETYTIMER_TIME_ms (45*60*1000ul) // Online crash dumper -//#define EMERGENCY_SERIAL_DUMP // Request dump via serial on stack corruption and WDR -//#define MENU_SERIAL_DUMP // Enable "Memory dump" in Settings menu +#define EMERGENCY_SERIAL_DUMP // Request dump via serial on stack corruption and WDR +#define MENU_SERIAL_DUMP // Enable "Memory dump" in Settings menu // Filament sensor #define FILAMENT_SENSOR #define PAT9125 -//#define DEBUG_DCODE2 +#define DEBUG_DCODE2 #define DEBUG_DCODE3 //#define DEBUG_BUILD diff --git a/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h index 9b4e591ae..ddafa6f45 100644 --- a/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h @@ -121,14 +121,14 @@ #define FARM_DEFAULT_SAFETYTIMER_TIME_ms (45*60*1000ul) // Online crash dumper -//#define EMERGENCY_SERIAL_DUMP // Request dump via serial on stack corruption and WDR -//#define MENU_SERIAL_DUMP // Enable "Memory dump" in Settings menu +#define EMERGENCY_SERIAL_DUMP // Request dump via serial on stack corruption and WDR +#define MENU_SERIAL_DUMP // Enable "Memory dump" in Settings menu // Filament sensor #define FILAMENT_SENSOR #define PAT9125 -//#define DEBUG_DCODE2 +#define DEBUG_DCODE2 #define DEBUG_DCODE3 //#define DEBUG_BUILD diff --git a/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h index 74ef38b6e..29ff5b356 100644 --- a/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h @@ -120,14 +120,14 @@ #define FARM_DEFAULT_SAFETYTIMER_TIME_ms (45*60*1000ul) // Online crash dumper -//#define EMERGENCY_SERIAL_DUMP // Request dump via serial on stack corruption and WDR -//#define MENU_SERIAL_DUMP // Enable "Memory dump" in Settings menu +#define EMERGENCY_SERIAL_DUMP // Request dump via serial on stack corruption and WDR +#define MENU_SERIAL_DUMP // Enable "Memory dump" in Settings menu // Filament sensor #define FILAMENT_SENSOR #define IR_SENSOR -//#define DEBUG_DCODE2 +#define DEBUG_DCODE2 #define DEBUG_DCODE3 //#define DEBUG_BUILD diff --git a/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h index 177586135..342a9a1fd 100644 --- a/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h @@ -121,14 +121,14 @@ #define FARM_DEFAULT_SAFETYTIMER_TIME_ms (45*60*1000ul) // Online crash dumper -//#define EMERGENCY_SERIAL_DUMP // Request dump via serial on stack corruption and WDR -//#define MENU_SERIAL_DUMP // Enable "Memory dump" in Settings menu +#define EMERGENCY_SERIAL_DUMP // Request dump via serial on stack corruption and WDR +#define MENU_SERIAL_DUMP // Enable "Memory dump" in Settings menu // Filament sensor #define FILAMENT_SENSOR #define IR_SENSOR -//#define DEBUG_DCODE2 +#define DEBUG_DCODE2 #define DEBUG_DCODE3 //#define DEBUG_BUILD diff --git a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h index 66643556a..aacb7cb7d 100644 --- a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h @@ -140,9 +140,9 @@ #define FARM_DEFAULT_SAFETYTIMER_TIME_ms (45*60*1000ul) // Offline crash dumper -//#define XFLASH_DUMP // enable dump functionality (including D20/D21/D22) -//#define MENU_DUMP // enable "Memory dump" in Settings menu -//#define EMERGENCY_DUMP // trigger crash on stack corruption and WDR +#define XFLASH_DUMP // enable dump functionality (including D20/D21/D22) +#define MENU_DUMP // enable "Memory dump" in Settings menu +#define EMERGENCY_DUMP // trigger crash on stack corruption and WDR // Online crash dumper //#define EMERGENCY_SERIAL_DUMP // Request dump via serial on stack corruption and WDR @@ -164,9 +164,9 @@ #define MINTEMP_MINAMBIENT 10 #define MINTEMP_MINAMBIENT_RAW 1002 -//#define DEBUG_DCODE2 +#define DEBUG_DCODE2 #define DEBUG_DCODE3 -//#define DEBUG_DCODE6 +#define DEBUG_DCODE6 //#define DEBUG_BUILD //#define DEBUG_SEC_LANG //secondary language debug output at startup diff --git a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h index 842ff40be..8659c582a 100644 --- a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h @@ -142,9 +142,9 @@ #define FARM_DEFAULT_SAFETYTIMER_TIME_ms (45*60*1000ul) // Offline crash dumper -//#define XFLASH_DUMP // enable dump functionality (including D20/D21/D22) -//#define MENU_DUMP // enable "Memory dump" in Settings menu -//#define EMERGENCY_DUMP // trigger crash on stack corruption and WDR +#define XFLASH_DUMP // enable dump functionality (including D20/D21/D22) +#define MENU_DUMP // enable "Memory dump" in Settings menu +#define EMERGENCY_DUMP // trigger crash on stack corruption and WDR // Online crash dumper //#define EMERGENCY_SERIAL_DUMP // Request dump via serial on stack corruption and WDR @@ -166,9 +166,9 @@ #define MINTEMP_MINAMBIENT 10 #define MINTEMP_MINAMBIENT_RAW 1002 -//#define DEBUG_DCODE2 +#define DEBUG_DCODE2 #define DEBUG_DCODE3 -//#define DEBUG_DCODE6 +#define DEBUG_DCODE6 //#define DEBUG_BUILD //#define DEBUG_SEC_LANG //secondary language debug output at startup From 8e667a8acdfb31f2ac9ce749c5719a8b9862baeb Mon Sep 17 00:00:00 2001 From: Voinea Dragos Date: Mon, 14 Jun 2021 11:30:38 +0300 Subject: [PATCH 53/72] bad ISR catch --- Firmware/Marlin_main.cpp | 15 +++++++++++++++ Firmware/xflash_dump.h | 1 + 2 files changed, 16 insertions(+) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 6e0ddcf9b..15fdc7c20 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -1727,6 +1727,21 @@ ISR(WDT_vect) } #endif +#if defined(WATCHDOG) && defined(EMERGENCY_HANDLERS) +ISR(BADISR_vect) +{ + WRITE(BEEPER, HIGH); + eeprom_update_byte((uint8_t*)EEPROM_FW_CRASH_FLAG, (uint8_t)dump_crash_reason::bad_isr); +#ifdef EMERGENCY_DUMP + xfdump_full_dump_and_reset(dump_crash_reason::bad_isr); +#elif defined(EMERGENCY_SERIAL_DUMP) + if(emergency_serial_dump) + serial_dump_and_reset(dump_crash_reason::bad_isr); +#endif + softReset(); +} +#endif + void stack_error() { WRITE(BEEPER, HIGH); diff --git a/Firmware/xflash_dump.h b/Firmware/xflash_dump.h index f517a5921..8866b1ec5 100644 --- a/Firmware/xflash_dump.h +++ b/Firmware/xflash_dump.h @@ -7,6 +7,7 @@ enum class dump_crash_reason : uint8_t manual = 0, stack_error, watchdog, + bad_isr, }; #ifdef XFLASH_DUMP From fa0f58d5bc9a5120e98c4006429b569ab75d4ac3 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 14 Jun 2021 12:30:24 +0200 Subject: [PATCH 54/72] serial_dump: add description about bad_isr --- Firmware/Marlin_main.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 15fdc7c20..286c3bc81 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -1030,6 +1030,9 @@ static void fw_crash_init() case dump_crash_reason::watchdog: lcd_puts_P(_i("Watchdog timeout")); break; + case dump_crash_reason::bad_isr: + lcd_puts_P(_i("Bad interrupt")); + break; default: lcd_print((uint8_t)crash_reason); break; @@ -1727,7 +1730,7 @@ ISR(WDT_vect) } #endif -#if defined(WATCHDOG) && defined(EMERGENCY_HANDLERS) +#ifdef EMERGENCY_HANDLERS ISR(BADISR_vect) { WRITE(BEEPER, HIGH); @@ -1742,7 +1745,6 @@ ISR(BADISR_vect) } #endif - void stack_error() { WRITE(BEEPER, HIGH); eeprom_update_byte((uint8_t*)EEPROM_FW_CRASH_FLAG, (uint8_t)dump_crash_reason::stack_error); From 96aad0a475de09c5ce9a9ef5099be94d574ed92e Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 14 Jun 2021 12:38:23 +0200 Subject: [PATCH 55/72] Remove duplication in crash handlers It's kind of nice that all handlers eventually came to become the same. --- Firmware/Marlin_main.cpp | 40 +++++++++++++++------------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 286c3bc81..1b50daaf7 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -1715,46 +1715,36 @@ void setup() #endif //WATCHDOG } -#if defined(WATCHDOG) && defined(EMERGENCY_HANDLERS) -ISR(WDT_vect) + +static inline void crash_and_burn(dump_crash_reason reason) { WRITE(BEEPER, HIGH); - eeprom_update_byte((uint8_t*)EEPROM_FW_CRASH_FLAG, (uint8_t)dump_crash_reason::watchdog); + eeprom_update_byte((uint8_t*)EEPROM_FW_CRASH_FLAG, (uint8_t)reason); #ifdef EMERGENCY_DUMP - xfdump_full_dump_and_reset(dump_crash_reason::watchdog); + xfdump_full_dump_and_reset(reason); #elif defined(EMERGENCY_SERIAL_DUMP) if(emergency_serial_dump) - serial_dump_and_reset(dump_crash_reason::watchdog); + serial_dump_and_reset(reason); #endif softReset(); } -#endif #ifdef EMERGENCY_HANDLERS -ISR(BADISR_vect) +#ifdef WATCHDOG +ISR(WDT_vect) { - WRITE(BEEPER, HIGH); - eeprom_update_byte((uint8_t*)EEPROM_FW_CRASH_FLAG, (uint8_t)dump_crash_reason::bad_isr); -#ifdef EMERGENCY_DUMP - xfdump_full_dump_and_reset(dump_crash_reason::bad_isr); -#elif defined(EMERGENCY_SERIAL_DUMP) - if(emergency_serial_dump) - serial_dump_and_reset(dump_crash_reason::bad_isr); -#endif - softReset(); + crash_and_burn(dump_crash_reason::watchdog); } #endif +ISR(BADISR_vect) +{ + crash_and_burn(dump_crash_reason::bad_isr); +} +#endif //EMERGENCY_HANDLERS + void stack_error() { - WRITE(BEEPER, HIGH); - eeprom_update_byte((uint8_t*)EEPROM_FW_CRASH_FLAG, (uint8_t)dump_crash_reason::stack_error); -#ifdef EMERGENCY_DUMP - xfdump_full_dump_and_reset(dump_crash_reason::stack_error); -#elif defined(EMERGENCY_SERIAL_DUMP) - if (emergency_serial_dump) - serial_dump_and_reset(dump_crash_reason::stack_error); -#endif - softReset(); + crash_and_burn(dump_crash_reason::stack_error); } From 928c7211ada12fe1171f5d08953804f5d8579329 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 15 Jun 2021 11:47:27 +0200 Subject: [PATCH 56/72] emergency handlers: always save SP _at_ the crash location Save SP which is closest to the crash location, which simplifies debugging. For serial_dump, write SP just before the dump. For xfdump, save SP in the dump header. This makes xfdump_dump and xfdump_full_dump_and_reset() equivalent for stack debugging. --- Firmware/Dcodes.cpp | 10 ++++++---- Firmware/Dcodes.h | 2 +- Firmware/Marlin_main.cpp | 12 ++++++------ Firmware/ultralcd.cpp | 4 ++-- Firmware/xflash_dump.cpp | 6 ++++-- Firmware/xflash_dump.h | 7 ++++--- Firmware/xflash_layout.h | 1 + 7 files changed, 24 insertions(+), 18 deletions(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index ea27caff6..0b2943b06 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -932,11 +932,11 @@ void dcode_9125() void dcode_20() { if(code_seen('E')) - xfdump_full_dump_and_reset(); + xfdump_full_dump_and_reset(SP); else { unsigned long ts = _millis(); - xfdump_dump(); + xfdump_dump(SP); ts = _millis() - ts; DBG(_N("dump completed in %lums\n"), ts); } @@ -971,7 +971,7 @@ void dcode_22() bool emergency_serial_dump = false; -void serial_dump_and_reset(dump_crash_reason reason) +void serial_dump_and_reset(uint16_t sp, dump_crash_reason reason) { // we're being called from a live state, so shut off interrupts and heaters cli(); @@ -982,7 +982,9 @@ void serial_dump_and_reset(dump_crash_reason reason) // this function can also be called from within a corrupted state, so not use // printf family of functions that use the heap or grow the stack. SERIAL_ECHOLNPGM("D23 - emergency serial dump"); - SERIAL_ECHOPGM("reason: "); + SERIAL_ECHOPGM("exception: "); + SERIAL_ECHO(sp); + SERIAL_ECHO(" "); SERIAL_ECHOLN((unsigned)reason); // set WDT long enough to allow writing the entire stream diff --git a/Firmware/Dcodes.h b/Firmware/Dcodes.h index c4b470e4b..477a58470 100644 --- a/Firmware/Dcodes.h +++ b/Firmware/Dcodes.h @@ -38,7 +38,7 @@ extern void dcode_22(); //D22 - Clear crash dump state #ifdef EMERGENCY_SERIAL_DUMP #include "xflash_dump.h" extern bool emergency_serial_dump; -extern void serial_dump_and_reset(dump_crash_reason); +extern void serial_dump_and_reset(uint16_t sp, dump_crash_reason); #endif #ifdef HEATBED_ANALYSIS diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 1b50daaf7..acf73ab83 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -1716,15 +1716,15 @@ void setup() } -static inline void crash_and_burn(dump_crash_reason reason) +static inline void crash_and_burn(uint16_t sp, dump_crash_reason reason) { WRITE(BEEPER, HIGH); eeprom_update_byte((uint8_t*)EEPROM_FW_CRASH_FLAG, (uint8_t)reason); #ifdef EMERGENCY_DUMP - xfdump_full_dump_and_reset(reason); + xfdump_full_dump_and_reset(sp, reason); #elif defined(EMERGENCY_SERIAL_DUMP) if(emergency_serial_dump) - serial_dump_and_reset(reason); + serial_dump_and_reset(sp, reason); #endif softReset(); } @@ -1733,18 +1733,18 @@ static inline void crash_and_burn(dump_crash_reason reason) #ifdef WATCHDOG ISR(WDT_vect) { - crash_and_burn(dump_crash_reason::watchdog); + crash_and_burn(SP, dump_crash_reason::watchdog); } #endif ISR(BADISR_vect) { - crash_and_burn(dump_crash_reason::bad_isr); + crash_and_burn(SP, dump_crash_reason::bad_isr); } #endif //EMERGENCY_HANDLERS void stack_error() { - crash_and_burn(dump_crash_reason::stack_error); + crash_and_burn(SP, dump_crash_reason::stack_error); } diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index c2c148830..dd3d3f5ce 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -1807,7 +1807,7 @@ static void lcd_preheat_menu() static void lcd_dump_memory() { lcd_beeper_quick_feedback(); - xfdump_dump(); + xfdump_dump(SP); lcd_return_to_status(); } #endif //MENU_DUMP @@ -1816,7 +1816,7 @@ static void lcd_dump_memory() static void lcd_serial_dump() { - serial_dump_and_reset(dump_crash_reason::manual); + serial_dump_and_reset(SP, dump_crash_reason::manual); } #endif //MENU_SERIAL_DUMP diff --git a/Firmware/xflash_dump.cpp b/Firmware/xflash_dump.cpp index 8b4ab9955..4c9aca42d 100644 --- a/Firmware/xflash_dump.cpp +++ b/Firmware/xflash_dump.cpp @@ -68,12 +68,13 @@ static void xfdump_dump_core(dump_header_t& hdr, uint32_t addr, uint8_t* buf, ui } -void xfdump_dump() +void xfdump_dump(uint16_t sp) { dump_header_t buf; buf.magic = DUMP_MAGIC; buf.regs_present = false; buf.crash_reason = (uint8_t)dump_crash_reason::manual; + buf.sp = sp; // write sram only xfdump_dump_core(buf, DUMP_OFFSET + offsetof(dump_t, data.sram), @@ -81,12 +82,13 @@ void xfdump_dump() } -void xfdump_full_dump_and_reset(dump_crash_reason reason) +void xfdump_full_dump_and_reset(uint16_t sp, dump_crash_reason reason) { dump_header_t buf; buf.magic = DUMP_MAGIC; buf.regs_present = true; buf.crash_reason = (uint8_t)reason; + buf.sp = sp; // disable interrupts for a cleaner register dump cli(); diff --git a/Firmware/xflash_dump.h b/Firmware/xflash_dump.h index 8866b1ec5..c9a82c667 100644 --- a/Firmware/xflash_dump.h +++ b/Firmware/xflash_dump.h @@ -11,12 +11,13 @@ enum class dump_crash_reason : uint8_t }; #ifdef XFLASH_DUMP -void xfdump_reset(); // reset XFLASH dump state -void xfdump_dump(); // create a new SRAM memory dump +void xfdump_reset(); // reset XFLASH dump state +void xfdump_dump(uint16_t sp); // create a new SRAM memory dump // return true if a dump is present, save type in "reason" if provided bool xfdump_check_state(dump_crash_reason* reason = NULL); // create a new dump containing registers and SRAM, then reset -void xfdump_full_dump_and_reset(dump_crash_reason crash = dump_crash_reason::manual); +void xfdump_full_dump_and_reset( + uint16_t sp, dump_crash_reason crash = dump_crash_reason::manual); #endif diff --git a/Firmware/xflash_layout.h b/Firmware/xflash_layout.h index 31f67b7d6..0e533494c 100644 --- a/Firmware/xflash_layout.h +++ b/Firmware/xflash_layout.h @@ -21,6 +21,7 @@ struct dump_header_t uint8_t regs_present; // true when the lower segment containing registers is present uint8_t crash_reason; // uses values from dump_crash_source + uint16_t sp; // SP closest to the crash location }; struct dump_data_t From d193d0f7ac7fef41b9180e6a4636c4be587273f1 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 15 Jun 2021 16:21:56 +0200 Subject: [PATCH 57/72] serial_dump: manipulate WDT just once --- Firmware/Dcodes.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index 0b2943b06..09c412994 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -973,9 +973,12 @@ bool emergency_serial_dump = false; void serial_dump_and_reset(uint16_t sp, dump_crash_reason reason) { - // we're being called from a live state, so shut off interrupts and heaters cli(); - wdt_enable(WDTO_15MS); + + // extend WDT long enough to allow writing the entire stream + wdt_enable(WDTO_8S); + + // we're being called from a live state, so shut off interrupts and heaters WRITE(FAN_PIN, HIGH); disable_heater(); @@ -987,8 +990,6 @@ void serial_dump_and_reset(uint16_t sp, dump_crash_reason reason) SERIAL_ECHO(" "); SERIAL_ECHOLN((unsigned)reason); - // set WDT long enough to allow writing the entire stream - wdt_enable(WDTO_8S); print_mem(0, RAMEND+1, dcode_mem_t::sram); SERIAL_ECHOLNRPGM(MSG_OK); From a614268c947880dbbea4a1c94c99042f50443a37 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 15 Jun 2021 18:44:44 +0200 Subject: [PATCH 58/72] serial_dump_and_reset: do not call manage_heater with interrupts disabled Do not call manage_heater() in print_mem() if interrupts are already disabled. This means we're running inside the crash handler. --- Firmware/Dcodes.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index 09c412994..713f3ed5b 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -101,8 +101,10 @@ void print_mem(daddr_t address, daddr_t count, dcode_mem_t type, uint8_t countpe count_line--; count--; - // sporadically call manage heaters to avoid wdt - if(!((uint16_t)count % 8192)) + // sporadically call manage_heater, but only when interrupts are enabled (meaning + // print_mem is called by D2). Don't do anything otherwise: we are inside a crash + // handler where memory & stack needs to be preserved! + if((SREG & (1 << SREG_I)) && !((uint16_t)count % 8192)) manage_heater(); } putchar('\n'); From e6d520cf6e927c486ea1a4a3424793b586ae1df8 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 15 Jun 2021 18:49:20 +0200 Subject: [PATCH 59/72] Add test code for the stack overflow handler --- Firmware/ultralcd.cpp | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index dd3d3f5ce..0b8cf3504 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -1820,13 +1820,40 @@ static void lcd_serial_dump() } #endif //MENU_SERIAL_DUMP -#if defined(WATCHDOG) && defined(DEBUG_BUILD) && defined(EMERGENCY_HANDLERS) +#defined(DEBUG_BUILD) && defined(EMERGENCY_HANDLERS) +#include + +#ifdef WATCHDOG static void lcd_wdr_crash() { while (1); } #endif +static uint8_t lcd_stack_crash_(uint8_t arg, uint32_t sp = 0) +{ + // populate the stack with an increasing value for ease of testing + volatile uint16_t tmp __attribute__((unused)) = sp; + + _delay(arg); + uint8_t ret = lcd_stack_crash_(arg, SP); + + // required to avoid tail call elimination and to slow down the stack growth + _delay(ret); + + return ret; +} + +static void lcd_stack_crash() +{ +#ifdef WATCHDOG + wdt_disable(); +#endif + // delay choosen in order to hit the stack-check in the temperature isr reliably + lcd_stack_crash_(10); +} +#endif + //! @brief Show Support Menu //! @@ -2027,9 +2054,12 @@ static void lcd_support_menu() MENU_ITEM_FUNCTION_P(_i("Dump to serial"), lcd_serial_dump); #endif #ifdef DEBUG_BUILD -#if defined(WATCHDOG) && defined(EMERGENCY_HANDLERS) +#ifdef EMERGENCY_HANDLERS +#ifdef WATCHDOG MENU_ITEM_FUNCTION_P(PSTR("WDR crash"), lcd_wdr_crash); -#endif +#endif //WATCHDOG + MENU_ITEM_FUNCTION_P(PSTR("Stack crash"), lcd_stack_crash); +#endif //EMERGENCY_HANDLERS MENU_ITEM_SUBMENU_P(PSTR("Debug"), lcd_menu_debug);////MSG_DEBUG c=18 #endif /* DEBUG_BUILD */ From 97535ec0c14dab8a656fe3184058b80a12a27ccb Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 15 Jun 2021 22:10:08 +0200 Subject: [PATCH 60/72] Fix last commit --- Firmware/ultralcd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 0b8cf3504..6e4b33015 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -1820,7 +1820,7 @@ static void lcd_serial_dump() } #endif //MENU_SERIAL_DUMP -#defined(DEBUG_BUILD) && defined(EMERGENCY_HANDLERS) +#if defined(DEBUG_BUILD) && defined(EMERGENCY_HANDLERS) #include #ifdef WATCHDOG From dd8c6c064ccf30616094c22ebe10e037d55691d5 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Wed, 16 Jun 2021 23:58:00 +0200 Subject: [PATCH 61/72] xfdump: simplify stack debugging (sample pc+sp) Instead of having to guess the PC where the SP was sampled, always take both. This allows "seamless" stack decoding for both serial and xflash dumps, since we don't have to guess which function generated the dump. Make the core functions (doing the sampling) be ``noinline`` as well, so that they always have valid frame. --- Firmware/Dcodes.cpp | 27 +++++++++++++++++++-------- Firmware/Dcodes.h | 2 +- Firmware/Marlin_main.cpp | 12 ++++++------ Firmware/asm.h | 27 +++++++++++++++++++++++++++ Firmware/ultralcd.cpp | 4 ++-- Firmware/xflash_dump.cpp | 13 ++++++++----- Firmware/xflash_dump.h | 7 +++---- Firmware/xflash_layout.h | 4 +++- 8 files changed, 69 insertions(+), 27 deletions(-) create mode 100644 Firmware/asm.h diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index 713f3ed5b..c4fd5311f 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -934,11 +934,11 @@ void dcode_9125() void dcode_20() { if(code_seen('E')) - xfdump_full_dump_and_reset(SP); + xfdump_full_dump_and_reset(); else { unsigned long ts = _millis(); - xfdump_dump(SP); + xfdump_dump(); ts = _millis() - ts; DBG(_N("dump completed in %lums\n"), ts); } @@ -969,28 +969,39 @@ void dcode_22() #endif #ifdef EMERGENCY_SERIAL_DUMP +#include "asm.h" #include "xflash_dump.h" bool emergency_serial_dump = false; -void serial_dump_and_reset(uint16_t sp, dump_crash_reason reason) +void __attribute__((noinline)) serial_dump_and_reset(dump_crash_reason reason) { + uint16_t sp; + uint32_t pc; + + // we're being called from a live state, so shut off interrupts ... cli(); + // sample SP/PC + sp = SP; + GETPC(&pc); + // extend WDT long enough to allow writing the entire stream wdt_enable(WDTO_8S); - // we're being called from a live state, so shut off interrupts and heaters + // ... and heaters WRITE(FAN_PIN, HIGH); disable_heater(); // this function can also be called from within a corrupted state, so not use // printf family of functions that use the heap or grow the stack. SERIAL_ECHOLNPGM("D23 - emergency serial dump"); - SERIAL_ECHOPGM("exception: "); - SERIAL_ECHO(sp); - SERIAL_ECHO(" "); - SERIAL_ECHOLN((unsigned)reason); + SERIAL_ECHOPGM("error: "); + MYSERIAL.print((uint8_t)reason, DEC); + MYSERIAL.print(" "); + MYSERIAL.print(pc, HEX); + MYSERIAL.print(" "); + MYSERIAL.println(sp, HEX); print_mem(0, RAMEND+1, dcode_mem_t::sram); SERIAL_ECHOLNRPGM(MSG_OK); diff --git a/Firmware/Dcodes.h b/Firmware/Dcodes.h index 477a58470..c4b470e4b 100644 --- a/Firmware/Dcodes.h +++ b/Firmware/Dcodes.h @@ -38,7 +38,7 @@ extern void dcode_22(); //D22 - Clear crash dump state #ifdef EMERGENCY_SERIAL_DUMP #include "xflash_dump.h" extern bool emergency_serial_dump; -extern void serial_dump_and_reset(uint16_t sp, dump_crash_reason); +extern void serial_dump_and_reset(dump_crash_reason); #endif #ifdef HEATBED_ANALYSIS diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index acf73ab83..1b50daaf7 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -1716,15 +1716,15 @@ void setup() } -static inline void crash_and_burn(uint16_t sp, dump_crash_reason reason) +static inline void crash_and_burn(dump_crash_reason reason) { WRITE(BEEPER, HIGH); eeprom_update_byte((uint8_t*)EEPROM_FW_CRASH_FLAG, (uint8_t)reason); #ifdef EMERGENCY_DUMP - xfdump_full_dump_and_reset(sp, reason); + xfdump_full_dump_and_reset(reason); #elif defined(EMERGENCY_SERIAL_DUMP) if(emergency_serial_dump) - serial_dump_and_reset(sp, reason); + serial_dump_and_reset(reason); #endif softReset(); } @@ -1733,18 +1733,18 @@ static inline void crash_and_burn(uint16_t sp, dump_crash_reason reason) #ifdef WATCHDOG ISR(WDT_vect) { - crash_and_burn(SP, dump_crash_reason::watchdog); + crash_and_burn(dump_crash_reason::watchdog); } #endif ISR(BADISR_vect) { - crash_and_burn(SP, dump_crash_reason::bad_isr); + crash_and_burn(dump_crash_reason::bad_isr); } #endif //EMERGENCY_HANDLERS void stack_error() { - crash_and_burn(SP, dump_crash_reason::stack_error); + crash_and_burn(dump_crash_reason::stack_error); } diff --git a/Firmware/asm.h b/Firmware/asm.h new file mode 100644 index 000000000..896f59bb8 --- /dev/null +++ b/Firmware/asm.h @@ -0,0 +1,27 @@ +#pragma once +#include + +#ifdef __AVR_ATmega2560__ + +// return the current PC (on AVRs with 22bit PC) +static inline void GETPC(uint32_t* v) +{ + uint8_t a, b, c; + asm + ( + "rcall .\n" + "pop %2\n" + "pop %1\n" + "pop %0\n" + : "=r" (a), "=r" (b), "=r" (c) + ); + ((uint8_t*)v)[0] = a; + ((uint8_t*)v)[1] = b; + ((uint8_t*)v)[2] = c; + ((uint8_t*)v)[3] = 0; + + // go back 1 instruction before rcall + *v = (*v - 2) * 2; +} + +#endif diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 6e4b33015..844436aa1 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -1807,7 +1807,7 @@ static void lcd_preheat_menu() static void lcd_dump_memory() { lcd_beeper_quick_feedback(); - xfdump_dump(SP); + xfdump_dump(); lcd_return_to_status(); } #endif //MENU_DUMP @@ -1816,7 +1816,7 @@ static void lcd_dump_memory() static void lcd_serial_dump() { - serial_dump_and_reset(SP, dump_crash_reason::manual); + serial_dump_and_reset(dump_crash_reason::manual); } #endif //MENU_SERIAL_DUMP diff --git a/Firmware/xflash_dump.cpp b/Firmware/xflash_dump.cpp index 4c9aca42d..7040b502e 100644 --- a/Firmware/xflash_dump.cpp +++ b/Firmware/xflash_dump.cpp @@ -5,6 +5,7 @@ #include "xflash_dump.h" #ifdef XFLASH_DUMP +#include "asm.h" #include "xflash.h" #include "Marlin.h" // for softReset @@ -49,13 +50,17 @@ static void xfdump_erase() } -static void xfdump_dump_core(dump_header_t& hdr, uint32_t addr, uint8_t* buf, uint16_t cnt) +static void __attribute__((noinline)) xfdump_dump_core(dump_header_t& hdr, uint32_t addr, uint8_t* buf, uint16_t cnt) { XFLASH_SPI_ENTER(); // start by clearing all sectors (we need all of them in any case) xfdump_erase(); + // sample SP/PC + hdr.sp = SP; + GETPC(&hdr.pc); + // write header static_assert(sizeof(hdr) <= 256, "header is larger than a single page write"); xflash_enable_wr(); @@ -68,13 +73,12 @@ static void xfdump_dump_core(dump_header_t& hdr, uint32_t addr, uint8_t* buf, ui } -void xfdump_dump(uint16_t sp) +void xfdump_dump() { dump_header_t buf; buf.magic = DUMP_MAGIC; buf.regs_present = false; buf.crash_reason = (uint8_t)dump_crash_reason::manual; - buf.sp = sp; // write sram only xfdump_dump_core(buf, DUMP_OFFSET + offsetof(dump_t, data.sram), @@ -82,13 +86,12 @@ void xfdump_dump(uint16_t sp) } -void xfdump_full_dump_and_reset(uint16_t sp, dump_crash_reason reason) +void xfdump_full_dump_and_reset(dump_crash_reason reason) { dump_header_t buf; buf.magic = DUMP_MAGIC; buf.regs_present = true; buf.crash_reason = (uint8_t)reason; - buf.sp = sp; // disable interrupts for a cleaner register dump cli(); diff --git a/Firmware/xflash_dump.h b/Firmware/xflash_dump.h index c9a82c667..6ece99c68 100644 --- a/Firmware/xflash_dump.h +++ b/Firmware/xflash_dump.h @@ -11,13 +11,12 @@ enum class dump_crash_reason : uint8_t }; #ifdef XFLASH_DUMP -void xfdump_reset(); // reset XFLASH dump state -void xfdump_dump(uint16_t sp); // create a new SRAM memory dump +void xfdump_reset(); // reset XFLASH dump state +void xfdump_dump(); // create a new SRAM memory dump // return true if a dump is present, save type in "reason" if provided bool xfdump_check_state(dump_crash_reason* reason = NULL); // create a new dump containing registers and SRAM, then reset -void xfdump_full_dump_and_reset( - uint16_t sp, dump_crash_reason crash = dump_crash_reason::manual); +void xfdump_full_dump_and_reset(dump_crash_reason crash = dump_crash_reason::manual); #endif diff --git a/Firmware/xflash_layout.h b/Firmware/xflash_layout.h index 0e533494c..22353a743 100644 --- a/Firmware/xflash_layout.h +++ b/Firmware/xflash_layout.h @@ -21,7 +21,9 @@ struct dump_header_t uint8_t regs_present; // true when the lower segment containing registers is present uint8_t crash_reason; // uses values from dump_crash_source - uint16_t sp; // SP closest to the crash location + + uint32_t pc; // PC nearby the crash location + uint16_t sp; // SP nearby the crash location }; struct dump_data_t From 06d91ddceeb94d26e00338236bb0d69ca0eef1fa Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Thu, 17 Jun 2021 20:07:01 +0200 Subject: [PATCH 62/72] Handle Long-Press in the main loop The longpress function is currently called within the temperature ISR, which is bogus. Calling the longpress function at the wrong moment can corrupt the menu buffers. Move the call to the main loop by changing the logic slightly: - still sample the lcd buttons inside the temperature ISR, which keeps scrollong/pressing responsive, but... - set a flag to indicate that longpress has been triggered instead of calling the function directly - call the function on the next manage_inactivity run Combined with #3180 this removes _most_ unsafe operations out of the ISR which can happen during a normal run (max/mintemp warnings are still an exception). --- Firmware/Marlin_main.cpp | 11 +++++++++++ Firmware/lcd.cpp | 6 +++--- Firmware/lcd.h | 1 + 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 92df0122d..1f7d46419 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -9901,6 +9901,17 @@ if(0) #endif check_axes_activity(); mmu_loop(); + + // handle longpress + if(lcd_longpress_trigger) + { + // long press is not possible in modal mode, wait until ready + if (lcd_longpress_func && lcd_update_enabled) + { + lcd_longpress_func(); + lcd_longpress_trigger = 0; + } + } } void kill(const char *full_screen_message, unsigned char id) diff --git a/Firmware/lcd.cpp b/Firmware/lcd.cpp index c3f2921d1..a52bdd3e8 100644 --- a/Firmware/lcd.cpp +++ b/Firmware/lcd.cpp @@ -728,6 +728,8 @@ void lcd_update_enable(uint8_t enabled) } } +bool lcd_longpress_trigger = 0; + void lcd_buttons_update(void) { static uint8_t lcd_long_press_active = 0; @@ -749,9 +751,7 @@ void lcd_buttons_update(void) else if (longPressTimer.expired(LONG_PRESS_TIME)) { lcd_long_press_active = 1; - //long press is not possible in modal mode - if (lcd_longpress_func && lcd_update_enabled) - lcd_longpress_func(); + lcd_longpress_trigger = 1; } } } diff --git a/Firmware/lcd.h b/Firmware/lcd.h index 12b162e75..65bb9dc92 100644 --- a/Firmware/lcd.h +++ b/Firmware/lcd.h @@ -110,6 +110,7 @@ extern uint32_t lcd_next_update_millis; extern uint8_t lcd_status_update_delay; extern lcd_longpress_func_t lcd_longpress_func; +extern bool lcd_longpress_trigger; extern lcd_charsetup_func_t lcd_charsetup_func; From 72b8f0d1e62e3cc4896c91d2b9140e280dc55134 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sat, 19 Jun 2021 13:46:10 +0200 Subject: [PATCH 63/72] Add some warnings in lcd_buttons_update --- Firmware/lcd.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Firmware/lcd.cpp b/Firmware/lcd.cpp index a52bdd3e8..37b70f1a1 100644 --- a/Firmware/lcd.cpp +++ b/Firmware/lcd.cpp @@ -730,6 +730,8 @@ void lcd_update_enable(uint8_t enabled) bool lcd_longpress_trigger = 0; +// WARNING: this function is called from the temperature ISR. +// Only update flags, but do not perform any menu/lcd operation! void lcd_buttons_update(void) { static uint8_t lcd_long_press_active = 0; From bff79d290a33e806bf7d05a4c867157fb90bda59 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sat, 19 Jun 2021 13:56:40 +0200 Subject: [PATCH 64/72] GETPC: Do not manipulate the 32bit return address We can do that offline, saving over 30 bytes of instructions. --- Firmware/asm.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/Firmware/asm.h b/Firmware/asm.h index 896f59bb8..2ffb88ad9 100644 --- a/Firmware/asm.h +++ b/Firmware/asm.h @@ -19,9 +19,6 @@ static inline void GETPC(uint32_t* v) ((uint8_t*)v)[1] = b; ((uint8_t*)v)[2] = c; ((uint8_t*)v)[3] = 0; - - // go back 1 instruction before rcall - *v = (*v - 2) * 2; } #endif From 700825ff76c6683fa7e0dbdf8cbb83905c041a0b Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sat, 19 Jun 2021 13:57:40 +0200 Subject: [PATCH 65/72] serial_dump: include hex prefix --- Firmware/Dcodes.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index c4fd5311f..5a840ee45 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -998,9 +998,9 @@ void __attribute__((noinline)) serial_dump_and_reset(dump_crash_reason reason) SERIAL_ECHOLNPGM("D23 - emergency serial dump"); SERIAL_ECHOPGM("error: "); MYSERIAL.print((uint8_t)reason, DEC); - MYSERIAL.print(" "); + SERIAL_ECHOPGM(" 0x"); MYSERIAL.print(pc, HEX); - MYSERIAL.print(" "); + SERIAL_ECHOPGM(" 0x"); MYSERIAL.println(sp, HEX); print_mem(0, RAMEND+1, dcode_mem_t::sram); From 72be8f7be5099fe18027cc2436394e605d58b991 Mon Sep 17 00:00:00 2001 From: jfestrada Date: Mon, 21 Jun 2021 12:42:56 +0200 Subject: [PATCH 66/72] Fix spanish translation for MSG_UNLOAD_SUCCESSFUL (#3185) Fix spanish transtalation for MSG_UNLOAD_SUCCESSFUL by: jfestrada --- lang/lang_en_es.txt | 2 +- lang/po/Firmware_es.po | 2 +- lang/po/new/es.po | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lang/lang_en_es.txt b/lang/lang_en_es.txt index 6c629326a..591043d7c 100644 --- a/lang/lang_en_es.txt +++ b/lang/lang_en_es.txt @@ -1176,7 +1176,7 @@ #MSG_UNLOAD_SUCCESSFUL c=20 r=2 "Was filament unload successful?" -"Se cargocon exito el filamento?" +"Se descargo con exito el filamento?" #MSG_SELFTEST_WIRINGERROR c=18 "Wiring error" diff --git a/lang/po/Firmware_es.po b/lang/po/Firmware_es.po index ab8ecec91..a28eb8612 100644 --- a/lang/po/Firmware_es.po +++ b/lang/po/Firmware_es.po @@ -1488,7 +1488,7 @@ msgstr "Cuidado: Ha cambiado el tipo de impresora." # MSG_UNLOAD_SUCCESSFUL c=20 r=2 #: Marlin_main.cpp:3680 msgid "Was filament unload successful?" -msgstr "Se cargocon exito el filamento?" +msgstr "Se descargo con exito el filamento?" # MSG_SELFTEST_WIRINGERROR c=18 #: messages.c:98 diff --git a/lang/po/new/es.po b/lang/po/new/es.po index 7f4b7d8bf..9e5088485 100644 --- a/lang/po/new/es.po +++ b/lang/po/new/es.po @@ -1488,7 +1488,7 @@ msgstr "Cuidado: Ha cambiado el tipo de impresora." # MSG_UNLOAD_SUCCESSFUL c=20 r=2 #: Marlin_main.cpp:3680 msgid "Was filament unload successful?" -msgstr "Se cargocon exito el filamento?" +msgstr "Se descargo con exito el filamento?" # MSG_SELFTEST_WIRINGERROR c=18 #: messages.c:98 From 934b567e5afefa53b198713bd288e7d5fdccbb20 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 21 Jun 2021 22:36:32 +0200 Subject: [PATCH 67/72] Remove "bonus" exclamation points from the crash message --- Firmware/Marlin_main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 1b50daaf7..4b374cd29 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -1008,7 +1008,7 @@ static void fw_crash_init() eeprom_read_byte((uint8_t*)EEPROM_FW_CRASH_FLAG) != 0xFF) { lcd_show_fullscreen_message_and_wait_P( - _i("!!!FIRMWARE CRASH!!!\n" + _i("FIRMWARE CRASH!\n" "Debug data available for analysis. " "Contact support to submit details.")); } @@ -1021,7 +1021,7 @@ static void fw_crash_init() lcd_beeper_quick_feedback(); lcd_clear(); - lcd_puts_P(_i("!!!FIRMWARE CRASH!!!\nCrash reason:\n")); + lcd_puts_P(_i("FIRMWARE CRASH!\nCrash reason:\n")); switch(crash_reason) { case dump_crash_reason::stack_error: From f4fcdae6303b1ad441025bdd65904d9628e7fbfb Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 22 Jun 2021 00:04:39 +0200 Subject: [PATCH 68/72] Fixup the DUMP_MAGIC constant --- Firmware/xflash_layout.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/xflash_layout.h b/Firmware/xflash_layout.h index 22353a743..5d92d6e6c 100644 --- a/Firmware/xflash_layout.h +++ b/Firmware/xflash_layout.h @@ -11,7 +11,7 @@ #define LANG_SIZE XFLASH_SIZE #else -#define DUMP_MAGIC 0x47555255ul +#define DUMP_MAGIC 0x55525547ul struct dump_header_t { From 79287ffb3df0e112c08ee8d9f708f95869d6bbcc Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sat, 19 Jun 2021 17:12:17 +0200 Subject: [PATCH 69/72] Use uint8_t consistently for the block buffer's index Instead of using a mixture of int8_t, unsigned char and (incorrectly) int, use uint8_t consistently for indexing the current block. This improves the performance of the wait loop in plan_buffer_line, which currently expands all comparisons to a word for no reason. This also extends the theoretical limit to 128 entries. Add some static assertions to ensure BLOCK_BUFFER_SIZE is correct. --- Firmware/planner.cpp | 26 +++++++++++++------------- Firmware/planner.h | 14 +++++++++----- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/Firmware/planner.cpp b/Firmware/planner.cpp index ba3791ae8..b6d012b24 100644 --- a/Firmware/planner.cpp +++ b/Firmware/planner.cpp @@ -109,9 +109,9 @@ unsigned char g_uc_extruder_last_move[3] = {0,0,0}; //=========================================================================== //=================semi-private variables, used in inline functions ===== //=========================================================================== -block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions -volatile unsigned char block_buffer_head; // Index of the next block to be pushed -volatile unsigned char block_buffer_tail; // Index of the block to process now +block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions +volatile uint8_t block_buffer_head; // Index of the next block to be pushed +volatile uint8_t block_buffer_tail; // Index of the block to process now #ifdef PLANNER_DIAGNOSTICS // Diagnostic function: Minimum number of planned moves since the last @@ -136,17 +136,17 @@ static bool plan_reset_next_e_sched; // Returns the index of the next block in the ring buffer // NOTE: Removed modulo (%) operator, which uses an expensive divide and multiplication. -static inline int8_t next_block_index(int8_t block_index) { +static inline uint8_t next_block_index(uint8_t block_index) { if (++ block_index == BLOCK_BUFFER_SIZE) - block_index = 0; + block_index = 0; return block_index; } // Returns the index of the previous block in the ring buffer -static inline int8_t prev_block_index(int8_t block_index) { +static inline uint8_t prev_block_index(uint8_t block_index) { if (block_index == 0) - block_index = BLOCK_BUFFER_SIZE; + block_index = BLOCK_BUFFER_SIZE; -- block_index; return block_index; } @@ -358,14 +358,14 @@ void planner_recalculate(const float &safe_final_speed) // Reverse pass // Make a local copy of block_buffer_tail, because the interrupt can alter it // by consuming the blocks, therefore shortening the queue. - unsigned char tail = block_buffer_tail; + uint8_t tail = block_buffer_tail; uint8_t block_index; block_t *prev, *current, *next; // SERIAL_ECHOLNPGM("planner_recalculate - 1"); // At least three blocks are in the queue? - unsigned char n_blocks = (block_buffer_head + BLOCK_BUFFER_SIZE - tail) & (BLOCK_BUFFER_SIZE - 1); + uint8_t n_blocks = (block_buffer_head + BLOCK_BUFFER_SIZE - tail) & (BLOCK_BUFFER_SIZE - 1); if (n_blocks >= 3) { // Initialize the last tripple of blocks. block_index = prev_block_index(block_buffer_head); @@ -709,7 +709,7 @@ float junction_deviation = 0.1; void plan_buffer_line(float x, float y, float z, const float &e, float feed_rate, uint8_t extruder, const float* gcode_target) { // Calculate the buffer head after we push this byte - int next_buffer_head = next_block_index(block_buffer_head); + uint8_t next_buffer_head = next_block_index(block_buffer_head); // If the buffer is full: good! That means we are well ahead of the robot. // Rest here until there is room in the buffer. @@ -1475,7 +1475,7 @@ void update_mode_profile() } #endif //TMC2130 -unsigned char number_of_blocks() +uint8_t number_of_blocks() { return (block_buffer_head + BLOCK_BUFFER_SIZE - block_buffer_tail) & (BLOCK_BUFFER_SIZE - 1); } @@ -1505,8 +1505,8 @@ void planner_add_sd_length(uint16_t sdlen) uint16_t planner_calc_sd_length() { - unsigned char _block_buffer_head = block_buffer_head; - unsigned char _block_buffer_tail = block_buffer_tail; + uint8_t _block_buffer_head = block_buffer_head; + uint8_t _block_buffer_tail = block_buffer_tail; uint16_t sdlen = 0; while (_block_buffer_head != _block_buffer_tail) { diff --git a/Firmware/planner.h b/Firmware/planner.h index 34899cac4..f7fd849e0 100644 --- a/Firmware/planner.h +++ b/Firmware/planner.h @@ -202,16 +202,20 @@ extern uint8_t maxlimit_status; extern float autotemp_factor; #endif - +// Check for BLOCK_BUFFER_SIZE requirements +static_assert(!(BLOCK_BUFFER_SIZE & (BLOCK_BUFFER_SIZE - 1)), + "BLOCK_BUFFER_SIZE must be a power of two"); +static_assert(BLOCK_BUFFER_SIZE <= (UINT8_MAX>>1), + "BLOCK_BUFFER_SIZE too large for uint8_t"); extern block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions // Index of the next block to be pushed into the planner queue. -extern volatile unsigned char block_buffer_head; +extern volatile uint8_t block_buffer_head; // Index of the first block in the planner queue. // This is the block, which is being currently processed by the stepper routine, // or which is first to be processed by the stepper routine. -extern volatile unsigned char block_buffer_tail; +extern volatile uint8_t block_buffer_tail; // Called when the current block is no longer needed. Discards the block and makes the memory // available for new blocks. FORCE_INLINE void plan_discard_current_block() @@ -246,7 +250,7 @@ FORCE_INLINE uint8_t moves_planned() { } FORCE_INLINE bool planner_queue_full() { - unsigned char next_block_index = block_buffer_head; + uint8_t next_block_index = block_buffer_head; if (++ next_block_index == BLOCK_BUFFER_SIZE) next_block_index = 0; return block_buffer_tail == next_block_index; @@ -267,7 +271,7 @@ void reset_acceleration_rates(); void update_mode_profile(); -unsigned char number_of_blocks(); +uint8_t number_of_blocks(); // #define PLANNER_DIAGNOSTICS #ifdef PLANNER_DIAGNOSTICS From 88074ac6c8d941a77e41c84645abe71671041a38 Mon Sep 17 00:00:00 2001 From: "D.R.racer" Date: Tue, 30 Mar 2021 07:16:08 +0200 Subject: [PATCH 70/72] Remove FW version parsing as it can be done at compile time. Code size dropped by >800 bytes. --- Firmware/Configuration.h | 7 ++- Firmware/util.cpp | 123 +++++---------------------------------- 2 files changed, 19 insertions(+), 111 deletions(-) diff --git a/Firmware/Configuration.h b/Firmware/Configuration.h index 4ee9f4fde..efdc63ee8 100644 --- a/Firmware/Configuration.h +++ b/Firmware/Configuration.h @@ -16,8 +16,13 @@ extern uint16_t nPrinterType; extern PGM_P sPrinterName; // Firmware version -#define FW_VERSION "3.10.0" +#define FW_MAJOR 3 +#define FW_MINOR 10 +#define FW_REVISION 0 +#define FW_VERSION STR(FW_MAJOR) "." STR(FW_MINOR) "." STR(FW_REVISION) + #define FW_COMMIT_NR 4481 + // FW_VERSION_UNKNOWN means this is an unofficial build. // The firmware should only be checked into github with this symbol. #define FW_DEV_VERSION FW_VERSION_UNKNOWN diff --git a/Firmware/util.cpp b/Firmware/util.cpp index 5ce21cd0a..97ea9fffa 100644 --- a/Firmware/util.cpp +++ b/Firmware/util.cpp @@ -8,7 +8,8 @@ #include // Allocate the version string in the program memory. Otherwise the string lands either on the stack or in the global RAM. -const char FW_VERSION_STR[] PROGMEM = FW_VERSION; +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 }; const char* FW_VERSION_STR_P() { @@ -139,105 +140,14 @@ inline bool strncmp_PP(const char *p1, const char *p2, uint8_t n) return 0; } -// Parse a major.minor.revision version number. -// Return true if valid. -inline bool parse_version_P(const char *str, uint16_t version[4]) -{ -#if 0 - SERIAL_ECHOPGM("Parsing version string "); - SERIAL_ECHORPGM(str); - SERIAL_ECHOLNPGM(""); -#endif - - const char *major = str; - const char *p = str; - while (is_digit(char(pgm_read_byte(p)))) ++ p; - if (pgm_read_byte(p) != '.') - return false; - const char *minor = ++ p; - while (is_digit(char(pgm_read_byte(p)))) ++ p; - if (pgm_read_byte(p) != '.') - return false; - const char *rev = ++ p; - while (is_digit(char(pgm_read_byte(p)))) ++ p; - if (! is_whitespace_or_nl_or_eol(char(pgm_read_byte(p))) && pgm_read_byte(p) != '-') - return false; - - char buf[5]; - uint8_t n = minor - major - 1; - if (n > 4) - return false; - memcpy_P(buf, major, n); buf[n] = 0; - char *endptr = NULL; - version[0] = strtol(buf, &endptr, 10); - if (*endptr != 0) - return false; - n = rev - minor - 1; - if (n > 4) - return false; - memcpy_P(buf, minor, n); buf[n] = 0; - version[1] = strtol(buf, &endptr, 10); - if (*endptr != 0) - return false; - n = p - rev; - if (n > 4) - return false; - memcpy_P(buf, rev, n); - buf[n] = 0; - version[2] = strtol(buf, &endptr, 10); - if (*endptr != 0) - return false; - - version[3] = FIRMWARE_REVISION_RELEASED; - if (pgm_read_byte(p ++) == '-') { - const char *q = p; - while (! is_whitespace_or_nl_or_eol(char(pgm_read_byte(q)))) - ++ q; - n = q - p; - if (n == strlen_P(STR_REVISION_DEV) && strncmp_PP(p, STR_REVISION_DEV, n) == 0) - version[3] = FIRMWARE_REVISION_DEV; - else if (n == strlen_P(STR_REVISION_ALPHA) && strncmp_PP(p, STR_REVISION_ALPHA, n) == 0) - version[3] = FIRMWARE_REVISION_ALPHA; - else if (n == strlen_P(STR_REVISION_BETA) && strncmp_PP(p, STR_REVISION_BETA, n) == 0) - version[3] = FIRMWARE_REVISION_BETA; - else if ((n == 2 || n == 3) && strncmp_PP(p, STR_REVISION_RC, 2) == 0) { - if (n == 2) - version[3] = FIRMWARE_REVISION_RC; - else { - p += 2; - if (is_digit(pgm_read_byte(p))) - version[3] = FIRMWARE_REVISION_RC + pgm_read_byte(p) - '1'; - else - return false; - } - } else - return false; - } - -#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; -} - // 1 - yes, 0 - false, -1 - error; inline int8_t is_provided_version_newer(const char *version_string) { - uint16_t ver_gcode[4], ver_current[4]; + uint16_t ver_gcode[4]; if (! parse_version(version_string, ver_gcode)) return -1; - if (! parse_version_P(FW_VERSION_STR, ver_current)) - return 0; // this shall not happen for (uint8_t i = 0; i < 3; ++ i) - if (ver_gcode[i] > ver_current[i]) + if (ver_gcode[i] > FW_VERSION_NR[i]) return 1; return 0; } @@ -272,22 +182,17 @@ bool force_selftest_if_fw_version() bool show_upgrade_dialog_if_version_newer(const char *version_string) { - uint16_t ver_gcode[4], ver_current[4]; + uint16_t ver_gcode[4]; if (! parse_version(version_string, ver_gcode)) { // SERIAL_PROTOCOLLNPGM("parse_version failed"); return false; } - if (! parse_version_P(FW_VERSION_STR, ver_current)) { -// SERIAL_PROTOCOLLNPGM("parse_version_P failed"); - return false; // this shall not happen - } -// SERIAL_PROTOCOLLNPGM("versions parsed"); bool upgrade = false; for (uint8_t i = 0; i < 4; ++ i) { - if (ver_gcode[i] > ver_current[i]) { + if (ver_gcode[i] > FW_VERSION_NR[i]) { upgrade = true; break; - } else if (ver_gcode[i] < ver_current[i]) + } else if (ver_gcode[i] < FW_VERSION_NR[i]) break; } @@ -312,16 +217,14 @@ bool show_upgrade_dialog_if_version_newer(const char *version_string) void update_current_firmware_version_to_eeprom() { - for (int8_t i = 0; i < FW_PRUSA3D_MAGIC_LEN; ++ i) + for (int8_t i = 0; i < FW_PRUSA3D_MAGIC_LEN; ++ i){ eeprom_update_byte((uint8_t*)(EEPROM_FIRMWARE_PRUSA_MAGIC+i), pgm_read_byte(FW_PRUSA3D_MAGIC_STR+i)); - uint16_t ver_current[4]; - if (parse_version_P(FW_VERSION_STR, ver_current)) { - eeprom_update_word((uint16_t*)EEPROM_FIRMWARE_VERSION_MAJOR, ver_current[0]); - eeprom_update_word((uint16_t*)EEPROM_FIRMWARE_VERSION_MINOR, ver_current[1]); - eeprom_update_word((uint16_t*)EEPROM_FIRMWARE_VERSION_REVISION, ver_current[2]); - // See FirmwareRevisionFlavorType for the definition of firmware flavors. - eeprom_update_word((uint16_t*)EEPROM_FIRMWARE_VERSION_FLAVOR, ver_current[3]); } + eeprom_update_word((uint16_t*)EEPROM_FIRMWARE_VERSION_MAJOR, FW_VERSION_NR[0]); + eeprom_update_word((uint16_t*)EEPROM_FIRMWARE_VERSION_MINOR, FW_VERSION_NR[1]); + eeprom_update_word((uint16_t*)EEPROM_FIRMWARE_VERSION_REVISION, FW_VERSION_NR[2]); + // See FirmwareRevisionFlavorType for the definition of firmware flavors. + eeprom_update_word((uint16_t*)EEPROM_FIRMWARE_VERSION_FLAVOR, FW_VERSION_NR[3]); } From 8d11ad9d2d2eeec1bda2cff8f473a9622a71006f Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 22 Jun 2021 15:54:22 +0200 Subject: [PATCH 71/72] xfdump: correctly erase all sectors in xfdump_erase --- Firmware/xflash_dump.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/xflash_dump.cpp b/Firmware/xflash_dump.cpp index 7040b502e..e69c1d3a0 100644 --- a/Firmware/xflash_dump.cpp +++ b/Firmware/xflash_dump.cpp @@ -44,7 +44,7 @@ static void xfdump_erase() addr += 4096) { xflash_enable_wr(); - xflash_sector_erase(DUMP_OFFSET); + xflash_sector_erase(addr); xflash_wait_busy(); } } From 66ee9a295f7c74bd8137929c98d93cfd7b8e5d6a Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sat, 19 Jun 2021 14:17:13 +0200 Subject: [PATCH 72/72] Remove useless function EEPROM_read_st --- Firmware/stepper.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/Firmware/stepper.cpp b/Firmware/stepper.cpp index 614480a33..c9cb8bebc 100644 --- a/Firmware/stepper.cpp +++ b/Firmware/stepper.cpp @@ -1559,17 +1559,6 @@ void digitalPotWrite(int address, int value) // From Arduino DigitalPotControl e } #endif -void EEPROM_read_st(int pos, uint8_t* value, uint8_t size) -{ - do - { - *value = eeprom_read_byte((unsigned char*)pos); - pos++; - value++; - }while(--size); -} - - void st_current_init() //Initialize Digipot Motor Current { #ifdef MOTOR_CURRENT_PWM_XY_PIN