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/65] 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 1db8a406..56aed489 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/65] 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 dace219f..9a353be8 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 856d04ad..02ef7422 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 92df0122..b2bb36bb 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/65] 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 9a353be8..5af12e2e 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/65] 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 5af12e2e..d550afeb 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/65] 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 d550afeb..b3bdbdca 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 b2bb36bb..01ef1ef9 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/65] 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 b3bdbdca..7585af0b 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/65] 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 7585af0b..9603dc62 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/65] 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 9603dc62..31922314 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 02ef7422..c019c981 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/65] 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 31922314..d6ab3d99 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/65] 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 d6ab3d99..9de93f77 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/65] 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 9de93f77..e1b38ad4 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 01a39652..9a1113b9 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 00000000..39b5f26c --- /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/65] 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 e9d894a5..43680b2e 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/65] 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 43680b2e..cc758ebf 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 c9ad5275..a75abb18 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/65] 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 e1b38ad4..475714c2 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 00000000..7c44e577 --- /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 00000000..8492523c --- /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 39b5f26c..a5e5559c 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/65] 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 12a9ed51..2ba73228 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/65] 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 475714c2..bbe39775 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 c019c981..4e37cc24 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 01ef1ef9..4f95ed7a 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/65] 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 4f95ed7a..2048b416 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 56aed489..e70227c0 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 02b9d308..39eb0a03 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/65] 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 39eb0a03..8edcf707 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/65] 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 7c44e577..519ecf1b 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/65] 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 519ecf1b..f1ff9ded 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/65] 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 2ba73228..ecd2df2c 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/65] 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 2ec2077e..fa86f456 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/65] 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 bbe39775..48f67cb3 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 6ff086f4..44e1d16d 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 f1ff9ded..65722b1c 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 a5e5559c..f44b9c80 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/65] 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 48f67cb3..9a78f296 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/65] 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 acd7883d..f49f5e1c 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 ddf7e77a..0d900508 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 e7b114d9..73eb52f6 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 cde81249..738f421e 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 16fba5d7..ab65d024 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 13fc2a79..48154903 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/65] 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 65722b1c..74b049f8 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/65] 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 74b049f8..655765b8 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/65] 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 9a78f296..dc92d143 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/65] 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 655765b8..0b9883a1 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/65] 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 f44b9c80..570098bd 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/65] 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 f49f5e1c..b05475ab 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 0d900508..0750bc5c 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 73eb52f6..d8a4158b 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 738f421e..9a25dce2 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/65] 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 dc92d143..69de8e11 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/65] 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 2048b416..dd713737 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 8edcf707..3eecb765 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 0b9883a1..99d92b55 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 8492523c..7ad1c546 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 570098bd..5bbe2a79 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 ea92359c..06544f19 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/65] 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 69de8e11..f821c47f 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/65] 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 f821c47f..9451308e 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/65] 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 99d92b55..66a85112 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/65] 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 3eecb765..ba8f42e7 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/65] 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 dd713737..50d5bee3 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 ba8f42e7..f9303b48 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 ab65d024..b03fe726 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 48154903..934c0913 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 66a85112..5667e41c 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 06544f19..bc335307 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/65] 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 50d5bee3..eec6591b 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 f9303b48..c0729245 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 5667e41c..b9d2679a 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 7ad1c546..18e1c684 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 5bbe2a79..31f67b7d 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/65] 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 eec6591b..91da6cc9 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 b9d2679a..290a8d99 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 18e1c684..658ecd2d 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/65] 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 290a8d99..3f293890 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/65] 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 51da4ee2..50206ab9 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 c42b74b1..2a70d98a 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 4c20082e..7ccd9151 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 35313a41..4686f097 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 b05475ab..fa7f2690 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 0750bc5c..10aa14f9 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 d8a4158b..4540fd72 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 9a25dce2..53773e97 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 b03fe726..f6b17889 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 934c0913..92698b47 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/65] 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 9451308e..1fbca4c6 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 44e1d16d..9a77c5ab 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 3f293890..8b4ab995 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/65] 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 1fbca4c6..e9ba0454 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 4e37cc24..c4b470e4 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 91da6cc9..7656ddcd 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 fa86f456..5adba50d 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 c0729245..fcf2e458 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 fa7f2690..3cbc3829 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 10aa14f9..9b4e591a 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 4540fd72..74ef38b6 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 53773e97..17758613 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 f6b17889..66643556 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 92698b47..842ff40b 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 658ecd2d..f517a592 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 bc335307..cc2d940d 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/65] 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 7656ddcd..54d0b9c2 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 e70227c0..62aafe42 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 fcf2e458..1820d0e6 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/65] 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 54d0b9c2..afb9672d 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 a86c49e1..caf759f1 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 a9471139..cbaee9b8 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 35b05f0e..1d0dfdb6 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 1820d0e6..c9863787 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 3aab932d..d8781001 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 cf9b05b7..5ce21cd0 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/65] 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 afb9672d..56a90849 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 c9863787..caf9c47c 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/65] 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 98e5102c..c2c5ca93 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 56a90849..6e0ddcf9 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 1d0dfdb6..3e617a66 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 caf9c47c..b277df4c 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 d8781001..8c344d12 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/65] 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 b277df4c..c2c14883 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/65] 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 e9ba0454..dc60fcd7 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/65] 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 dc60fcd7..ea27caff 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/65] 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 3cbc3829..aa625c64 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 9b4e591a..ddafa6f4 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 74ef38b6..29ff5b35 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 17758613..342a9a1f 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 66643556..aacb7cb7 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 842ff40b..8659c582 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/65] 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 6e0ddcf9..15fdc7c2 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 f517a592..8866b1ec 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/65] 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 15fdc7c2..286c3bc8 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/65] 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 286c3bc8..1b50daaf 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/65] 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 ea27caff..0b2943b0 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 c4b470e4..477a5847 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 1b50daaf..acf73ab8 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 c2c14883..dd3d3f5c 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 8b4ab995..4c9aca42 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 8866b1ec..c9a82c66 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 31f67b7d..0e533494 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/65] 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 0b2943b0..09c41299 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/65] 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 09c41299..713f3ed5 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/65] 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 dd3d3f5c..0b8cf350 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/65] 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 0b8cf350..6e4b3301 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/65] 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 713f3ed5..c4fd5311 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 477a5847..c4b470e4 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 acf73ab8..1b50daaf 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 00000000..896f59bb --- /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 6e4b3301..844436aa 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 4c9aca42..7040b502 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 c9a82c66..6ece99c6 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 0e533494..22353a74 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 bff79d290a33e806bf7d05a4c867157fb90bda59 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sat, 19 Jun 2021 13:56:40 +0200 Subject: [PATCH 62/65] 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 896f59bb..2ffb88ad 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 63/65] 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 c4fd5311..5a840ee4 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 934b567e5afefa53b198713bd288e7d5fdccbb20 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 21 Jun 2021 22:36:32 +0200 Subject: [PATCH 64/65] 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 1b50daaf..4b374cd2 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 65/65] 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 22353a74..5d92d6e6 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 {