synth/arm/crash.cc

119 lines
2.8 KiB
C++
Raw Permalink Normal View History

2022-05-17 03:56:25 +00:00
#include <cstdint>
#include "gpio.h"
#include "itoa.h"
#include "sleep.h"
2022-06-19 07:48:28 +00:00
#include "trace.h"
2022-05-17 03:56:25 +00:00
#include "uart.h"
extern "C" uint32_t _initial_stack_pointer, _text_begin, _text_end;
namespace crash {
namespace {
[[maybe_unused]] void CrashHexDump(uint32_t* begin, uint32_t* end,
int direction = 1) {
char number[] = "00000000 ";
char addr[] = "00000000: ";
int i = 0;
itoa(reinterpret_cast<uint32_t>(begin), addr);
2022-05-17 17:17:56 +00:00
UartWriteCrash(addr);
2022-05-17 03:56:25 +00:00
for (uint32_t* ptr = begin; direction > 0 ? ptr < end : ptr > end;
ptr += direction, i++) {
itoa(*ptr, number);
2022-05-17 17:17:56 +00:00
UartWriteCrash(number);
2022-05-17 03:56:25 +00:00
if (i % 4 == 3) {
2022-05-17 17:17:56 +00:00
UartWriteCrash("\r\n");
2022-05-17 03:56:25 +00:00
itoa(reinterpret_cast<uint32_t>(ptr + 1), addr);
2022-05-17 17:17:56 +00:00
UartWriteCrash(addr);
2022-05-17 03:56:25 +00:00
}
}
if (i % 4 != 3) {
2022-05-17 17:17:56 +00:00
UartWriteCrash("\r\n");
2022-05-17 03:56:25 +00:00
}
}
void StackTrace(uint32_t* sp) {
char number[] = "00000000\r\n";
for (uint32_t* ptr = sp; ptr < &_initial_stack_pointer; ptr++) {
auto addr = reinterpret_cast<uint32_t*>(*ptr);
if (addr < &_text_begin || addr >= &_text_end || (*ptr & 0x1) == 0) {
continue;
}
itoa(*ptr, number);
2022-05-17 17:17:56 +00:00
UartWriteCrash(number);
2022-05-17 03:56:25 +00:00
}
}
struct Armv6mRegs {
uintptr_t r4;
uintptr_t r5;
uintptr_t r6;
uintptr_t r7;
uintptr_t r8;
uintptr_t r9;
uintptr_t r10;
uintptr_t r11;
uintptr_t sp;
// saved by the CPU
uintptr_t r0;
uintptr_t r1;
uintptr_t r2;
uintptr_t r3;
uintptr_t r12;
uintptr_t lr;
uintptr_t pc;
uintptr_t xpsr;
};
void CrashHandler(Armv6mRegs* regs) {
char number[] = "00000000\r\n";
2022-05-17 17:17:56 +00:00
UartWriteCrash("\r\n\r\nCra$h!!\r\n- xpsr: 0x");
2022-05-17 03:56:25 +00:00
itoa(regs->xpsr, number);
2022-05-17 17:17:56 +00:00
UartWriteCrash(number);
UartWriteCrash("- pc: 0x");
2022-05-17 03:56:25 +00:00
itoa(regs->pc, number);
2022-05-17 17:17:56 +00:00
UartWriteCrash(number);
UartWriteCrash("- lr: 0x");
2022-05-17 03:56:25 +00:00
itoa(regs->lr, number);
2022-05-17 17:17:56 +00:00
UartWriteCrash(number);
UartWriteCrash("- Stack trace:\r\n");
2022-05-17 03:56:25 +00:00
StackTrace(reinterpret_cast<uint32_t*>(regs->sp));
2022-06-19 07:48:28 +00:00
tracing::dump();
2022-05-17 03:56:25 +00:00
while (1) {
gpio0->data = 0x55;
sleep(100);
gpio0->data = 0xaa;
sleep(100);
}
}
} // namespace
__attribute__((naked)) void HardFaultHandler() {
asm volatile(
// set those leds first
"mov r0, %0 \n"
"mov r1, #0xa5 \n"
"str r1, [r0] \n"
"mov r0, r8 \n"
"mov r1, r9 \n"
"mov r2, r10 \n"
"mov r3, r11 \n"
"mrs lr, msp \n"
"push {r0-r3, lr} \n"
"push {r4-r7} \n"
2022-05-17 17:17:56 +00:00
:
: "r"(gpio0));
asm volatile(
2022-05-17 03:56:25 +00:00
"mrs r0, msp \n"
2022-05-17 17:17:56 +00:00
"mov r1, %0 \n"
2022-05-17 03:56:25 +00:00
"blx r1 \n"
:
2022-05-17 17:17:56 +00:00
: "r"(CrashHandler));
2022-05-17 03:56:25 +00:00
}
} // namespace crash