1 /*
2 * Copyright (c) 2021 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include "hpm_common.h"
9 #include "hpm_soc.h"
10
11 /********************** MCAUSE exception types **************************************/
12 #define MCAUSE_INSTR_ADDR_MISALIGNED (0U) //!< Instruction Address misaligned
13 #define MCAUSE_INSTR_ACCESS_FAULT (1U) //!< Instruction access fault
14 #define MCAUSE_ILLEGAL_INSTR (2U) //!< Illegal instruction
15 #define MCAUSE_BREAKPOINT (3U) //!< Breakpoint
16 #define MCAUSE_LOAD_ADDR_MISALIGNED (4U) //!< Load address misaligned
17 #define MCAUSE_LOAD_ACCESS_FAULT (5U) //!< Load access fault
18 #define MCAUSE_STORE_AMO_ADDR_MISALIGNED (6U) //!< Store/AMO address misaligned
19 #define MCAUSE_STORE_AMO_ACCESS_FAULT (7U) //!< Store/AMO access fault
20 #define MCAUSE_ECALL_FROM_USER_MODE (8U) //!< Environment call from User mode
21 #define MCAUSE_ECALL_FROM_SUPERVISOR_MODE (9U) //!< Environment call from Supervisor mode
22 #define MCAUSE_ECALL_FROM_MACHINE_MODE (11U) //!< Environment call from machine mode
23 #define MCAUSE_INSTR_PAGE_FAULT (12U) //!< Instruction page fault
24 #define MCAUSE_LOAD_PAGE_FAULT (13) //!< Load page fault
25 #define MCAUSE_STORE_AMO_PAGE_FAULT (15U) //!< Store/AMO page fault
26
27 #define IRQ_S_SOFT 1
28 #define IRQ_H_SOFT 2
29 #define IRQ_M_SOFT 3
30 #define IRQ_S_TIMER 5
31 #define IRQ_H_TIMER 6
32 #define IRQ_M_TIMER 7
33 #define IRQ_S_EXT 9
34 #define IRQ_H_EXT 10
35 #define IRQ_M_EXT 11
36 #define IRQ_COP 12
37 #define IRQ_HOST 13
38
39
40
mchtmr_isr(void)41 __attribute__((weak)) void mchtmr_isr(void)
42 {
43 }
44
swi_isr(void)45 __attribute__((weak)) void swi_isr(void)
46 {
47 }
48
syscall_handler(long n,long a0,long a1,long a2,long a3)49 __attribute__((weak)) void syscall_handler(long n, long a0, long a1, long a2, long a3)
50 {
51 }
52
exception_handler(long cause,long epc)53 __attribute__((weak)) long exception_handler(long cause, long epc)
54 {
55 switch (cause) {
56 case MCAUSE_INSTR_ADDR_MISALIGNED:
57 break;
58 case MCAUSE_INSTR_ACCESS_FAULT:
59 break;
60 case MCAUSE_ILLEGAL_INSTR:
61 break;
62 case MCAUSE_BREAKPOINT:
63 break;
64 case MCAUSE_LOAD_ADDR_MISALIGNED:
65 break;
66 case MCAUSE_LOAD_ACCESS_FAULT:
67 break;
68 case MCAUSE_STORE_AMO_ADDR_MISALIGNED:
69 break;
70 case MCAUSE_STORE_AMO_ACCESS_FAULT:
71 break;
72 case MCAUSE_ECALL_FROM_USER_MODE:
73 break;
74 case MCAUSE_ECALL_FROM_SUPERVISOR_MODE:
75 break;
76 case MCAUSE_ECALL_FROM_MACHINE_MODE:
77 break;
78 case MCAUSE_INSTR_PAGE_FAULT:
79 break;
80 case MCAUSE_LOAD_PAGE_FAULT:
81 break;
82 case MCAUSE_STORE_AMO_PAGE_FAULT:
83 break;
84 default:
85 break;
86 }
87 /* Unhandled Trap */
88 return epc;
89 }
90
91 #ifndef CONFIG_FREERTOS
92 void irq_handler_trap(void) __attribute__ ((section(".isr_vector"), interrupt("machine"), aligned(4)));
93 #else
94 void irq_handler_trap(void) __attribute__ ((section(".isr_vector")));
95 #endif
irq_handler_trap(void)96 void irq_handler_trap(void)
97 {
98 long mcause = read_csr(CSR_MCAUSE);
99 long mepc = read_csr(CSR_MEPC);
100 long mstatus = read_csr(CSR_MSTATUS);
101 #if SUPPORT_PFT_ARCH
102 long mxstatus = read_csr(CSR_MXSTATUS);
103 #endif
104 #ifdef __riscv_dsp
105 int ucode = read_csr(CSR_UCODE);
106 #endif
107 #ifdef __riscv_flen
108 int fcsr = read_fcsr();
109 #endif
110
111 /* clobbers list for ecall */
112 #ifdef __riscv_32e
113 __asm volatile("" : : :"t0", "a0", "a1", "a2", "a3");
114 #else
115 __asm volatile("" : : :"a7", "a0", "a1", "a2", "a3");
116 #endif
117
118 /* Do your trap handling */
119 if ((mcause & CSR_MCAUSE_INTERRUPT_MASK) && ((mcause & CSR_MCAUSE_EXCEPTION_CODE_MASK) == IRQ_M_TIMER)) {
120 /* Machine timer interrupt */
121 mchtmr_isr();
122 }
123 #ifdef USE_NONVECTOR_MODE
124 else if ((mcause & CSR_MCAUSE_INTERRUPT_MASK) && ((mcause & CSR_MCAUSE_EXCEPTION_CODE_MASK) == IRQ_M_EXT)) {
125
126 typedef void(*isr_func_t)(void);
127
128 /* Machine-level interrupt from PLIC */
129 uint32_t irq_index = __plic_claim_irq(HPM_PLIC_BASE, HPM_PLIC_TARGET_M_MODE);
130 if (irq_index) {
131 /* Workaround: irq number returned by __plic_claim_irq might be 0, which is caused by plic. So skip invalid irq_index as a workaround */
132 #ifndef DISABLE_IRQ_PREEMPTIVE
133 enable_global_irq(CSR_MSTATUS_MIE_MASK);
134 #endif
135 ((isr_func_t)__vector_table[irq_index])();
136 __plic_complete_irq(HPM_PLIC_BASE, HPM_PLIC_TARGET_M_MODE, irq_index);
137 }
138
139 }
140 #endif
141
142 else if ((mcause & CSR_MCAUSE_INTERRUPT_MASK) && ((mcause & CSR_MCAUSE_EXCEPTION_CODE_MASK) == IRQ_M_SOFT)) {
143 /* Machine SWI interrupt */
144 intc_m_claim_swi();
145 swi_isr();
146 intc_m_complete_swi();
147 } else if (!(mcause & CSR_MCAUSE_INTERRUPT_MASK) && ((mcause & CSR_MCAUSE_EXCEPTION_CODE_MASK) == MCAUSE_ECALL_FROM_MACHINE_MODE)) {
148 /* Machine Syscal call */
149 __asm volatile(
150 "mv a4, a3\n"
151 "mv a3, a2\n"
152 "mv a2, a1\n"
153 "mv a1, a0\n"
154 #ifdef __riscv_32e
155 "mv a0, t0\n"
156 #else
157 "mv a0, a7\n"
158 #endif
159 "jalr %0\n"
160 : :"r"(syscall_handler) : "a4"
161 );
162 mepc += 4;
163 } else {
164 mepc = exception_handler(mcause, mepc);
165 }
166
167 /* Restore CSR */
168 write_csr(CSR_MSTATUS, mstatus);
169 write_csr(CSR_MEPC, mepc);
170 #if SUPPORT_PFT_ARCH
171 write_csr(CSR_MXSTATUS, mxstatus);
172 #endif
173 #ifdef __riscv_dsp
174 write_csr(CSR_UCODE, ucode);
175 #endif
176 #ifdef __riscv_flen
177 write_fcsr(fcsr);
178 #endif
179 }
180