[sw] Split irq control functions from handlers
When testing, it is useful to be able to use the irq control functions,
while also overriding the default handler implementations in handler.c.
This commit splits the libraries, so components can both control their
interrupts and override the default handlers (which depend on uart).
This commit also splits off the declarations of the handler function
names into the handler header, so that other libraries can produce
compatible definitions which override the default, weak-linkage,
definitions. In particular, only the default definitions should have
`__attribute__((weak))`, and only the hardware interrupt handlers should
be aligned and have `__attribute__((interrupt))`.
This commit also documents the requirements about interrupt handler and
mtvec address alignment.
Signed-off-by: Sam Elliott <selliott@lowrisc.org>
diff --git a/sw/device/lib/handler.c b/sw/device/lib/handler.c
index 12bfcdc..ed5728c 100644
--- a/sw/device/lib/handler.c
+++ b/sw/device/lib/handler.c
@@ -9,52 +9,6 @@
#include "sw/device/lib/uart.h"
/**
- * Default exception handler. Can be overidden.
- */
-void handler_exception(void) __attribute__((aligned(4), interrupt, weak));
-
-/**
- * SW IRQ handler. Can be overidden.
- */
-void handler_irq_software(void) __attribute__((aligned(4), interrupt, weak));
-
-/**
- * Timer IRQ handler. Can be overidden.
- */
-void handler_irq_timer(void) __attribute__((aligned(4), interrupt, weak));
-
-/**
- * external IRQ handler. Can be overidden.
- */
-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) {
@@ -79,7 +33,7 @@
}
// Below functions are default weak exception handlers meant to be overriden
-void handler_exception(void) {
+__attribute__((weak)) void handler_exception(void) {
uint32_t mcause;
exc_id_t exc_cause;
@@ -114,48 +68,48 @@
}
}
-void handler_irq_software(void) {
+__attribute__((weak)) void handler_irq_software(void) {
uart_send_str("Software IRQ triggered!\n");
while (1) {
}
}
-void handler_irq_timer(void) {
+__attribute__((weak)) void handler_irq_timer(void) {
uart_send_str("Timer IRQ triggered!\n");
while (1) {
}
}
-void handler_irq_external(void) {
+__attribute__((weak)) void handler_irq_external(void) {
uart_send_str("External IRQ triggered!\n");
while (1) {
}
}
-void handler_instr_acc_fault(void) {
+__attribute__((weak)) 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) {
+__attribute__((weak)) 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) {
+__attribute__((weak)) 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) {
+__attribute__((weak)) 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) {
+__attribute__((weak)) void handler_ecall(void) {
uart_send_str("Environment call encountered\n");
while (1) {
}