xfdump: implement dump-to-xflash functionality

Update xflash_layout to include information about the dump, which sits
at the end of xflash.
This commit is contained in:
Yuri D'Elia 2021-06-08 15:28:02 +02:00
parent b398a09a4f
commit 6dfef76346
4 changed files with 163 additions and 1 deletions

View file

@ -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
Firmware/xflash_dump.cpp Normal file
View file

@ -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
Firmware/xflash_dump.h Normal file
View file

@ -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

View file

@ -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