From 6dfef763467af6ec944d45084a97cc3cc8f1f23f Mon Sep 17 00:00:00 2001 From: Yuri D'Elia <wavexx@thregr.org> Date: Tue, 8 Jun 2021 15:28:02 +0200 Subject: [PATCH] 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 <stddef.h> + +#include <avr/wdt.h> +#include <avr/interrupt.h> + +#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