1 /*
2 * Copyright (c) 2021-2023 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7 #include "hpm_common.h"
8 #include "hpm_soc.h"
9 #include <rtthread.h>
10 #include "rt_hw_stack_frame.h"
11
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 #ifdef DEBUG
40 #define RT_EXCEPTION_TRACE rt_kprintf
41 #else
42 #define RT_EXCEPTION_TRACE(...)
43 #endif
44
45 typedef void (*isr_func_t)(void);
46
47 static volatile rt_hw_stack_frame_t *s_stack_frame;
48
mchtmr_isr(void)49 __attribute((weak)) void mchtmr_isr(void)
50 {
51 }
52
mswi_isr(void)53 __attribute__((weak)) void mswi_isr(void)
54 {
55 }
56
syscall_handler(uint32_t n,uint32_t a0,uint32_t a1,uint32_t a2,uint32_t a3)57 __attribute__((weak)) void syscall_handler(uint32_t n, uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3)
58 {
59 }
60
rt_show_stack_frame(void)61 void rt_show_stack_frame(void)
62 {
63 RT_EXCEPTION_TRACE("Stack frame:\r\n----------------------------------------\r\n");
64 RT_EXCEPTION_TRACE("ra : 0x%08x\r\n", s_stack_frame->ra);
65 RT_EXCEPTION_TRACE("mstatus : 0x%08x\r\n", read_csr(0x300));//mstatus
66 RT_EXCEPTION_TRACE("t0 : 0x%08x\r\n", s_stack_frame->t0);
67 RT_EXCEPTION_TRACE("t1 : 0x%08x\r\n", s_stack_frame->t1);
68 RT_EXCEPTION_TRACE("t2 : 0x%08x\r\n", s_stack_frame->t2);
69 RT_EXCEPTION_TRACE("a0 : 0x%08x\r\n", s_stack_frame->a0);
70 RT_EXCEPTION_TRACE("a1 : 0x%08x\r\n", s_stack_frame->a1);
71 RT_EXCEPTION_TRACE("a2 : 0x%08x\r\n", s_stack_frame->a2);
72 RT_EXCEPTION_TRACE("a3 : 0x%08x\r\n", s_stack_frame->a3);
73 RT_EXCEPTION_TRACE("a4 : 0x%08x\r\n", s_stack_frame->a4);
74 RT_EXCEPTION_TRACE("a5 : 0x%08x\r\n", s_stack_frame->a5);
75 #ifndef __riscv_32e
76 RT_EXCEPTION_TRACE("a6 : 0x%08x\r\n", s_stack_frame->a6);
77 RT_EXCEPTION_TRACE("a7 : 0x%08x\r\n", s_stack_frame->a7);
78 RT_EXCEPTION_TRACE("t3 : 0x%08x\r\n", s_stack_frame->t3);
79 RT_EXCEPTION_TRACE("t4 : 0x%08x\r\n", s_stack_frame->t4);
80 RT_EXCEPTION_TRACE("t5 : 0x%08x\r\n", s_stack_frame->t5);
81 RT_EXCEPTION_TRACE("t6 : 0x%08x\r\n", s_stack_frame->t6);
82 #endif
83 }
84
exception_handler(uint32_t cause,uint32_t epc)85 uint32_t exception_handler(uint32_t cause, uint32_t epc)
86 {
87 /* Unhandled Trap */
88 uint32_t mdcause = read_csr(CSR_MDCAUSE);
89 uint32_t mtval = read_csr(CSR_MTVAL);
90 rt_uint32_t mscratch = read_csr(0x340);
91
92 s_stack_frame = (rt_hw_stack_frame_t *)mscratch;
93 rt_show_stack_frame();
94
95 switch (cause)
96 {
97 case MCAUSE_INSTR_ADDR_MISALIGNED:
98 RT_EXCEPTION_TRACE("exception: instruction address was mis-aligned, mtval=0x%08x\n", mtval);
99 break;
100 case MCAUSE_INSTR_ACCESS_FAULT:
101 RT_EXCEPTION_TRACE("exception: instruction access fault happened, mtval=0x%08x, epc=0x%08x\n", mtval, epc);
102 switch (mdcause & 0x07)
103 {
104 case 1:
105 RT_EXCEPTION_TRACE("mdcause: ECC/Parity error\r\n");
106 break;
107 case 2:
108 RT_EXCEPTION_TRACE("mdcause: PMP instruction access violation \r\n");
109 break;
110 case 3:
111 RT_EXCEPTION_TRACE("mdcause: BUS error\r\n");
112 break;
113 case 4:
114 RT_EXCEPTION_TRACE("mdcause: PMP empty hole access \r\n");
115 break;
116 default:
117 RT_EXCEPTION_TRACE("mdcause: reserved \r\n");
118 break;
119 }
120 break;
121 case MCAUSE_ILLEGAL_INSTR:
122 RT_EXCEPTION_TRACE("exception: illegal instruction was met, mtval=0x%08x\n", mtval);
123 switch (mdcause & 0x07)
124 {
125 case 0:
126 RT_EXCEPTION_TRACE("mdcause: the actual faulting instruction is stored in the mtval CSR\r\n");
127 break;
128 case 1:
129 RT_EXCEPTION_TRACE("mdcause: FP disabled exception \r\n");
130 break;
131 case 2:
132 RT_EXCEPTION_TRACE("mdcause: ACE disabled exception \r\n");
133 break;
134 default:
135 RT_EXCEPTION_TRACE("mdcause: reserved \r\n");
136 break;
137 }
138 break;
139 case MCAUSE_BREAKPOINT:
140 RT_EXCEPTION_TRACE("exception: breakpoint was hit, mtval=0x%08x\n", mtval);
141 break;
142 case MCAUSE_LOAD_ADDR_MISALIGNED:
143 RT_EXCEPTION_TRACE("exception: load address was mis-aligned, mtval=0x%08x\n", mtval);
144 break;
145 case MCAUSE_LOAD_ACCESS_FAULT:
146 RT_EXCEPTION_TRACE("exception: load access fault happened, epc=%08x, mdcause=0x%x\n", epc, mdcause);
147 switch (mdcause & 0x07)
148 {
149 case 1:
150 RT_EXCEPTION_TRACE("mdcause: ECC/Parity error\r\n");
151 break;
152 case 2:
153 RT_EXCEPTION_TRACE("mdcause: PMP instruction access violation \r\n");
154 break;
155 case 3:
156 RT_EXCEPTION_TRACE("mdcause: BUS error\r\n");
157 break;
158 case 4:
159 RT_EXCEPTION_TRACE("mdcause: Misaligned access \r\n");
160 break;
161 case 5:
162 RT_EXCEPTION_TRACE("mdcause: PMP empty hole access \r\n");
163 break;
164 case 6:
165 RT_EXCEPTION_TRACE("mdcause: PMA attribute inconsistency\r\n");
166 break;
167 default:
168 RT_EXCEPTION_TRACE("mdcause: reserved \r\n");
169 break;
170 }
171 break;
172 case MCAUSE_STORE_AMO_ADDR_MISALIGNED:
173 RT_EXCEPTION_TRACE("exception: store amo address was misaligned, epc=%08x\n", epc);
174 break;
175 case MCAUSE_STORE_AMO_ACCESS_FAULT:
176 RT_EXCEPTION_TRACE("exception: store amo access fault happened, epc=%08x\n", epc);
177 switch (mdcause & 0x07)
178 {
179 case 1:
180 RT_EXCEPTION_TRACE("mdcause: ECC/Parity error\r\n");
181 break;
182 case 2:
183 RT_EXCEPTION_TRACE("mdcause: PMP instruction access violation \r\n");
184 break;
185 case 3:
186 RT_EXCEPTION_TRACE("mdcause: BUS error\r\n");
187 break;
188 case 4:
189 RT_EXCEPTION_TRACE("mdcause: Misaligned access \r\n");
190 break;
191 case 5:
192 RT_EXCEPTION_TRACE("mdcause: PMP empty hole access \r\n");
193 break;
194 case 6:
195 RT_EXCEPTION_TRACE("mdcause: PMA attribute inconsistency\r\n");
196 break;
197 case 7:
198 RT_EXCEPTION_TRACE("mdcause: PMA NAMO exception \r\n");
199 default:
200 RT_EXCEPTION_TRACE("mdcause: reserved \r\n");
201 break;
202 }
203 break;
204 default:
205 RT_EXCEPTION_TRACE("Unknown exception happened, cause=%d\n", cause);
206 break;
207 }
208
209 rt_kprintf("cause=0x%08x, epc=0x%08x, ra=0x%08x\n", cause, epc, s_stack_frame->ra);
210 while(1) {
211 }
212 }
213
214 void trap_entry(void);
215
trap_entry(void)216 void trap_entry(void)
217 {
218 uint32_t mcause = read_csr(CSR_MCAUSE);
219 uint32_t mepc = read_csr(CSR_MEPC);
220 uint32_t mstatus = read_csr(CSR_MSTATUS);
221
222 #if SUPPORT_PFT_ARCH
223 uint32_t mxstatus = read_csr(CSR_MXSTATUS);
224 #endif
225 #ifdef __riscv_dsp
226 int ucode = read_csr(CSR_UCODE);
227 #endif
228 #ifdef __riscv_flen
229 int fcsr = read_fcsr();
230 #endif
231
232 /* clobbers list for ecall */
233 #ifdef __riscv_32e
234 __asm volatile("" : : :"t0", "a0", "a1", "a2", "a3");
235 #else
236 __asm volatile("" : : :"a7", "a0", "a1", "a2", "a3");
237 #endif
238
239 /* Do your trap handling */
240 uint32_t cause_type = mcause & CSR_MCAUSE_EXCEPTION_CODE_MASK;
241 uint32_t irq_index;
242 if (mcause & CSR_MCAUSE_INTERRUPT_MASK)
243 {
244 switch (cause_type)
245 {
246 /* Machine timer interrupt */
247 case IRQ_M_TIMER:
248 mchtmr_isr();
249 break;
250 /* Machine EXT interrupt */
251 case IRQ_M_EXT:
252 /* Claim interrupt */
253 irq_index = __plic_claim_irq(HPM_PLIC_BASE, HPM_PLIC_TARGET_M_MODE);
254 /* Execute EXT interrupt handler */
255 if (irq_index > 0)
256 {
257 ((isr_func_t) __vector_table[irq_index])();
258 /* Complete interrupt */
259 __plic_complete_irq(HPM_PLIC_BASE, HPM_PLIC_TARGET_M_MODE, irq_index);
260 }
261 break;
262 /* Machine SWI interrupt */
263 case IRQ_M_SOFT:
264 mswi_isr();
265 intc_m_complete_swi();
266 break;
267 }
268 }
269 else if (cause_type == MCAUSE_ECALL_FROM_MACHINE_MODE)
270 {
271 /* Machine Syscal call */
272 __asm volatile(
273 "mv a4, a3\n"
274 "mv a3, a2\n"
275 "mv a2, a1\n"
276 "mv a1, a0\n"
277 #ifdef __riscv_32e
278 "mv a0, t0\n"
279 #else
280 "mv a0, a7\n"
281 #endif
282 "call syscall_handler\n"
283 : : : "a4"
284 );
285 mepc += 4;
286 }
287 else
288 {
289 mepc = exception_handler(mcause, mepc);
290 }
291
292 /* Restore CSR */
293 write_csr(CSR_MSTATUS, mstatus);
294 write_csr(CSR_MEPC, mepc);
295 #if SUPPORT_PFT_ARCH
296 write_csr(CSR_MXSTATUS, mxstatus);
297 #endif
298 #ifdef __riscv_dsp
299 write_csr(CSR_UCODE, ucode);
300 #endif
301 #ifdef __riscv_flen
302 write_fcsr(fcsr);
303 #endif
304 }
305
306 /**
307 * Trap Handler
308 */
handle_trap(rt_uint32_t mcause,rt_uint32_t mepc,rt_uint32_t sp)309 rt_weak void handle_trap(rt_uint32_t mcause, rt_uint32_t mepc, rt_uint32_t sp)
310 {
311 }
312