aboutsummaryrefslogtreecommitdiff
path: root/src/interrupts/interrupts.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interrupts/interrupts.c')
-rw-r--r--src/interrupts/interrupts.c135
1 files changed, 135 insertions, 0 deletions
diff --git a/src/interrupts/interrupts.c b/src/interrupts/interrupts.c
new file mode 100644
index 0000000..121d79c
--- /dev/null
+++ b/src/interrupts/interrupts.c
@@ -0,0 +1,135 @@
+#include "io.h"
+#include "uart.h"
+#include "svc_interface.h"
+#include "armclock.h"
+#include "scheduler.h"
+/**
+ @brief The undefined instruction interrupt handler
+**/
+
+
+void __attribute__((noreturn)) setup(void);
+
+// from what I've heard, reset is never used on the Pi;
+// in our case it should run once - when stage1 of the kernel
+// jumps to stage2
+void reset_handler(void)
+{
+ setup();
+}
+
+void undefined_instruction_vector(void)
+{
+ error("Undefined instruction occured");
+}
+
+uint32_t supervisor_call_handler(uint32_t regs[14])
+{
+ switch(regs[0]) {
+ case UART_PUTCHAR:
+ if (putchar_non_blocking(regs[1]))
+ schedule_wait_for_output(regs, regs[1]);
+ break;
+ case UART_GETCHAR:
+ {
+ int c;
+ if ((c = getchar_non_blocking()) == -1)
+ schedule_wait_for_input(regs);
+
+ regs[0] = c;
+ break;
+ }
+ case UART_WRITE:
+ error("UART_WRITE not implemented!!!!!");
+ break;
+ default:
+ // perhaps we should kill the process now?
+ error("unknown supervisor call type!!!!!");
+ }
+
+ return 0; // a dummy value
+}
+
+void abort_handler(void)
+{
+ // TODO maybe dump registers here?
+ error("re-entered system due to data/prefetch abort");
+}
+
+void generic_handler(void)
+{
+ error("something weird happened");
+}
+
+void irq_handler(uint32_t regs[14])
+{
+ if (armclk_irq_pending())
+ {
+ write_SPSR(PL1_PSR);
+ asm volatile("mov r0, %[context]\n\r"
+ "mov lr, %[return_func]\n\r"
+ "subs pc, lr, #0" ::
+ [context]"r" (regs),
+ [return_func]"r" (schedule_save_context) :
+ "memory");
+ }
+ else if (uart_irq_pending())
+ {
+ if (uart_recv_irq_pending())
+ {
+ uart_clear_recv_irq();
+ scheduler_try_input();
+ }
+ if (uart_send_irq_pending())
+ {
+ uart_clear_send_irq();
+ scheduler_try_output();
+ }
+
+ if (read_SPSR().fields.PSR_MODE_4_0 != MODE_USER)
+ {
+ write_SPSR(PL1_PSR);
+ asm volatile("mov lr, %0\n\r"
+ "subs pc, lr, #0" ::
+ "r" (schedule) : "memory");
+ }
+ }
+ else
+ error("unknown irq");
+
+ // important - don't allow this handler to return if irq came from
+ // PL1 (likely supervisor, because we don't really use system) mode
+}
+
+void fiq_handler(void)
+{
+ error("fiq happened");
+}
+
+
+/* Here is your interrupt function */
+//void
+//__attribute__((interrupt("IRQ")))
+//__attribute__((section(".interrupt_vectors.text")))
+//irq_handler2(void) {
+// /* You code goes here */
+//// uart_puts("GOT INTERRUPT!\r\n");
+//
+// local_timer_clr_reload_reg_t temp = { .IntClear = 1, .Reload = 1 };
+// QA7->TimerClearReload = temp; // Clear interrupt & reload
+//}
+
+///* here is your main */
+//int enable_timer(void) {
+//
+// QA7->TimerRouting.Routing = LOCALTIMER_TO_CORE0_IRQ; // Route local timer IRQ to Core0
+// QA7->TimerControlStatus.ReloadValue = 100; // Timer period set
+// QA7->TimerControlStatus.TimerEnable = 1; // Timer enabled
+// QA7->TimerControlStatus.IntEnable = 1; // Timer IRQ enabled
+// QA7->TimerClearReload.IntClear = 1; // Clear interrupt
+// QA7->TimerClearReload.Reload = 1; // Reload now
+// QA7->Core0TimerIntControl.nCNTPNSIRQ_IRQ = 1; // We are in NS EL1 so enable IRQ to core0 that level
+// QA7->Core0TimerIntControl.nCNTPNSIRQ_FIQ = 0; // Make sure FIQ is zero
+//// uart_puts("Enabled Timer\r\n");
+// return(0);
+//} \ No newline at end of file