Bugfixes for fault handlers
This commit is contained in:
		
							
								
								
									
										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));
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user