#pragma once #include "Arduino.h" struct FaultStatusRegisters { uint32_t HFSR; uint32_t CFSR; uint32_t MMFAR; uint32_t BFAR; uint32_t DFSR; uint32_t AFSR; uint32_t SHCSR; }; enum class FaultType { HardFault, MemManage, BusFault, UsageFault }; struct FlashDump { FaultType type; uint32_t stacked_registers[8]; FaultStatusRegisters fsr; }; struct FlashDumpInfo { uint8_t _zero; // Used to check that the storage area has been initialized uint32_t n_dumps; }; 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(FaultType fault_type, 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); void uart_wait_for_txrdy(); size_t uart_write(uint8_t c); size_t uart_print(const char* str); size_t uart_print_hex(uint32_t x); void print_dumped_faults(bool in_irq=false); void print_stacked_registers(const uint32_t *stack, bool in_irq=false); void print_fault_registers(const FaultStatusRegisters *fsr, bool in_irq=false); FaultStatusRegisters get_current_fsr(); const char* get_fault_type_name(FaultType type); void fault_handler(uint32_t *stack_addr, FaultType fault_type, const int *leds, unsigned n_leds); void inline busy_wait(size_t iterations) { for (size_t i = 0; i < iterations; i++) { // Does nothing, but ensures the compiler doesn't optimize the loop away. __ASM ("" ::: "memory"); } }