Bugfixes for fault handlers
This commit is contained in:
parent
2ca1ec4b8f
commit
fb68e8c4d6
|
@ -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");
|
||||
}
|
||||
}
|
230
src/debug.cpp
230
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));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue