]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/riscv_cpu.c
Update RISCC-V-RV32-SiFive_HiFive1_FreedomStudio project to latest tools and metal...
[freertos] / FreeRTOS / Demo / RISC-V_RV32_SiFive_HiFive1_FreedomStudio / freedom-metal / src / drivers / riscv_cpu.c
index 88175eb18ffae87aa4bd5c59cce4cbebf3afeafc..b693f312a9ace767e0994d4ac6260a6a7e720eab 100644 (file)
@@ -6,6 +6,7 @@
 #include <metal/shutdown.h>
 #include <metal/machine.h>
 
+extern void __metal_vector_table();
 unsigned long long __metal_driver_cpu_mtime_get(struct metal_cpu *cpu);
 int __metal_driver_cpu_mtimecmp_set(struct metal_cpu *cpu, unsigned long long time);
 
@@ -20,7 +21,7 @@ struct metal_cpu *__metal_driver_cpu_get(int hartid)
 uintptr_t __metal_myhart_id (void)
 {
     uintptr_t myhart;
-    asm volatile ("csrr %0, mhartid" : "=r"(myhart));
+    __asm__ volatile ("csrr %0, mhartid" : "=r"(myhart));
     return myhart;
 }
 
@@ -34,54 +35,54 @@ void __metal_zero_memory (unsigned char *base, unsigned int size)
 
 void __metal_interrupt_global_enable (void) {
     uintptr_t m;
-    asm volatile ("csrrs %0, mstatus, %1" : "=r"(m) : "r"(METAL_MIE_INTERRUPT));
+    __asm__ volatile ("csrrs %0, mstatus, %1" : "=r"(m) : "r"(METAL_MIE_INTERRUPT));
 }
 
 void __metal_interrupt_global_disable (void) {
     uintptr_t m;
-    asm volatile ("csrrc %0, mstatus, %1" : "=r"(m) : "r"(METAL_MIE_INTERRUPT));
+    __asm__ volatile ("csrrc %0, mstatus, %1" : "=r"(m) : "r"(METAL_MIE_INTERRUPT));
 }
 
 void __metal_interrupt_software_enable (void) {
     uintptr_t m;
-    asm volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_SW));
+    __asm__ volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_SW));
 }
 
 void __metal_interrupt_software_disable (void) {
     uintptr_t m;
-    asm volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_SW));
+    __asm__ volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_SW));
 }
 
 void __metal_interrupt_timer_enable (void) {
     uintptr_t m;
-    asm volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_TMR));
+    __asm__ volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_TMR));
 }
 
 void __metal_interrupt_timer_disable (void) {
     uintptr_t m;
-    asm volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_TMR));
+    __asm__ volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_TMR));
 }
 
 void __metal_interrupt_external_enable (void) {
     uintptr_t m;
-    asm volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_EXT));
+    __asm__ volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_EXT));
 }
 
 void __metal_interrupt_external_disable (void) {
     unsigned long m;
-    asm volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_EXT));
+    __asm__ volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_EXT));
 }
 
 void __metal_interrupt_local_enable (int id) {
     uintptr_t b = 1 << id;
     uintptr_t m;
-    asm volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(b));
+    __asm__ volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(b));
 }
 
 void __metal_interrupt_local_disable (int id) {
     uintptr_t b = 1 << id;
     uintptr_t m;
-    asm volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(b));
+    __asm__ volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(b));
 }
 
 void __metal_default_exception_handler (struct metal_cpu *cpu, int ecode) {
@@ -92,12 +93,31 @@ void __metal_default_interrupt_handler (int id, void *priv) {
     metal_shutdown(200);
 }
 
+/* The metal_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_interrupt_vector_handler (void) {
+    metal_shutdown(300);
+}
+
+/* The metal_software_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_software_interrupt_vector_handler (void) {
+    void *priv;
+    struct __metal_driver_riscv_cpu_intc *intc;
+    struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+    if ( cpu ) {
+        intc = (struct __metal_driver_riscv_cpu_intc *)
+          __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+        priv = intc->metal_int_table[METAL_INTERRUPT_ID_SW].exint_data;
+        intc->metal_int_table[METAL_INTERRUPT_ID_SW].handler(METAL_INTERRUPT_ID_SW, priv);
+    }
+}
+
 void __metal_default_sw_handler (int id, void *priv) {
     uintptr_t mcause;
     struct __metal_driver_riscv_cpu_intc *intc;
     struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
 
-    asm volatile ("csrr %0, mcause" : "=r"(mcause));
+    __asm__ volatile ("csrr %0, mcause" : "=r"(mcause));
     if ( cpu ) {
         intc = (struct __metal_driver_riscv_cpu_intc *)
          __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
@@ -105,6 +125,20 @@ void __metal_default_sw_handler (int id, void *priv) {
     }
 }
 
+/* The metal_timer_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_timer_interrupt_vector_handler (void) {
+    void *priv;
+    struct __metal_driver_riscv_cpu_intc *intc;
+    struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+    if ( cpu ) {
+        intc = (struct __metal_driver_riscv_cpu_intc *)
+          __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+        priv = intc->metal_int_table[METAL_INTERRUPT_ID_TMR].exint_data;
+        intc->metal_int_table[METAL_INTERRUPT_ID_TMR].handler(METAL_INTERRUPT_ID_TMR, priv);
+    }
+}
+
 void __metal_default_timer_handler (int id, void *priv) {
     struct metal_cpu *cpu = __metal_driver_cpu_get(__metal_myhart_id());
     unsigned long long time = __metal_driver_cpu_mtime_get(cpu);
@@ -113,6 +147,20 @@ void __metal_default_timer_handler (int id, void *priv) {
     __metal_driver_cpu_mtimecmp_set(cpu, time + 10);
 }
 
+/* The metal_external_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_external_interrupt_vector_handler (void) {
+    void *priv;
+    struct __metal_driver_riscv_cpu_intc *intc;
+    struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+    if ( cpu ) {
+        intc = (struct __metal_driver_riscv_cpu_intc *)
+          __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+        priv = intc->metal_int_table[METAL_INTERRUPT_ID_EXT].exint_data;
+        intc->metal_int_table[METAL_INTERRUPT_ID_EXT].handler(METAL_INTERRUPT_ID_EXT, priv);
+    }
+}
+
 void __metal_exception_handler(void) __attribute__((interrupt, aligned(128)));
 void __metal_exception_handler (void) {
     int id;
@@ -121,17 +169,17 @@ void __metal_exception_handler (void) {
     struct __metal_driver_riscv_cpu_intc *intc;
     struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
 
-    asm volatile ("csrr %0, mcause" : "=r"(mcause));
-    asm volatile ("csrr %0, mepc" : "=r"(mepc));
-    asm volatile ("csrr %0, mtval" : "=r"(mtval));
-    asm volatile ("csrr %0, mtvec" : "=r"(mtvec));
+    __asm__ volatile ("csrr %0, mcause" : "=r"(mcause));
+    __asm__ volatile ("csrr %0, mepc" : "=r"(mepc));
+    __asm__ volatile ("csrr %0, mtval" : "=r"(mtval));
+    __asm__ volatile ("csrr %0, mtvec" : "=r"(mtvec));
 
     if ( cpu ) {
         intc = (struct __metal_driver_riscv_cpu_intc *)
          __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
         id = mcause & METAL_MCAUSE_CAUSE;
         if (mcause & METAL_MCAUSE_INTR) {
-            if ((id < METAL_INTERRUPT_ID_LC0) ||
+            if ((id < METAL_INTERRUPT_ID_CSW) ||
                ((mtvec & METAL_MTVEC_MASK) == METAL_MTVEC_DIRECT)) {
                 priv = intc->metal_int_table[id].exint_data;
                 intc->metal_int_table[id].handler(id, priv);
@@ -141,9 +189,9 @@ void __metal_exception_handler (void) {
                uintptr_t mtvt;
                metal_interrupt_handler_t mtvt_handler;
 
-                asm volatile ("csrr %0, mtvt" : "=r"(mtvt));
+                __asm__ volatile ("csrr %0, 0x307" : "=r"(mtvt));
                        priv = intc->metal_int_table[METAL_INTERRUPT_ID_SW].sub_int;
-                       mtvt_handler = (metal_interrupt_handler_t)mtvt;
+                       mtvt_handler = (metal_interrupt_handler_t)*(uintptr_t *)mtvt;
                        mtvt_handler(id, priv);
                return;
             }
@@ -153,28 +201,271 @@ void __metal_exception_handler (void) {
     }
 }
 
+/* The metal_lc0_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc0_interrupt_vector_handler (void) {
+    void *priv;
+    struct __metal_driver_riscv_cpu_intc *intc;
+    struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+    if ( cpu ) {
+        intc = (struct __metal_driver_riscv_cpu_intc *)
+          __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+        priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC0].exint_data;
+        intc->metal_int_table[METAL_INTERRUPT_ID_LC0].handler(METAL_INTERRUPT_ID_LC0, priv);
+    }
+}
+
+/* The metal_lc1_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc1_interrupt_vector_handler (void) {
+    void *priv;
+    struct __metal_driver_riscv_cpu_intc *intc;
+    struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+    if ( cpu ) {
+        intc = (struct __metal_driver_riscv_cpu_intc *)
+          __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+        priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC1].exint_data;
+        intc->metal_int_table[METAL_INTERRUPT_ID_LC1].handler(METAL_INTERRUPT_ID_LC1, priv);
+    }
+}
+
+/* The metal_lc2_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc2_interrupt_vector_handler (void) {
+    void *priv;
+    struct __metal_driver_riscv_cpu_intc *intc;
+    struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+    if ( cpu ) {
+        intc = (struct __metal_driver_riscv_cpu_intc *)
+          __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+        priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC2].exint_data;
+        intc->metal_int_table[METAL_INTERRUPT_ID_LC2].handler(METAL_INTERRUPT_ID_LC2, priv);
+    }
+}
+
+/* The metal_lc3_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc3_interrupt_vector_handler (void) {
+    void *priv;
+    struct __metal_driver_riscv_cpu_intc *intc;
+    struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+    if ( cpu ) {
+        intc = (struct __metal_driver_riscv_cpu_intc *)
+          __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+        priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC3].exint_data;
+        intc->metal_int_table[METAL_INTERRUPT_ID_LC3].handler(METAL_INTERRUPT_ID_LC3, priv);
+    }
+}
+
+/* The metal_lc4_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc4_interrupt_vector_handler (void) {
+    void *priv;
+    struct __metal_driver_riscv_cpu_intc *intc;
+    struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+    if ( cpu ) {
+        intc = (struct __metal_driver_riscv_cpu_intc *)
+          __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+        priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC4].exint_data;
+        intc->metal_int_table[METAL_INTERRUPT_ID_LC4].handler(METAL_INTERRUPT_ID_LC4, priv);
+    }
+}
+
+/* The metal_lc5_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc5_interrupt_vector_handler (void) {
+    void *priv;
+    struct __metal_driver_riscv_cpu_intc *intc;
+    struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+    if ( cpu ) {
+        intc = (struct __metal_driver_riscv_cpu_intc *)
+          __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+        priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC5].exint_data;
+        intc->metal_int_table[METAL_INTERRUPT_ID_LC5].handler(METAL_INTERRUPT_ID_LC5, priv);
+    }
+}
+
+/* The metal_lc6_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc6_interrupt_vector_handler (void) {
+    void *priv;
+    struct __metal_driver_riscv_cpu_intc *intc;
+    struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+    if ( cpu ) {
+        intc = (struct __metal_driver_riscv_cpu_intc *)
+          __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+        priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC6].exint_data;
+        intc->metal_int_table[METAL_INTERRUPT_ID_LC6].handler(METAL_INTERRUPT_ID_LC6, priv);
+    }
+}
+
+/* The metal_lc7_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc7_interrupt_vector_handler (void) {
+    void *priv;
+    struct __metal_driver_riscv_cpu_intc *intc;
+    struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+    if ( cpu ) {
+        intc = (struct __metal_driver_riscv_cpu_intc *)
+          __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+        priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC7].exint_data;
+        intc->metal_int_table[METAL_INTERRUPT_ID_LC7].handler(METAL_INTERRUPT_ID_LC7, priv);
+    }
+}
+
+/* The metal_lc8_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc8_interrupt_vector_handler (void) {
+    void *priv;
+    struct __metal_driver_riscv_cpu_intc *intc;
+    struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+    if ( cpu ) {
+        intc = (struct __metal_driver_riscv_cpu_intc *)
+          __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+        priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC8].exint_data;
+        intc->metal_int_table[METAL_INTERRUPT_ID_LC8].handler(METAL_INTERRUPT_ID_LC8, priv);
+    }
+}
+
+/* The metal_lc9_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc9_interrupt_vector_handler (void) {
+    void *priv;
+    struct __metal_driver_riscv_cpu_intc *intc;
+    struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+    if ( cpu ) {
+        intc = (struct __metal_driver_riscv_cpu_intc *)
+          __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+        priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC9].exint_data;
+        intc->metal_int_table[METAL_INTERRUPT_ID_LC9].handler(METAL_INTERRUPT_ID_LC9, priv);
+    }
+}
+
+/* The metal_lc10_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc10_interrupt_vector_handler (void) {
+    void *priv;
+    struct __metal_driver_riscv_cpu_intc *intc;
+    struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+    if ( cpu ) {
+        intc = (struct __metal_driver_riscv_cpu_intc *)
+          __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+        priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC10].exint_data;
+        intc->metal_int_table[METAL_INTERRUPT_ID_LC10].handler(METAL_INTERRUPT_ID_LC10, priv);
+    }
+}
+
+/* The metal_lc11_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc11_interrupt_vector_handler (void) {
+    void *priv;
+    struct __metal_driver_riscv_cpu_intc *intc;
+    struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+    if ( cpu ) {
+        intc = (struct __metal_driver_riscv_cpu_intc *)
+          __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+        priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC11].exint_data;
+        intc->metal_int_table[METAL_INTERRUPT_ID_LC11].handler(METAL_INTERRUPT_ID_LC11, priv);
+    }
+}
+
+/* The metal_lc12_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc12_interrupt_vector_handler (void) {
+    void *priv;
+    struct __metal_driver_riscv_cpu_intc *intc;
+    struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+    if ( cpu ) {
+        intc = (struct __metal_driver_riscv_cpu_intc *)
+          __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+        priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC12].exint_data;
+        intc->metal_int_table[METAL_INTERRUPT_ID_LC12].handler(METAL_INTERRUPT_ID_LC12, priv);
+    }
+}
+
+/* The metal_lc13_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc13_interrupt_vector_handler (void) {
+    void *priv;
+    struct __metal_driver_riscv_cpu_intc *intc;
+    struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+    if ( cpu ) {
+        intc = (struct __metal_driver_riscv_cpu_intc *)
+          __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+        priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC13].exint_data;
+        intc->metal_int_table[METAL_INTERRUPT_ID_LC13].handler(METAL_INTERRUPT_ID_LC13, priv);
+    }
+}
+
+/* The metal_lc14_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc14_interrupt_vector_handler (void) {
+    void *priv;
+    struct __metal_driver_riscv_cpu_intc *intc;
+    struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+    if ( cpu ) {
+        intc = (struct __metal_driver_riscv_cpu_intc *)
+          __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+        priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC14].exint_data;
+        intc->metal_int_table[METAL_INTERRUPT_ID_LC14].handler(METAL_INTERRUPT_ID_LC14, priv);
+    }
+}
+
+/* The metal_lc15_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc15_interrupt_vector_handler (void) {
+    void *priv;
+    struct __metal_driver_riscv_cpu_intc *intc;
+    struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+    if ( cpu ) {
+        intc = (struct __metal_driver_riscv_cpu_intc *)
+          __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+        priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC15].exint_data;
+        intc->metal_int_table[METAL_INTERRUPT_ID_LC15].handler(METAL_INTERRUPT_ID_LC15, priv);
+    }
+}
+
+metal_vector_mode __metal_controller_interrupt_vector_mode (void)
+{
+    uintptr_t val;
+
+    asm volatile ("csrr %0, mtvec" : "=r"(val));
+    val &= METAL_MTVEC_MASK;
+
+    switch (val) {
+    case METAL_MTVEC_CLIC:
+        return METAL_SELECTIVE_VECTOR_MODE;
+    case METAL_MTVEC_CLIC_VECTORED:
+        return METAL_HARDWARE_VECTOR_MODE;
+    case METAL_MTVEC_VECTORED:
+        return METAL_VECTOR_MODE;
+    }
+    return METAL_DIRECT_MODE;
+}
+
 void __metal_controller_interrupt_vector (metal_vector_mode mode, void *vec_table)
 {  
     uintptr_t trap_entry, val;
 
-    asm volatile ("csrr %0, mtvec" : "=r"(val));
+    __asm__ volatile ("csrr %0, mtvec" : "=r"(val));
     val &= ~(METAL_MTVEC_CLIC_VECTORED | METAL_MTVEC_CLIC_RESERVED);
     trap_entry = (uintptr_t)vec_table;
 
     switch (mode) {
+    case METAL_SELECTIVE_NONVECTOR_MODE:
     case METAL_SELECTIVE_VECTOR_MODE:
-        asm volatile ("csrw mtvt, %0" :: "r"(trap_entry | METAL_MTVEC_CLIC));
-        asm volatile ("csrw mtvec, %0" :: "r"(val | METAL_MTVEC_CLIC));
+        __asm__ volatile ("csrw 0x307, %0" :: "r"(trap_entry));
+        __asm__ volatile ("csrw mtvec, %0" :: "r"(val | METAL_MTVEC_CLIC));
         break;
     case METAL_HARDWARE_VECTOR_MODE:
-        asm volatile ("csrw mtvt, %0" :: "r"(trap_entry | METAL_MTVEC_CLIC_VECTORED));
-        asm volatile ("csrw mtvec, %0" :: "r"(val | METAL_MTVEC_CLIC_VECTORED));
+        __asm__ volatile ("csrw 0x307, %0" :: "r"(trap_entry));
+        __asm__ volatile ("csrw mtvec, %0" :: "r"(val | METAL_MTVEC_CLIC_VECTORED));
         break;
     case METAL_VECTOR_MODE:
-        asm volatile ("csrw mtvec, %0" :: "r"(trap_entry | METAL_MTVEC_VECTORED));
+        __asm__ volatile ("csrw mtvec, %0" :: "r"(trap_entry | METAL_MTVEC_VECTORED));
         break;
     case METAL_DIRECT_MODE:
-        asm volatile ("csrw mtvec, %0" :: "r"(trap_entry & ~METAL_MTVEC_CLIC_VECTORED));
+        __asm__ volatile ("csrw mtvec, %0" :: "r"(trap_entry & ~METAL_MTVEC_CLIC_VECTORED));
         break;
     }
 }
@@ -270,7 +561,7 @@ int __metal_local_interrupt_enable (struct metal_interrupt *controller,
             __metal_interrupt_local_disable(id);
         }
         break;
-    defaut:
+    default:
         rc = -1;
     }
     return rc;
@@ -295,25 +586,25 @@ void __metal_driver_riscv_cpu_controller_interrupt_init (struct metal_interrupt
 
     if ( !intc->init_done ) {
         /* Disable and clear all interrupt sources */
-        asm volatile ("csrc mie, %0" :: "r"(-1));
-        asm volatile ("csrc mip, %0" :: "r"(-1));
+        __asm__ volatile ("csrc mie, %0" :: "r"(-1));
+        __asm__ volatile ("csrc mip, %0" :: "r"(-1));
 
         /* Read the misa CSR to determine if the delegation registers exist */
         uintptr_t misa;
-        asm volatile ("csrr %0, misa" : "=r" (misa));
+        __asm__ volatile ("csrr %0, misa" : "=r" (misa));
 
         /* The delegation CSRs exist if user mode interrupts (N extension) or
          * supervisor mode (S extension) are supported */
         if((misa & METAL_ISA_N_EXTENSIONS) || (misa & METAL_ISA_S_EXTENSIONS)) {
             /* Disable interrupt and exception delegation */
-            asm volatile ("csrc mideleg, %0" :: "r"(-1));
-            asm volatile ("csrc medeleg, %0" :: "r"(-1));
+            __asm__ volatile ("csrc mideleg, %0" :: "r"(-1));
+            __asm__ volatile ("csrc medeleg, %0" :: "r"(-1));
         }
 
         /* The satp CSR exists if supervisor mode (S extension) is supported */
         if(misa & METAL_ISA_S_EXTENSIONS) {
             /* Clear the entire CSR to make sure that satp.MODE = 0 */
-            asm volatile ("csrc satp, %0" :: "r"(-1));
+            __asm__ volatile ("csrc satp, %0" :: "r"(-1));
         }
 
         /* Default to use direct interrupt, setup sw cb table*/
@@ -325,12 +616,12 @@ void __metal_driver_riscv_cpu_controller_interrupt_init (struct metal_interrupt
        for (int i = 0; i < METAL_MAX_ME; i++) {
            intc->metal_exception_table[i] = __metal_default_exception_handler;
        }
-        __metal_controller_interrupt_vector(METAL_DIRECT_MODE, &__metal_exception_handler);
-       asm volatile ("csrr %0, misa" : "=r"(val));
+        __metal_controller_interrupt_vector(METAL_DIRECT_MODE, (void *)(uintptr_t)&__metal_exception_handler);
+       __asm__ volatile ("csrr %0, misa" : "=r"(val));
        if (val & (METAL_ISA_D_EXTENSIONS | METAL_ISA_F_EXTENSIONS | METAL_ISA_Q_EXTENSIONS)) {
            /* Floating point architecture, so turn on FP register saving*/
-           asm volatile ("csrr %0, mstatus" : "=r"(val));
-           asm volatile ("csrw mstatus, %0" :: "r"(val | METAL_MSTATUS_FS_INIT));
+           __asm__ volatile ("csrr %0, mstatus" : "=r"(val));
+           __asm__ volatile ("csrw mstatus, %0" :: "r"(val | METAL_MSTATUS_FS_INIT));
        }
        intc->init_done = 1;
     }
@@ -380,7 +671,7 @@ int __metal_driver_riscv_cpu_controller_interrupt_register(struct metal_interrup
             intc->metal_int_table[id].handler = __metal_default_interrupt_handler;
             intc->metal_int_table[id].sub_int = priv;
          break;
-       defaut:
+       default:
          rc = -12;
        }
     }
@@ -406,11 +697,11 @@ int __metal_driver_riscv_cpu_controller_interrupt_enable_vector(struct metal_int
 
     if (id == METAL_INTERRUPT_ID_BASE) {
         if (mode == METAL_DIRECT_MODE) {
-            __metal_controller_interrupt_vector(mode, &__metal_exception_handler);
+            __metal_controller_interrupt_vector(mode, (void *)(uintptr_t)&__metal_exception_handler);
             return 0;
         }   
         if (mode == METAL_VECTOR_MODE) {
-            __metal_controller_interrupt_vector(mode, &intc->metal_mtvec_table);
+            __metal_controller_interrupt_vector(mode, (void *)&intc->metal_mtvec_table);
             return 0;
         }
     }
@@ -420,10 +711,30 @@ int __metal_driver_riscv_cpu_controller_interrupt_enable_vector(struct metal_int
 int __metal_driver_riscv_cpu_controller_interrupt_disable_vector(struct metal_interrupt *controller,
                                                               int id)
 {
+    if (id == METAL_INTERRUPT_ID_BASE) {
+        __metal_controller_interrupt_vector(METAL_DIRECT_MODE, (void *)(uintptr_t)&__metal_exception_handler);
+        return 0;
+    }
+    return -1;
+}
+
+metal_vector_mode __metal_driver_riscv_cpu_controller_get_vector_mode (struct metal_interrupt *controller)
+{   
+    return __metal_controller_interrupt_vector_mode();
+}
+
+int __metal_driver_riscv_cpu_controller_set_vector_mode (struct metal_interrupt *controller,
+                                                         metal_vector_mode mode)
+{   
     struct __metal_driver_riscv_cpu_intc *intc = (void *)(controller);
+    ( void ) intc;
 
-    if (id == METAL_INTERRUPT_ID_BASE) {
-        __metal_controller_interrupt_vector(METAL_DIRECT_MODE, &__metal_exception_handler);
+    if (mode == METAL_DIRECT_MODE) {
+        __metal_controller_interrupt_vector(mode, (void *)(uintptr_t)&__metal_exception_handler);
+            return 0;
+    }
+    if (mode == METAL_VECTOR_MODE) {
+        __metal_controller_interrupt_vector(mode, (void *)__metal_vector_table);
         return 0;
     }
     return -1;
@@ -436,25 +747,23 @@ int __metal_driver_riscv_cpu_controller_command_request (struct metal_interrupt
     return 0;
 }
 
-extern inline int __metal_controller_interrupt_is_selective_vectored(void);
-
 /* CPU driver !!! */
 
-unsigned long long __metal_driver_cpu_timer_get(struct metal_cpu *cpu)
+unsigned long long __metal_driver_cpu_mcycle_get(struct metal_cpu *cpu)
 {
     unsigned long long val = 0;
 
 #if __riscv_xlen == 32
     unsigned long hi, hi1, lo;
 
-    asm volatile ("csrr %0, mcycleh" : "=r"(hi));
-    asm volatile ("csrr %0, mcycle" : "=r"(lo));
-    asm volatile ("csrr %0, mcycleh" : "=r"(hi1));
+    __asm__ volatile ("csrr %0, mcycleh" : "=r"(hi));
+    __asm__ volatile ("csrr %0, mcycle" : "=r"(lo));
+    __asm__ volatile ("csrr %0, mcycleh" : "=r"(hi1));
     if (hi == hi1) {
         val = ((unsigned long long)hi << 32) | lo;
     }
 #else
-    asm volatile ("csrr %0, mcycle" : "=r"(val));
+    __asm__ volatile ("csrr %0, mcycle" : "=r"(val));
 #endif
 
     return val;
@@ -477,7 +786,6 @@ unsigned long long  __metal_driver_cpu_mtime_get (struct metal_cpu *cpu)
     struct metal_interrupt *tmr_intc;
     struct __metal_driver_riscv_cpu_intc *intc =
         (struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu);
-    struct __metal_driver_cpu *_cpu = (void *)cpu;
 
     if (intc) {
         tmr_intc = intc->metal_int_table[METAL_INTERRUPT_ID_TMR].sub_int;
@@ -495,7 +803,6 @@ int __metal_driver_cpu_mtimecmp_set (struct metal_cpu *cpu, unsigned long long t
     struct metal_interrupt *tmr_intc;
     struct __metal_driver_riscv_cpu_intc *intc =
         (struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu);
-    struct __metal_driver_cpu *_cpu = (void *)cpu;
 
     if (intc) {
         tmr_intc = intc->metal_int_table[METAL_INTERRUPT_ID_TMR].sub_int;
@@ -517,7 +824,7 @@ __metal_driver_cpu_timer_controller_interrupt(struct metal_cpu *cpu)
 #ifdef __METAL_DT_SIFIVE_CLIC0_HANDLE
     return __METAL_DT_SIFIVE_CLIC0_HANDLE;
 #else
-#warning "There is no interrupt controller for Timer interrupt"
+#pragma message("There is no interrupt controller for Timer interrupt")
     return NULL;
 #endif
 #endif
@@ -537,7 +844,7 @@ __metal_driver_cpu_sw_controller_interrupt(struct metal_cpu *cpu)
 #ifdef __METAL_DT_SIFIVE_CLIC0_HANDLE
     return __METAL_DT_SIFIVE_CLIC0_HANDLE;
 #else
-#warning "There is no interrupt controller for Software interrupt"
+#pragma message("There is no interrupt controller for Software interrupt")
     return NULL;
 #endif
 #endif
@@ -554,7 +861,6 @@ int __metal_driver_cpu_set_sw_ipi (struct metal_cpu *cpu, int hartid)
     struct metal_interrupt *sw_intc;
     struct __metal_driver_riscv_cpu_intc *intc = 
         (struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu);
-    struct __metal_driver_cpu *_cpu = (void *)cpu;
 
     if (intc) {
         sw_intc = intc->metal_int_table[METAL_INTERRUPT_ID_SW].sub_int;
@@ -572,7 +878,6 @@ int __metal_driver_cpu_clear_sw_ipi (struct metal_cpu *cpu, int hartid)
     struct metal_interrupt *sw_intc;
     struct __metal_driver_riscv_cpu_intc *intc =
         (struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu);
-    struct __metal_driver_cpu *_cpu = (void *)cpu;
 
     if (intc) {
         sw_intc = intc->metal_int_table[METAL_INTERRUPT_ID_SW].sub_int;
@@ -590,7 +895,6 @@ int __metal_driver_cpu_get_msip (struct metal_cpu *cpu, int hartid)
     struct metal_interrupt *sw_intc;
     struct __metal_driver_riscv_cpu_intc *intc =
         (struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu);
-    struct __metal_driver_cpu *_cpu = (void *)cpu;
 
     if (intc) {
         sw_intc = intc->metal_int_table[METAL_INTERRUPT_ID_SW].sub_int;
@@ -642,35 +946,40 @@ int __metal_driver_cpu_exception_register(struct metal_cpu *cpu, int ecode,
 
 int  __metal_driver_cpu_get_instruction_length(struct metal_cpu *cpu, uintptr_t epc)
 {
-    /* Per ISA compressed instruction has last two bits of opcode set */
-    return (*(unsigned short*)epc & 3) ? 4 : 2;
+    /**
+     * Per ISA compressed instruction has last two bits of opcode set.
+     * The encoding '00' '01' '10' are used for compressed instruction.
+     * Only enconding '11' isn't regarded as compressed instruction (>16b).
+     */
+    return ((*(unsigned short*)epc & METAL_INSN_LENGTH_MASK)
+            == METAL_INSN_NOT_COMPRESSED) ? 4 : 2;
 }
 
 uintptr_t  __metal_driver_cpu_get_exception_pc(struct metal_cpu *cpu)
 {
     uintptr_t mepc;
-    asm volatile ("csrr %0, mepc" : "=r"(mepc));
+    __asm__ volatile ("csrr %0, mepc" : "=r"(mepc));
     return mepc;
 }
 
 int  __metal_driver_cpu_set_exception_pc(struct metal_cpu *cpu, uintptr_t mepc)
 {
-    asm volatile ("csrw mepc, %0" :: "r"(mepc));
+    __asm__ volatile ("csrw mepc, %0" :: "r"(mepc));
     return 0;
 }
 
 __METAL_DEFINE_VTABLE(__metal_driver_vtable_riscv_cpu_intc) = {
-    .controller_vtable.interrupt_init = __metal_driver_riscv_cpu_controller_interrupt_init,
+    .controller_vtable.interrupt_init     = __metal_driver_riscv_cpu_controller_interrupt_init,
     .controller_vtable.interrupt_register = __metal_driver_riscv_cpu_controller_interrupt_register,
     .controller_vtable.interrupt_enable   = __metal_driver_riscv_cpu_controller_interrupt_enable,
     .controller_vtable.interrupt_disable  = __metal_driver_riscv_cpu_controller_interrupt_disable,
-    .controller_vtable.interrupt_vector_enable   = __metal_driver_riscv_cpu_controller_interrupt_enable_vector,
-    .controller_vtable.interrupt_vector_disable  = __metal_driver_riscv_cpu_controller_interrupt_disable_vector,
+    .controller_vtable.interrupt_get_vector_mode = __metal_driver_riscv_cpu_controller_get_vector_mode,
+    .controller_vtable.interrupt_set_vector_mode = __metal_driver_riscv_cpu_controller_set_vector_mode,
     .controller_vtable.command_request    = __metal_driver_riscv_cpu_controller_command_request,
 };
 
 __METAL_DEFINE_VTABLE(__metal_driver_vtable_cpu) = {
-    .cpu_vtable.timer_get     = __metal_driver_cpu_timer_get,
+    .cpu_vtable.mcycle_get     = __metal_driver_cpu_mcycle_get,
     .cpu_vtable.timebase_get  = __metal_driver_cpu_timebase_get,
     .cpu_vtable.mtime_get = __metal_driver_cpu_mtime_get,
     .cpu_vtable.mtimecmp_set = __metal_driver_cpu_mtimecmp_set,