diff options
author | vetch <vetch97@gmail.com> | 2020-01-13 12:40:38 +0100 |
---|---|---|
committer | vetch <vetch97@gmail.com> | 2020-01-13 12:40:38 +0100 |
commit | 1af7591e37d09ddcd734ea07d0e999cf61c8bc5e (patch) | |
tree | a56c73c9eddeb148baffc3a31bf50edbbeb31074 /src/arm/PL1/kernel/interrupts.c | |
parent | 300cf770698142b636da867b7e04bf2d6ae9baa4 (diff) | |
download | rpi-MMU-example-1af7591e37d09ddcd734ea07d0e999cf61c8bc5e.tar.gz rpi-MMU-example-1af7591e37d09ddcd734ea07d0e999cf61c8bc5e.zip |
Great Reorganisation, modify structure and makefile
Diffstat (limited to 'src/arm/PL1/kernel/interrupts.c')
-rw-r--r-- | src/arm/PL1/kernel/interrupts.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/src/arm/PL1/kernel/interrupts.c b/src/arm/PL1/kernel/interrupts.c new file mode 100644 index 0000000..121d79c --- /dev/null +++ b/src/arm/PL1/kernel/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 |