From e008ed03839d46388f184206d634021fd083dc78 Mon Sep 17 00:00:00 2001 From: Drew Barbier Date: Wed, 26 Jul 2017 14:55:16 -0500 Subject: only save/restore "caller" registers on trap entry --- .../vectored_interrupts/vectored_interrupts.c | 216 +++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 FreedomStudio/E31FPGA/vectored_interrupts/vectored_interrupts.c (limited to 'FreedomStudio/E31FPGA/vectored_interrupts') diff --git a/FreedomStudio/E31FPGA/vectored_interrupts/vectored_interrupts.c b/FreedomStudio/E31FPGA/vectored_interrupts/vectored_interrupts.c new file mode 100644 index 0000000..8958105 --- /dev/null +++ b/FreedomStudio/E31FPGA/vectored_interrupts/vectored_interrupts.c @@ -0,0 +1,216 @@ +// See LICENSE for license details. + +#include +#include +#include "platform.h" +#include +#include "plic/plic_driver.h" +#include "encoding.h" +#include + +#ifndef _SIFIVE_COREPLEXIP_ARTY_H +#error 'global_interrupts' demo only supported for Coreplex IP Eval Kits +#endif + +// Global Instance data for the PLIC +// for use by the PLIC Driver. +plic_instance_t g_plic; + +// Structures for registering different interrupt handlers +// for different parts of the application. +typedef void (*interrupt_function_ptr_t) (void); +//array of function pointers which contains the PLIC +//interrupt handlers +interrupt_function_ptr_t g_ext_interrupt_handlers[PLIC_NUM_INTERRUPTS]; + +const char * instructions_msg = " \ +\n\ + SIFIVE, INC.\n\ +E31/E51 Coreplex IP Eval Kit 'vectored_interrupts' demo. \n\ +\n\ +This demo demonstrates Vectored Interrupts capabilities of\n\ +the E31/E51 Coreplex. The vector table is defined in \n\ +bsp/env/ventry.S \n\ +Button 0 is a global external interrupt routed to the PLIC.\n\ +Button 1 is a local interrupt.\n\ +\n"; + +void print_instructions() { + + write (STDOUT_FILENO, instructions_msg, strlen(instructions_msg)); + +} + +void set_timer() { + + volatile uint64_t * mtime = (uint64_t*) (CLINT_CTRL_ADDR + CLINT_MTIME); + volatile uint64_t * mtimecmp = (uint64_t*) (CLINT_CTRL_ADDR + CLINT_MTIMECMP); + uint64_t now = *mtime; + uint64_t then = now + 1*RTC_FREQ; + *mtimecmp = then; + + set_csr(mie, MIP_MTIP); +} + +/*Entry Point for Machine Timer Interrupt Handler*/ +/*called from bsp/env/ventry.s */ +void handle_m_time_interrupt(){ + static uint32_t onoff=1; + + clear_csr(mie, MIP_MTIP); + + // Set Green LED + if(onoff) { + GPIO_REG(GPIO_OUTPUT_VAL) |= (0x1 << GREEN_LED_OFFSET) ; + onoff=0; + }else { + GPIO_REG(GPIO_OUTPUT_VAL) &= ~((0x1 << GREEN_LED_OFFSET)) ; + onoff=1; + } + set_timer(); + + //re-enable button1 irq + set_csr(mie, MIP_MLIP(LOCAL_INT_BTN_1)); + +} + +/*Synchronous Trap Handler*/ +/*called from bsp/env/ventry.s */ +void handle_sync_trap(uintptr_t mcause, uintptr_t epc ) { + write(1, "vUnhandled Trap:\n", 16); + _exit(1 + mcause); +} + +/*Entry Point for PLIC Interrupt Handler*/ +/*called from bsp/env/ventry.s */ +void handle_m_external_interrupt(){ + printf("In PLIC handler\n"); + plic_source int_num = PLIC_claim_interrupt(&g_plic); + if ((int_num >=1 ) && (int_num < PLIC_NUM_INTERRUPTS)) { + g_ext_interrupt_handlers[int_num](); + } + else { + exit(1 + (uintptr_t) int_num); + } + PLIC_complete_interrupt(&g_plic, int_num); +} + +//default empty PLIC handler +void invalid_global_isr() { + printf("Unexpected global interrupt!\n"); +} + +/* b0 global interrupt isr */ +/*called from handle_m_external_interrupt */ +void button_0_handler() { + static uint32_t onoff=1; + // Set Green LED + + printf("In Button 0 handler\n"); + + if(onoff) { + GPIO_REG(GPIO_OUTPUT_VAL) |= (0x1 << BLUE_LED_OFFSET) ; + onoff=0; + }else { + GPIO_REG(GPIO_OUTPUT_VAL) &= ~((0x1 << BLUE_LED_OFFSET)) ; + onoff=1; + } + + //clear irq - interrupt pending register is write 1 to clear + GPIO_REG(GPIO_FALL_IP) |= (1<