140 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			140 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include <stdint.h>
 | |
| #include <stdio.h>
 | |
| #include <unistd.h>
 | |
| 
 | |
| #include "platform.h"
 | |
| #include "encoding.h"
 | |
| 
 | |
| #if __riscv_xlen == 32
 | |
| #define MCAUSE_INT         0x80000000UL
 | |
| #define MCAUSE_CAUSE       0x000003FFUL
 | |
| #else
 | |
| #define MCAUSE_INT         0x8000000000000000UL
 | |
| #define MCAUSE_CAUSE       0x00000000000003FFUL
 | |
| #endif
 | |
| 
 | |
| extern int main(int argc, char** argv);
 | |
| extern void trap_entry();
 | |
| #define IRQ_M_SOFT   3
 | |
| #define IRQ_M_TIMER  7
 | |
| #define IRQ_M_EXT    11
 | |
| 
 | |
| #define NUM_INTERRUPTS 16
 | |
| #define MTIMER_NEXT_TICK_INC 1000
 | |
| 
 | |
| void handle_m_ext_interrupt(void);
 | |
| void handle_m_time_interrupt(void);
 | |
| uint32_t handle_trap(uint32_t mcause, uint32_t mepc, uint32_t sp);
 | |
| void default_handler(void);
 | |
| void _init(void);
 | |
| 
 | |
| typedef void (*my_interrupt_function_ptr_t) (void);
 | |
| my_interrupt_function_ptr_t localISR[NUM_INTERRUPTS] __attribute__((aligned(64)));
 | |
| 
 | |
| static unsigned long mtime_lo(void)
 | |
| {
 | |
|     unsigned long ret;
 | |
|     __asm volatile("rdtime %0":"=r"(ret));
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| #if __riscv_xlen==32
 | |
| 
 | |
| static uint32_t mtime_hi(void)
 | |
| {
 | |
|     unsigned long ret;
 | |
|     __asm volatile("rdtimeh %0":"=r"(ret));
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| uint64_t get_timer_value()
 | |
| {
 | |
|   while (1) {
 | |
|     uint32_t hi = mtime_hi();
 | |
|     uint32_t lo = mtime_lo();
 | |
|     if (hi == mtime_hi())
 | |
|       return ((uint64_t)hi << 32) | lo;
 | |
|   }
 | |
| }
 | |
| 
 | |
| #elif __riscv_xlen==64
 | |
| 
 | |
| uint64_t get_timer_value()
 | |
| {
 | |
|   return mtime_lo();
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| unsigned long get_timer_freq()
 | |
| {
 | |
|   return 32768;
 | |
| }
 | |
| 
 | |
| unsigned long get_cpu_freq()
 | |
| {
 | |
|   return 100000000;
 | |
| }
 | |
| 
 | |
| void init_pll(void){
 | |
|     //TODO: implement initialization
 | |
| }
 | |
| 
 | |
| static void uart_init(size_t baud_rate)
 | |
| {
 | |
|   //TODO: implement initialization
 | |
| }
 | |
| 
 | |
| void __attribute__((weak)) handle_m_ext_interrupt(){
 | |
| }
 | |
| 
 | |
| void __attribute__((weak)) handle_m_time_interrupt(){
 | |
|     uint64_t time = ((uint64_t)mtimer->mtimeh)<<32 || mtimer->mtime;
 | |
|     time+=MTIMER_NEXT_TICK_INC;
 | |
|     mtimer->mtimecmph = time>>32;
 | |
|     mtimer->mtimecmp = time;
 | |
| }
 | |
| 
 | |
| void __attribute__((weak)) default_handler(void) {
 | |
|   puts("default handler\n");
 | |
| }
 | |
| 
 | |
| uint32_t handle_trap(uint32_t mcause, uint32_t mepc, uint32_t sp){
 | |
|   if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)) {
 | |
|     handle_m_ext_interrupt();
 | |
|     // External Machine-Level interrupt from PLIC
 | |
|   } else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)){
 | |
|     handle_m_time_interrupt();
 | |
|   } else {
 | |
|     write(1, "trap\n", 5);
 | |
|     _exit(1 + mcause);
 | |
|   }
 | |
|   return mepc;
 | |
| }
 | |
| 
 | |
| void _init()
 | |
| {
 | |
|   
 | |
| #ifndef NO_INIT
 | |
|   init_pll();
 | |
|   uart_init(115200);
 | |
|   printf("core freq at %d Hz\n", get_cpu_freq());
 | |
|   write_csr(mtvec, &trap_entry);
 | |
|   if (read_csr(misa) & (1 << ('F' - 'A'))) { // if F extension is present
 | |
|     write_csr(mstatus, MSTATUS_FS); // allow FPU instructions without trapping
 | |
|     write_csr(fcsr, 0); // initialize rounding mode, undefined at reset
 | |
|   }
 | |
|   int i=0;
 | |
|   while(i<NUM_INTERRUPTS)  {
 | |
|     localISR[i++] = default_handler;
 | |
|   }
 | |
| 
 | |
| #endif
 | |
|   
 | |
| }
 | |
| 
 | |
| void _fini()
 | |
| {
 | |
| }
 |