// 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<