From ffb2c4adfb8e65e355b39abd39d994eebc649c98 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Fri, 3 Jan 2020 04:53:01 +0100 Subject: add (not yet fully working - it can only send through uart now) interrupt-driven uart together with "scheduler" --- interrupts.c | 93 ++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 63 insertions(+), 30 deletions(-) (limited to 'interrupts.c') 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("<>"); - 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"); } -- cgit v1.2.3