#pragma once

#include "Arduino.h"

struct FaultStatusRegisters {
  uint32_t HFSR;
  uint32_t CFSR;
  uint32_t BFAR;
  uint32_t DFSR;
  uint32_t AFSR;
  uint32_t SHCSR;
};

struct FlashDumpInfo {
  uint8_t _zero; // Used to check that the storage area has been initialized
  uint32_t n_dumps;
};

struct FlashDump {
  uint32_t stacked_registers[8];
  FaultStatusRegisters fsr;
};

constexpr uint32_t FLASH_DUMP_ADDR_BASE = 0;
constexpr uint32_t FLASH_DUMP_ADDR_INFO = FLASH_DUMP_ADDR_BASE + 0;
constexpr uint32_t FLASH_DUMP_ADDR_DUMPS =
    FLASH_DUMP_ADDR_INFO + sizeof(FlashDump);

void flash_dump_write_fault(const uint32_t *stack,
                            const FaultStatusRegisters *fsr);
/**
 * Read the FlashDumpInfo (and create it if it hasn't been initialized yet).
 */
const FlashDumpInfo *flash_dump_get_info();
const FlashDump *flash_dump_get_fault(uint32_t n);

bool check_serial_available();

void print_dumped_faults();
void print_stacked_registers(const uint32_t *stack);
void print_fault_registers(const FaultStatusRegisters *fsr);

FaultStatusRegisters get_current_fsr();

void fault_handler(uint32_t *stack_addr, const char *fault_type,
                   const int *leds, unsigned n_leds);