Add exception handling for instruction / ld errors
Addresses #18
diff --git a/sw/lib/handler.c b/sw/lib/handler.c
index cefe4e5..20d0ba7 100644
--- a/sw/lib/handler.c
+++ b/sw/lib/handler.c
@@ -2,7 +2,10 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
+#include "handler.h"
+
#include "common.h"
+#include "uart.h"
/**
* Default exception handler. Can be overidden.
@@ -24,23 +27,135 @@
*/
void handler_irq_external(void) __attribute__((aligned(4), interrupt, weak));
+/**
+ * Instruction access fault. Can be overriden.
+ */
+void handler_instr_acc_fault(void) __attribute__((aligned(4), interrupt, weak));
+
+/**
+ * Illegal Instruction fault. Can be overriden.
+ */
+void handler_instr_ill_fault(void) __attribute__((aligned(4), interrupt, weak));
+;
+
+/**
+ * Breakpoint handler. Can be overriden.
+ */
+void handler_bkpt(void) __attribute__((aligned(4), interrupt, weak));
+
+/**
+ * Load store unit fault. Can be overriden.
+ */
+void handler_lsu_fault(void) __attribute__((aligned(4), interrupt, weak));
+
+/**
+ * Exception call handler. Can be overriden.
+ */
+void handler_ecall(void) __attribute__((aligned(4), interrupt, weak));
+
+/**
+ * Return value of mtval
+ */
+static uint32_t get_mtval(void) {
+ uint32_t mtval;
+ asm volatile("csrr %0, mtval" : "=r"(mtval) : :);
+ return mtval;
+}
+
+/**
+ * Default Error Handling
+ * @param error message supplied by caller
+ * TODO - this will be soon by a real print formatting
+ */
+static void print_exc_msg(const char *msg) {
+ const uint32_t mtval = get_mtval();
+ uart_send_str((char *)msg);
+ uart_send_str("MTVAL value is ");
+ uart_send_uint(mtval, 32);
+ uart_send_str("\n");
+ while (1) {
+ };
+}
+
// Below functions are default weak exception handlers meant to be overriden
void handler_exception(void) {
- while (1) {
+ uint32_t mcause;
+ exc_id_t exc_cause;
+
+ asm volatile("csrr %0 , mcause" : "=r"(mcause) : :);
+ exc_cause = (exc_id_t)(mcause & kIdMax);
+
+ switch (exc_cause) {
+ case kInstMisa:
+ handler_instr_acc_fault();
+ break;
+ case kInstAccFault:
+ handler_instr_acc_fault();
+ break;
+ case kInstIllegalFault:
+ handler_instr_ill_fault();
+ break;
+ case kBkpt:
+ handler_bkpt();
+ break;
+ case kLoadAccFault:
+ handler_lsu_fault();
+ break;
+ case kStrAccFault:
+ handler_lsu_fault();
+ break;
+ case kECall:
+ handler_ecall();
+ break;
+ default:
+ while (1) {
+ };
}
}
void handler_irq_software(void) {
+ uart_send_str("Software IRQ triggered!\n");
while (1) {
}
}
void handler_irq_timer(void) {
+ uart_send_str("Timer IRQ triggered!\n");
while (1) {
}
}
void handler_irq_external(void) {
+ uart_send_str("External IRQ triggered!\n");
+ while (1) {
+ }
+}
+
+void handler_instr_acc_fault(void) {
+ const char fault_msg[] =
+ "Instruction access fault, mtval shows fault address\n";
+ print_exc_msg(fault_msg);
+}
+
+void handler_instr_ill_fault(void) {
+ const char fault_msg[] =
+ "Illegal Instruction fault, mtval shows instruction content\n";
+ print_exc_msg(fault_msg);
+}
+
+void handler_bkpt(void) {
+ const char exc_msg[] =
+ "Breakpoint triggerd, mtval shows the breakpoint address\n";
+ print_exc_msg(exc_msg);
+}
+
+void handler_lsu_fault(void) {
+ const char exc_msg[] = "Load/Store fault, mtval shows the fault address\n";
+ print_exc_msg(exc_msg);
+}
+
+void handler_ecall(void) {
+ uart_send_str("Environment call encountered\n");
while (1) {
}
}