aboutsummaryrefslogtreecommitdiff
path: root/interrupts.c
diff options
context:
space:
mode:
authorWojtek Kosior <kwojtus@protonmail.com>2020-01-03 04:53:01 +0100
committerWojtek Kosior <kwojtus@protonmail.com>2020-01-03 04:53:01 +0100
commitffb2c4adfb8e65e355b39abd39d994eebc649c98 (patch)
tree760ef43f89b480ecd0be4bfd9312eb0d8c744d05 /interrupts.c
parent6bf5a3b8c6e8a5d1cb3fb4880a5d9688ab094c62 (diff)
downloadrpi-MMU-example-ffb2c4adfb8e65e355b39abd39d994eebc649c98.tar.gz
rpi-MMU-example-ffb2c4adfb8e65e355b39abd39d994eebc649c98.zip
add (not yet fully working - it can only send through uart now) interrupt-driven uart together with "scheduler"
Diffstat (limited to 'interrupts.c')
-rw-r--r--interrupts.c93
1 files changed, 63 insertions, 30 deletions
diff --git a/interrupts.c b/interrupts.c
index f4192a0..9beee0a 100644
--- a/interrupts.c
+++ b/interrupts.c
@@ -1,6 +1,8 @@
#include "io.h"
+#include "uart.h"
#include "svc_interface.h"
#include "armclock.h"
+#include "scheduler.h"
void __attribute__((noreturn)) setup(void);
@@ -14,30 +16,40 @@ 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)
+_Bool flag = 0;
+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;
+ case 17:
+ {
+ flag = 1;
+ /* while (1) */
+ /* { */
+ /* printbin(*(uint32_t volatile*) PL011_UART_MIS); puts(""); */
+ /* } */
+ break;
+ }
default:
// perhaps we should kill the process now?
- puts("unknown supervisor call type!!!!!");
+ error("unknown supervisor call type!!!!!");
}
return 0; // a dummy value
@@ -45,36 +57,57 @@ 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])
{
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");
}