aboutsummaryrefslogtreecommitdiff
path: root/interrupts.c
diff options
context:
space:
mode:
Diffstat (limited to 'interrupts.c')
-rw-r--r--interrupts.c91
1 files changed, 56 insertions, 35 deletions
diff --git a/interrupts.c b/interrupts.c
index ff26eba..51cab25 100644
--- a/interrupts.c
+++ b/interrupts.c
@@ -1,11 +1,13 @@
-#include "uart.h"
-#include "interrupts.h"
#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;
@@ -18,30 +20,31 @@ void reset_handler(void)
void undefined_instruction_vector(void)
{
- puts("Undefined instruction occured");
- while( 1 )
- {
- /* Do Nothing! */
- }
+ error("Undefined instruction occured");
}
-uint32_t supervisor_call_handler(enum svc_type request, uint32_t arg1,
- uint32_t arg2, uint32_t arg3)
+uint32_t supervisor_call_handler(uint32_t regs[14])
{
- (void) arg2; (void) arg3; // unused for now
-
- switch(request) {
+ switch(regs[0]) {
case UART_PUTCHAR:
- putchar(arg1);
+ if (putchar_non_blocking(regs[1]))
+ schedule_wait_for_output(regs, regs[1]);
break;
case UART_GETCHAR:
- return getchar();
+ {
+ int c;
+ if ((c = getchar_non_blocking()) == -1)
+ schedule_wait_for_input(regs);
+
+ regs[0] = c;
+ break;
+ }
case UART_WRITE:
- puts("UART_WRITE not implemented!!!!!");
+ error("UART_WRITE not implemented!!!!!");
break;
default:
// perhaps we should kill the process now?
- puts("unknown supervisor call type!!!!!");
+ error("unknown supervisor call type!!!!!");
}
return 0; // a dummy value
@@ -49,40 +52,58 @@ uint32_t supervisor_call_handler(enum svc_type request, uint32_t arg1,
void abort_handler(void)
{
- puts("re-entered system");
-
- while(1);
+ // TODO maybe dump registers here?
+ error("re-entered system due to data/prefetch abort");
}
void generic_handler(void)
{
- puts("something weird happened");
-
- while(1);
+ error("something weird happened");
}
-void irq_handler(void)
+void irq_handler(uint32_t regs[14])
{
-// uart_puts("nwm\r\n");
-
-// system_reentry_point();
if (armclk_irq_pending())
{
- puts("<<irq from timer>>");
- armclk_irq_settimeout(0x00100000);
+ 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
+ else if (uart_irq_pending())
{
- puts("unknown irq");
- while(1);
+ 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)
{
- puts("fiq happened");
-
- while(1);
+ error("fiq happened");
}