/* Baremetal main program with timer interrupt. SPDX-License-Identifier: Unlicense https://five-embeddev.com/ Tested with sifive-hifive-revb, but should not have any dependencies to any particular implementation. */ // RISC-V CSR definitions and access classes #include "riscv-csr.h" #include "riscv-interrupt.h" #include "hwtimer.h" #include "vector_table.h" extern void _tx_timer_interrupt(void); // Machine mode interrupt service routine // Global to hold current timestamp, written in MTI handler. static volatile uint64_t timestamp = 0; #define RISCV_MTVEC_MODE_VECTORED 1 int init_irq(void) { // Global interrupt disable csr_clr_bits_mstatus(MSTATUS_MIE_BIT_MASK); csr_write_mie(0); // Setup the IRQ handler entry point, set the mode to vectored csr_write_mtvec((uint_xlen_t) riscv_mtvec_table | RISCV_MTVEC_MODE_VECTORED); // Enable MIE.MTI csr_set_bits_mie(MIE_MTI_BIT_MASK); // Global interrupt enable csr_set_bits_mstatus(MSTATUS_MIE_BIT_MASK); // Setup timer for 1 second interval hwtimer_init(); // Busy loop do { // Wait for timer interrupt __asm__ volatile ("wfi"); // Try a synchronous exception. __asm__ volatile ("ecall"); } while (1); // Will not reach here return 0; } #pragma GCC push_options // Force the alignment for mtvec.BASE. A 'C' extension program could be aligned to to bytes. #pragma GCC optimize ("align-functions=4") // The 'riscv_mtvec_mti' function is added to the vector table by the vector_table.c void riscv_mtvec_mti(void) { hwtimer_handler(); _tx_timer_interrupt(); } // The 'riscv_mtvec_exception' function is added to the vector table by the vector_table.c // This function looks at the cause of the exception, if it is an 'ecall' instruction then increment a global counter. void riscv_mtvec_exception(void) { uint_xlen_t this_cause = csr_read_mcause(); uint_xlen_t this_pc = csr_read_mepc(); //uint_xlen_t this_value = csr_read_mtval(); switch (this_cause) { case RISCV_EXCP_ENVIRONMENT_CALL_FROM_M_MODE: ecall_count++; // Make sure the return address is the instruction AFTER ecall csr_write_mepc(this_pc+4); break; } } #pragma GCC pop_options