Browse Source

xfdump: implement dump-to-xflash functionality

Update xflash_layout to include information about the dump, which sits
at the end of xflash.
Yuri D'Elia 2 years ago
parent
commit
6dfef76346
4 changed files with 163 additions and 1 deletions
  1. 1 1
      Firmware/Dcodes.cpp
  2. 106 0
      Firmware/xflash_dump.cpp
  3. 14 0
      Firmware/xflash_dump.h
  4. 42 0
      Firmware/xflash_layout.h

+ 1 - 1
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
 

+ 106 - 0
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);
+}

+ 14 - 0
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

+ 42 - 0
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