From fb68e8c4d658e3105ee287a8412a70ddb81ad393 Mon Sep 17 00:00:00 2001 From: jvblanck Date: Sun, 18 Jul 2021 17:14:03 +0200 Subject: [PATCH] Bugfixes for fault handlers --- include/debug.h | 40 ++++++--- src/debug.cpp | 230 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 181 insertions(+), 89 deletions(-) diff --git a/include/debug.h b/include/debug.h index c06e729..58aa341 100644 --- a/include/debug.h +++ b/include/debug.h @@ -5,28 +5,35 @@ 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; }; -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, +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). @@ -34,13 +41,24 @@ void flash_dump_write_fault(const uint32_t *stack, const FlashDumpInfo *flash_dump_get_info(); const FlashDump *flash_dump_get_fault(uint32_t n); -bool check_serial_available(); +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(); -void print_stacked_registers(const uint32_t *stack); -void print_fault_registers(const FaultStatusRegisters *fsr); +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(); -void fault_handler(uint32_t *stack_addr, const char *fault_type, +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"); + } +} \ No newline at end of file diff --git a/src/debug.cpp b/src/debug.cpp index 49dc785..527de31 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -6,11 +6,13 @@ DueFlashStorage Flash; -void flash_dump_fault(const uint32_t *stack, const FaultStatusRegisters *fsr) { +void flash_dump_write_fault(FaultType fault_type, const uint32_t *stack, + const FaultStatusRegisters *fsr) { FlashDumpInfo info; memcpy(&info, flash_dump_get_info(), sizeof(info)); FlashDump dump; + dump.type = fault_type; memcpy(dump.stacked_registers, stack, sizeof(dump.stacked_registers)); memcpy(&dump.fsr, fsr, sizeof(dump.fsr)); @@ -36,92 +38,164 @@ const FlashDump *flash_dump_get_fault(uint32_t n) { return (const FlashDump *)Flash.readAddress(addr); } -bool check_serial_available() { - int available = Serial.availableForWrite(); - if (available == 0) { - // No bytes available for write, maybe we were just writing? Wait 10 ms and - // check again. - delay(10); - available = Serial.availableForWrite(); - if (available == 0) { - // Still no bytes available for write, looks like we can't write at all. - return false; +void uart_wait_for_txrdy() { + while ((UART->UART_SR & UART_SR_TXRDY) != UART_SR_TXRDY) + ; +} + +size_t uart_write(uint8_t c) { + uart_wait_for_txrdy(); + UART->UART_THR = c; + uart_wait_for_txrdy(); + return 1; +} + +size_t uart_print(const char *str) { + const char *c = str; + while (*c != '\0') { + uart_write(*c); + c++; + } + return c - str; +} + +size_t uart_print_hex(uint32_t x) { + for (int i = 0; i < 8; i++) { + uint8_t nibble = (x >> (7 - i) * 4) & 0xF; + if (nibble < 0xA) { + uart_write(nibble + '0'); + } else { + uart_write(nibble - 0xA + 'A'); } } - // Write a byte, and wait 10 ms. If the number of available bytes decreased, - // we can't write. - Serial.write('\0'); - delay(10); - return Serial.availableForWrite() >= available; + return 8; } -void print_dumped_faults() { +size_t write(uint8_t c, bool in_irq) { + if (in_irq) { + uart_write(c); + } else { + Serial.write(c); + } +} +size_t print(const char *str, bool in_irq) { + if (in_irq) { + uart_print(str); + } else { + Serial.print(str); + } +} +size_t print_hex(uint32_t x, bool in_irq) { + if (in_irq) { + uart_print_hex(x); + } else { + Serial.print(x, HEX); + } +} + +void print_dumped_faults(bool in_irq) { uint32_t n = flash_dump_get_info()->n_dumps; - Serial.println("===================="); - Serial.print(n); - Serial.println(" DUMPED FAULTS"); + print("====================\n", in_irq); + print_hex(n, in_irq); + print(" DUMPED FAULTS\n", in_irq); for (uint32_t i = 0; i < n; i++) { - Serial.println("--------------------"); - Serial.print("Fault "); - Serial.println(i); + print("--------------------\n", in_irq); + print("Fault ", in_irq); + print_hex(i, in_irq); + write('\n', in_irq); const FlashDump *dump = flash_dump_get_fault(i); - print_stacked_registers(dump->stacked_registers); - print_fault_registers(&dump->fsr); + print(get_fault_type_name(dump->type), in_irq); + write('\n', in_irq); + print_stacked_registers(dump->stacked_registers, in_irq); + print_fault_registers(&dump->fsr, in_irq); } - Serial.println("===================="); + print("====================\n", in_irq); } -void print_stacked_registers(const uint32_t *stack) { - Serial.print("R0 = "); - Serial.println(stack[0], HEX); - Serial.print("R1 = "); - Serial.println(stack[1], HEX); - Serial.print("R2 = "); - Serial.println(stack[2], HEX); - Serial.print("R3 = "); - Serial.println(stack[3], HEX); - Serial.print("R12 = "); - Serial.println(stack[4], HEX); - Serial.print("LR = "); - Serial.println(stack[5], HEX); - Serial.print("PC = "); - Serial.println(stack[6], HEX); - Serial.print("PSR = "); - Serial.println(stack[7], HEX); - Serial.println(); +void print_stacked_registers(const uint32_t *stack, bool in_irq) { + print("R0 = ", in_irq); + print_hex(stack[0], in_irq); + write('\n', in_irq); + print("R1 = ", in_irq); + print_hex(stack[1], in_irq); + write('\n', in_irq); + print("R2 = ", in_irq); + print_hex(stack[2], in_irq); + write('\n', in_irq); + print("R3 = ", in_irq); + print_hex(stack[3], in_irq); + write('\n', in_irq); + print("R12 = ", in_irq); + print_hex(stack[4], in_irq); + write('\n', in_irq); + print("LR = ", in_irq); + print_hex(stack[5], in_irq); + write('\n', in_irq); + print("PC = ", in_irq); + print_hex(stack[6], in_irq); + write('\n', in_irq); + print("PSR = ", in_irq); + print_hex(stack[7], in_irq); + write('\n', in_irq); + write('\n', in_irq); } -void print_fault_registers(const FaultStatusRegisters *fsr) { - Serial.print("HFSR = "); - Serial.println(fsr->HFSR, HEX); - Serial.print("CFSR = "); - Serial.println(fsr->CFSR, HEX); - Serial.print("BFAR = "); - Serial.println(fsr->BFAR, HEX); - Serial.print("DFSR = "); - Serial.println(fsr->DFSR, HEX); - Serial.print("AFSR = "); - Serial.println(fsr->AFSR, HEX); - Serial.print("SHCSR = "); - Serial.println(fsr->SHCSR, HEX); - Serial.println(); +void print_fault_registers(const FaultStatusRegisters *fsr, bool in_irq) { + print("HFSR = ", in_irq); + print_hex(fsr->HFSR, in_irq); + write('\n', in_irq); + print("CFSR = ", in_irq); + print_hex(fsr->CFSR, in_irq); + write('\n', in_irq); + print("MMFAR = ", in_irq); + print_hex(fsr->MMFAR, in_irq); + write('\n', in_irq); + print("BFAR = ", in_irq); + print_hex(fsr->BFAR, in_irq); + write('\n', in_irq); + + print("DFSR = ", in_irq); + print_hex(fsr->DFSR, in_irq); + write('\n', in_irq); + print("AFSR = ", in_irq); + print_hex(fsr->AFSR, in_irq); + write('\n', in_irq); + print("SHCSR = ", in_irq); + print_hex(fsr->SHCSR, in_irq); + write('\n', in_irq); + write('\n', in_irq); } FaultStatusRegisters get_current_fsr() { FaultStatusRegisters fsr; fsr.HFSR = SCB->HFSR; fsr.CFSR = SCB->CFSR; + fsr.MMFAR = SCB->MMFAR; fsr.BFAR = SCB->BFAR; + fsr.DFSR = SCB->DFSR; fsr.AFSR = SCB->AFSR; fsr.SHCSR = SCB->SHCSR; return fsr; } -void fault_handler(uint32_t *stack_addr, const char *fault_type, - const int *leds, unsigned n_leds) { +const char *get_fault_type_name(FaultType type) { + switch (type) { + case FaultType::HardFault: + return "HARD FAULT"; + case FaultType::MemManage: + return "MEMMANGAGE FAULT"; + case FaultType::BusFault: + return "BUS FAULT"; + case FaultType::UsageFault: + return "USAGE FAULT"; + } +} + +void fault_handler(uint32_t *stack_addr, FaultType fault_type, const int *leds, + unsigned n_leds) { Serial.begin(9600); for (unsigned i = 0; i < n_leds; i++) { pinMode(leds[i], OUTPUT); @@ -129,25 +203,23 @@ void fault_handler(uint32_t *stack_addr, const char *fault_type, FaultStatusRegisters fsr = get_current_fsr(); - flash_dump_fault(stack_addr, &fsr); + flash_dump_write_fault(fault_type, stack_addr, &fsr); while (1) { - if (check_serial_available()) { - Serial.println("===================="); - Serial.println(fault_type); - Serial.println("===================="); + uart_print("====================\n"); + uart_print(get_fault_type_name(fault_type)); + uart_print("\n====================\n"); - print_stacked_registers(stack_addr); - print_fault_registers(&fsr); - } + print_stacked_registers(stack_addr, true); + print_fault_registers(&fsr, true); for (unsigned i = 0; i < n_leds; i++) { digitalWrite(leds[i], HIGH); } - delay(500); + busy_wait(5000000); for (unsigned i = 0; i < n_leds; i++) { digitalWrite(leds[i], LOW); } - delay(500); + busy_wait(5000000); } } @@ -192,29 +264,31 @@ void UsageFault_Handler(void) { } void HardFault_Handler_C(uint32_t *stack_addr) { - // All LEDs - static const int leds[] = {led1, led2, led3, led4, led5, led6, - led7, led8, led9, led10, led11, led12, - led13, led14, led15, led16}; - fault_handler(stack_addr, "HARD FAULT", leds, sizeof(leds) / sizeof(int)); + // All LEDs except for the bottom ones + static const int leds[] = {led1, led2, led3, led4, led5, led6, led7, + led8, led9, led10, led11, led12, led14, led15}; + fault_handler(stack_addr, FaultType::HardFault, leds, + sizeof(leds) / sizeof(int)); } void MemManage_Handler_C(uint32_t *stack_addr) { // Left of display static const int leds[] = {led11, led12, led13}; - fault_handler(stack_addr, "MEMMANAGE FAULT", leds, + fault_handler(stack_addr, FaultType::MemManage, leds, sizeof(leds) / sizeof(int)); } void BusFault_Handler_C(uint32_t *stack_addr) { // Right of display static const int leds[] = {led14, led15, led16}; - fault_handler(stack_addr, "BUS FAULT", leds, sizeof(leds) / sizeof(int)); + fault_handler(stack_addr, FaultType::BusFault, leds, + sizeof(leds) / sizeof(int)); } void UsageFault_Handler_C(uint32_t *stack_addr) { // Left and right of display static const int leds[] = {led11, led12, led13, led14, led15, led16}; - fault_handler(stack_addr, "USAGE FAULT", leds, sizeof(leds) / sizeof(int)); + fault_handler(stack_addr, FaultType::UsageFault, leds, + sizeof(leds) / sizeof(int)); } }