diff options
author | vetch <vetch97@gmail.com> | 2020-01-04 11:26:57 +0100 |
---|---|---|
committer | vetch <vetch97@gmail.com> | 2020-01-04 11:26:57 +0100 |
commit | 885a097da42317f48cead2d91c0e0240066943a8 (patch) | |
tree | 0ee86dbaf5678b32f496b99c48ea81bbd20971f2 /interrupts.c | |
parent | 2d31012739a11724844701d07db12e6e1307925e (diff) | |
parent | 814d4a5357d849c4988422d48afa4aaa5432ce78 (diff) | |
download | rpi-MMU-example-885a097da42317f48cead2d91c0e0240066943a8.tar.gz rpi-MMU-example-885a097da42317f48cead2d91c0e0240066943a8.zip |
Merge branch 'bob' of https://repo.or.cz/RPi-MMU-example into alice
# Conflicts:
# demo_functionality.h
# interrupt_vector.S
# interrupts.c
Diffstat (limited to 'interrupts.c')
-rw-r--r-- | interrupts.c | 91 |
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"); } |