[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.h b/sw/device/lib/handler.h
index 6af92d3..50dfadf 100644
--- a/sw/device/lib/handler.h
+++ b/sw/device/lib/handler.h
@@ -16,4 +16,114 @@
kIdMax = 31
} exc_id_t;
+// The RISC-V interrupt vector will not include the addresses of the handlers,
+// instead, it includes (uncompressed) instructions. Thus the interrupt vector
+// will include `j <interrupt handler name>` for each handler.
+//
+// The only requirement on the symbol in the jump is that it must be correctly
+// aligned. If the processor supports the C extension, this can be 2-byte
+// aligned, but 4-byte aligned is compatible with all RISC-V processors.
+//
+// If the processor is not using interrupt vectoring, then there will be a
+// single address where interrupts jump to, which will either contain a function
+// (which will need to be aligned), or will contain a jump to a function, again
+// which will need to be aligned.
+//
+// You only need to use this ABI for handlers that are the first function called
+// in an interrupt handler. Subsequent functions can just use the regular RISC-V
+// calling convention.
+#define INTERRUPT_HANDLER_ABI __attribute__((aligned(4), interrupt))
+
+// The following `handler_*` functions have weak definitions, provided by
+// `handler.c`. This weak definition can be overriden at link-time by providing
+// an additional non-weak definition of each function. Executables and libraries
+// must not contain more than one weak definition of the same symbol.
+
+/**
+ * Default exception handler.
+ *
+ * `handler.c` provides a weak definition of this symbol, which can be overriden
+ * at link-time by providing an additional non-weak definition.
+ */
+INTERRUPT_HANDLER_ABI void handler_exception(void);
+
+/**
+ * SW IRQ handler.
+ *
+ * `handler.c` provides a weak definition of this symbol, which can be overriden
+ * at link-time by providing an additional non-weak definition.
+ */
+INTERRUPT_HANDLER_ABI void handler_irq_software(void);
+
+/**
+ * Timer IRQ handler.
+ *
+ * `handler.c` provides a weak definition of this symbol, which can be overriden
+ * at link-time by providing an additional non-weak definition.
+ */
+INTERRUPT_HANDLER_ABI void handler_irq_timer(void);
+
+/**
+ * external IRQ handler.
+ *
+ * `handler.c` provides a weak definition of this symbol, which can be overriden
+ * at link-time by providing an additional non-weak definition.
+ */
+INTERRUPT_HANDLER_ABI void handler_irq_external(void);
+
+/**
+ * Instruction access fault.
+ *
+ * Called by default implementation of `handler_exception`. If that function is
+ * overriden, this function may not be called.
+ *
+ * `handler.c` provides a weak definition of this symbol, which can be overriden
+ * at link-time by providing an additional non-weak definition.
+ */
+void handler_instr_acc_fault(void);
+
+/**
+ * Illegal Instruction fault.
+ *
+ * Called by default implementation of `handler_exception`. If that function is
+ * overriden, this function may not be called.
+ *
+ * `handler.c` provides a weak definition of this symbol, which can be overriden
+ * at link-time by providing an additional non-weak definition.
+ */
+void handler_instr_ill_fault(void);
+
+/**
+ * Breakpoint handler.
+ *
+ * Called by default implementation of `handler_exception`. If that function is
+ * overriden, this function may not be called.
+ *
+ * `handler.c` provides a weak definition of this symbol, which can be overriden
+ * at link-time by providing an additional non-weak definition.
+ */
+void handler_bkpt(void);
+
+/**
+ * Load store unit fault.
+ *
+ * Called by default implementation of `handler_exception`. If that function is
+ * overriden, this function may not be called.
+ *
+ * `handler.c` provides a weak definition of this symbol, which can be overriden
+ * at link-time by providing an additional non-weak definition.
+ */
+void handler_lsu_fault(void);
+
+/**
+ * Exception call handler.
+ *
+ * Called by default implementation of `handler_exception`. If that function is
+ * overriden, this function may not be called.
+ *
+ * `handler.c` provides a weak definition of this symbol, which can be overriden
+ * at link-time by providing an additional non-weak definition.
+ */
+void handler_ecall(void);
+
#endif