RV32 SoC DS UG
High-Perf RV32 SoC DS UG
RV64 SoC DS UG API and Examples
Embedded IDE UG
Loading...
Searching...
No Matches
mtrap.c
Go to the documentation of this file.
1
2// Copyright (C) 2013-2026 Efinix Inc. All rights reserved.
3// Full license header bsp/efinix/EfxSapphireSocRV64/include/LICENSE.MD
5
6
16
17#include <stddef.h>
18#include "bsp.h"
19#include "mtrap.h"
20
21/******************************************************************************
22*
23* @brief Default Fallback Interrupt Handler.
24* @note Invoked if an interrupt fires but no specific handler is defined.
25*
26******************************************************************************/
28 LOG_WARN(DBG_MOD_IRQ, "Default IRQ handler invoked (Unhandled Interrupt).");
29 return 0;
30}
31
32/******************************************************************************
33*
34* @brief These are weak aliases for all PLIC interrupt sources.
35* @note The user can override any of these by defining a function with the same name.
36*
37******************************************************************************/
38int irq_m_invalid_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 0
39int irq_m_uart0_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 1
40int irq_m_uart1_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 2
41int irq_m_uart2_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 3
42int irq_m_spi0_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 6
43int irq_m_spi1_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 7
44int irq_m_spi2_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 8
45int irq_m_i2c0_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 11
46int irq_m_i2c1_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 12
47int irq_m_i2c2_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 13
48int irq_m_i2c3_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 14
49int irq_m_i2c4_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 15
50int irq_m_gpio0_0_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 16
51int irq_m_gpio0_1_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 17
52int irq_m_gpio1_0_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 18
53int irq_m_gpio1_1_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 19
54int irq_m_userTimer0_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 21
55int irq_m_userTimer1_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 22
56int irq_m_userTimer2_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 23
57int irq_m_watchDog0_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 26
58int irq_m_axiA_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 30
59int irq_m_l2Cache_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 31
60int irq_m_user_a_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 32
61int irq_m_user_b_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 33
62int irq_m_user_c_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 34
63int irq_m_user_d_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 35
64int irq_m_user_e_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 36
65int irq_m_user_f_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 37
66int irq_m_user_g_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 38
67int irq_m_user_h_handler(void) __attribute__((weak, alias("irq_handleDefault"))); // ID: 39
68
69
70/******************************************************************************
71*
72* @brief Vector Table for PLIC Interrupts.
73*
74******************************************************************************/
75int (*interrupt_vector_table[64])(void) =
76{
81 0, // 4
82 0, // 5
86 0, // 9
87 0, // 10
97 0, // 20
101 0, // 24
102 0, // 25
104 0, // 27
105 0, // 28
106 0, // 29
107 irq_m_axiA_handler, // 30
117};
118
119
120/******************************************************************************
121*
122* @brief This function uses for setting up the trap entry point.
123* @note Naked function to setup the stack and call the C trap handler.
124* @note This trap entry should work for both RV32 and RV64, with or without FPU,
125* by adjusting the stack frame accordingly.
126*
127******************************************************************************/
128__attribute__((naked, aligned(4)))
129void trap_entry (void) {
130
131 asm volatile (
132 "addi sp,sp, -(" STACK_SIZE ")\n"
133
134 // --- SAVE GPRs ---
135 STORE " x1, 0*"GPR_SIZE"(sp)\n"
136 STORE " x5, 1*"GPR_SIZE"(sp)\n"
137 STORE " x6, 2*"GPR_SIZE"(sp)\n"
138 STORE " x7, 3*"GPR_SIZE"(sp)\n"
139 STORE " x10, 4*"GPR_SIZE"(sp)\n"
140 STORE " x11, 5*"GPR_SIZE"(sp)\n"
141 STORE " x12, 6*"GPR_SIZE"(sp)\n"
142 STORE " x13, 7*"GPR_SIZE"(sp)\n"
143 STORE " x14, 8*"GPR_SIZE"(sp)\n"
144 STORE " x15, 9*"GPR_SIZE"(sp)\n"
145 STORE " x16, 10*"GPR_SIZE"(sp)\n"
146 STORE " x17, 11*"GPR_SIZE"(sp)\n"
147 STORE " x28, 12*"GPR_SIZE"(sp)\n"
148 STORE " x29, 13*"GPR_SIZE"(sp)\n"
149 STORE " x30, 14*"GPR_SIZE"(sp)\n"
150 STORE " x31, 15*"GPR_SIZE"(sp)\n"
151
152#ifdef __riscv_flen
153 // --- SAVE FPRs ---
154 FSTORE " f0, (16*"GPR_SIZE" + 0*"FPR_SIZE")(sp)\n"
155 FSTORE " f1, (16*"GPR_SIZE" + 1*"FPR_SIZE")(sp)\n"
156 FSTORE " f2, (16*"GPR_SIZE" + 2*"FPR_SIZE")(sp)\n"
157 FSTORE " f3, (16*"GPR_SIZE" + 3*"FPR_SIZE")(sp)\n"
158 FSTORE " f4, (16*"GPR_SIZE" + 4*"FPR_SIZE")(sp)\n"
159 FSTORE " f5, (16*"GPR_SIZE" + 5*"FPR_SIZE")(sp)\n"
160 FSTORE " f6, (16*"GPR_SIZE" + 6*"FPR_SIZE")(sp)\n"
161 FSTORE " f7, (16*"GPR_SIZE" + 7*"FPR_SIZE")(sp)\n"
162 FSTORE " f10, (16*"GPR_SIZE" + 8*"FPR_SIZE")(sp)\n"
163 FSTORE " f11, (16*"GPR_SIZE" + 9*"FPR_SIZE")(sp)\n"
164 FSTORE " f12, (16*"GPR_SIZE" + 10*"FPR_SIZE")(sp)\n"
165 FSTORE " f13, (16*"GPR_SIZE" + 11*"FPR_SIZE")(sp)\n"
166 FSTORE " f14, (16*"GPR_SIZE" + 12*"FPR_SIZE")(sp)\n"
167 FSTORE " f15, (16*"GPR_SIZE" + 13*"FPR_SIZE")(sp)\n"
168 FSTORE " f16, (16*"GPR_SIZE" + 14*"FPR_SIZE")(sp)\n"
169 FSTORE " f17, (16*"GPR_SIZE" + 15*"FPR_SIZE")(sp)\n"
170 FSTORE " f28, (16*"GPR_SIZE" + 16*"FPR_SIZE")(sp)\n"
171 FSTORE " f29, (16*"GPR_SIZE" + 17*"FPR_SIZE")(sp)\n"
172 FSTORE " f30, (16*"GPR_SIZE" + 18*"FPR_SIZE")(sp)\n"
173 FSTORE " f31, (16*"GPR_SIZE" + 19*"FPR_SIZE")(sp)\n"
174
175 // --- SAVE FCSR ---
176 "csrr t0, fcsr\n"
177 STORE " t0, (16*"GPR_SIZE" + 20*"FPR_SIZE")(sp)\n"
178#endif
179
180 "call trap\n"
181
182#ifdef __riscv_flen
183 // --- RESTORE FCSR ---
184 LOAD " t0, (16*"GPR_SIZE" + 20*"FPR_SIZE")(sp)\n"
185 "csrw fcsr, t0\n"
186
187 // --- RESTORE FPRs ---
188 FLOAD " f0, (16*"GPR_SIZE" + 0*"FPR_SIZE")(sp)\n"
189 FLOAD " f1, (16*"GPR_SIZE" + 1*"FPR_SIZE")(sp)\n"
190 FLOAD " f2, (16*"GPR_SIZE" + 2*"FPR_SIZE")(sp)\n"
191 FLOAD " f3, (16*"GPR_SIZE" + 3*"FPR_SIZE")(sp)\n"
192 FLOAD " f4, (16*"GPR_SIZE" + 4*"FPR_SIZE")(sp)\n"
193 FLOAD " f5, (16*"GPR_SIZE" + 5*"FPR_SIZE")(sp)\n"
194 FLOAD " f6, (16*"GPR_SIZE" + 6*"FPR_SIZE")(sp)\n"
195 FLOAD " f7, (16*"GPR_SIZE" + 7*"FPR_SIZE")(sp)\n"
196 FLOAD " f10, (16*"GPR_SIZE" + 8*"FPR_SIZE")(sp)\n"
197 FLOAD " f11, (16*"GPR_SIZE" + 9*"FPR_SIZE")(sp)\n"
198 FLOAD " f12, (16*"GPR_SIZE" + 10*"FPR_SIZE")(sp)\n"
199 FLOAD " f13, (16*"GPR_SIZE" + 11*"FPR_SIZE")(sp)\n"
200 FLOAD " f14, (16*"GPR_SIZE" + 12*"FPR_SIZE")(sp)\n"
201 FLOAD " f15, (16*"GPR_SIZE" + 13*"FPR_SIZE")(sp)\n"
202 FLOAD " f16, (16*"GPR_SIZE" + 14*"FPR_SIZE")(sp)\n"
203 FLOAD " f17, (16*"GPR_SIZE" + 15*"FPR_SIZE")(sp)\n"
204 FLOAD " f28, (16*"GPR_SIZE" + 16*"FPR_SIZE")(sp)\n"
205 FLOAD " f29, (16*"GPR_SIZE" + 17*"FPR_SIZE")(sp)\n"
206 FLOAD " f30, (16*"GPR_SIZE" + 18*"FPR_SIZE")(sp)\n"
207 FLOAD " f31, (16*"GPR_SIZE" + 19*"FPR_SIZE")(sp)\n"
208#endif
209
210 // --- RESTORE GPRs ---
211 LOAD " x1 , 0*"GPR_SIZE"(sp)\n"
212 LOAD " x5, 1*"GPR_SIZE"(sp)\n"
213 LOAD " x6, 2*"GPR_SIZE"(sp)\n"
214 LOAD " x7, 3*"GPR_SIZE"(sp)\n"
215 LOAD " x10, 4*"GPR_SIZE"(sp)\n"
216 LOAD " x11, 5*"GPR_SIZE"(sp)\n"
217 LOAD " x12, 6*"GPR_SIZE"(sp)\n"
218 LOAD " x13, 7*"GPR_SIZE"(sp)\n"
219 LOAD " x14, 8*"GPR_SIZE"(sp)\n"
220 LOAD " x15, 9*"GPR_SIZE"(sp)\n"
221 LOAD " x16, 10*"GPR_SIZE"(sp)\n"
222 LOAD " x17, 11*"GPR_SIZE"(sp)\n"
223 LOAD " x28, 12*"GPR_SIZE"(sp)\n"
224 LOAD " x29, 13*"GPR_SIZE"(sp)\n"
225 LOAD " x30, 14*"GPR_SIZE"(sp)\n"
226 LOAD " x31, 15*"GPR_SIZE"(sp)\n"
227
228 "addi sp,sp, " STACK_SIZE "\n"
229 "mret\n"
230 );
231}
232
233/******************************************************************************
234*
235* @brief Claim pending interrupts for a hart and call their corresponding handlers.
236*
237* @param hart_id Hart ID
238*
239* @note Uses PLIC claim/release mechanism.
240*
241******************************************************************************/
243{
244 volatile uintptr_t id;
245
246 while ((id = plic_claimExtIRQ_m())) {
247
248 // Call the external interrupt handler
250
252 }
253}
254
255/******************************************************************************
256*
257* @brief This function handles to report exception counter and cause .
258*
259* @note Default exception handler to read and print mepc and mcause.
260* __attribute__((weak)) means the user can override this function.
261*
262******************************************************************************/
263__attribute__((weak))
265{
266 LOG_ERR(DBG_MOD_FAULT,"Exception occurred!\n");
267 LOG_ERR(DBG_MOD_FAULT,"mepc: 0x%lx\n", csr_read(mepc));
268 LOG_ERR(DBG_MOD_FAULT,"mcause: 0x%lx\n", csr_read(mcause));
269 while(1) {
270 __asm__ volatile ("wfi");
271 }
272
273}
274
275/******************************************************************************
276*
277* @brief This function uses when unexpected cause happens.
278*
279* @note Default crash handler for any unhandled exceptions or interrupts.
280* __attribute__((weak)) means the user can override this function.
281*
282******************************************************************************/
283__attribute__((weak))
284void crash()
285{
286 LOG_ERR(DBG_MOD_FAULT,"\n*** Unsupported irq or exception ***\n");
287 while(1) {
288 __asm__ volatile ("wfi");
289 }
290}
291
292/******************************************************************************
293*
294* @brief Default function handles both exceptions and interrupts.
295*
296* @note Called by trap_entry (from trap.S) on any trap event.
297* It reads mcause to determine the type of trap, and then
298* calls the corresponding handler function.
299* If unhandled, it calls crash().
300* __attribute__((weak)) means the user can override this function.
301*
302******************************************************************************/
303__attribute__((weak))
304void trap(){
305 // Read the current hart/core ID
306 volatile uintptr_t mhartid = csr_read(mhartid);
307
308 // Read the cause of the trap
309 volatile intptr_t mcause = csr_read(mcause);
310
311 // Determine if it is an interrupt (true) or exception (false)
312 intptr_t interrupt = mcause < 0;
313 intptr_t cause = mcause & 0xF; // Lower bits indicate cause
314
315 if(interrupt){ // Handle interrupts
316 switch(cause){
317
319 // Needs a handler that clears the CLINT MSIP bit.
321 break;
322
324 // Needs a handler that updates the CLINT mtimecmp register.
326 break;
327
329 // It handles the PLIC "Claim/Release" dance.
330 irq_handleExt();
331 break;
332 default:
333 crash(); // Call crash if interrupt is unhandled
334 }
335 } else { // Handle exceptions
336 switch (cause){
337 case CAUSE_INSTRUCTION_ADDR_MISALIGNED: // Instruction address misaligned
338 case CAUSE_ACCESS_FAULT: // Memory access fault
339 case CAUSE_ILLEGAL_INSTRUCTION: // Illegal instruction executed
340 case CAUSE_BREAKPOINT: // Breakpoint trap
341 case CAUSE_LOAD_ADDR_MISALIGNED: // Load address misaligned
342 case CAUSE_LOAD_ACCESS_FAULT: // Load access fault
343 case CAUSE_STORE_AMO_ADDR_MISALIGNED: // Store/AMO address misaligned
344 case CAUSE_STORE_AMO_ACCESS_FAULT: // Store/AMO access fault
345 case CAUSE_ENV_CALL_U_MODE: // Environment call from U-mode
346 case CAUSE_ENV_CALL_S_MODE: // Environment call from S-mode
347 case CAUSE_ENV_CALL_M_MODE: // Environment call from M-mode
348 case CAUSE_INSTRUCTION_PAGE_FAULT: // Instruction page fault
349 case CAUSE_LOAD_PAGE_FAULT: // Load page fault
350 case CAUSE_STORE_AMO_PAGE_FAULT: // Store/AMO page fault
352 break;
353 default: // Any other exception
354 crash();
355 }
356 }
357}
Board Support Package API definitions.
#define LOG_WARN(mod, fmt,...)
Log a warning message (yellow).
Definition debug.h:245
#define LOG_ERR(mod, fmt,...)
Log an error message (red).
Definition debug.h:257
#define DBG_MOD_FAULT
Hard faults and errors.
Definition debug.h:139
#define DBG_MOD_IRQ
Interrupt controller.
Definition debug.h:138
int irq_handleDefault(void)
Default Fallback Interrupt Handler.
Definition mtrap.c:27
void irq_handleExt()
External Interrupt Handler (PLIC).
Definition mtrap.c:242
void trap_entry(void)
The Main Trap Entry Point (Naked).
Definition mtrap.c:129
void crash()
Fatal Exception Handler.
Definition mtrap.c:284
int irq_handleSoft(void)
Handlers for CPU interrupts (Software).
void trap()
Main C Trap Dispatcher.
Definition mtrap.c:304
int irq_handleTimer(void)
Handlers for CPU interrupts (Timer).
#define LOAD
Load Word (32-bit).
Definition mtrap.h:73
#define GPR_SIZE
Definition mtrap.h:74
#define STACK_SIZE
Definition mtrap.h:75
#define STORE
Store Word (32-bit).
Definition mtrap.h:72
int(* interrupt_vector_table[64])(void)
Global Interrupt Vector Table.
Definition mtrap.c:75
void plic_releaseExtIRQ_m(u32 gateway)
Release ID source from external IRQ.
Definition plic.c:34
u32 plic_claimExtIRQ_m()
Initialize the PLIC instance with a base address. Calculates the internal pointers for the register b...
Definition plic.c:28
#define CAUSE_ILLEGAL_INSTRUCTION
Exception: Illegal Instruction.
Definition riscv.h:103
#define CAUSE_ENV_CALL_M_MODE
Exception: Environment Call from M Mode.
Definition riscv.h:111
#define CAUSE_STORE_AMO_PAGE_FAULT
Exception: Store/AMO Page Fault.
Definition riscv.h:114
#define CAUSE_MACHINE_EXTERNAL
Interrupt: Machine External.
Definition riscv.h:95
#define CAUSE_MACHINE_SOFTWARE
Interrupt: Machine Software.
Definition riscv.h:89
#define CAUSE_ENV_CALL_U_MODE
Exception: Environment Call from U Mode.
Definition riscv.h:109
#define CAUSE_LOAD_ADDR_MISALIGNED
Exception: Load Address Misaligned.
Definition riscv.h:105
#define CAUSE_ACCESS_FAULT
Exception: Instruction Access Fault.
Definition riscv.h:102
#define CAUSE_BREAKPOINT
Exception: Breakpoint.
Definition riscv.h:104
#define CAUSE_STORE_AMO_ACCESS_FAULT
Exception: Store/AMO Access Fault.
Definition riscv.h:108
#define CAUSE_INSTRUCTION_ADDR_MISALIGNED
Exception: Instruction Address Misaligned.
Definition riscv.h:101
#define CAUSE_LOAD_ACCESS_FAULT
Exception: Load Access Fault.
Definition riscv.h:106
#define CAUSE_INSTRUCTION_PAGE_FAULT
Exception: Instruction Page Fault.
Definition riscv.h:112
#define CAUSE_MACHINE_TIMER
Interrupt: Machine Timer.
Definition riscv.h:92
#define CAUSE_LOAD_PAGE_FAULT
Exception: Load Page Fault.
Definition riscv.h:113
#define CAUSE_STORE_AMO_ADDR_MISALIGNED
Exception: Store/AMO Address Misaligned.
Definition riscv.h:107
#define CAUSE_ENV_CALL_S_MODE
Exception: Environment Call from S Mode.
Definition riscv.h:110
#define csr_read(csr)
This function is used to read the value of a CSR.
Definition riscv.h:232
int irq_m_gpio1_1_handler(void)
int irq_m_user_h_handler(void)
int irq_m_user_c_handler(void)
int irq_m_gpio0_0_handler(void)
int irq_m_spi1_handler(void)
int irq_m_user_f_handler(void)
int irq_m_gpio0_1_handler(void)
int irq_m_userTimer2_handler(void)
int irq_m_uart1_handler(void)
int irq_m_i2c3_handler(void)
int irq_m_invalid_handler(void)
int irq_m_l2Cache_handler(void)
int irq_m_user_e_handler(void)
int irq_m_i2c0_handler(void)
int irq_m_userTimer1_handler(void)
int irq_m_user_g_handler(void)
int irq_m_userTimer0_handler(void)
int irq_m_i2c1_handler(void)
int irq_m_uart0_handler(void)
int irq_m_i2c2_handler(void)
int irq_m_axiA_handler(void)
int irq_m_gpio1_0_handler(void)
int irq_m_watchDog0_handler(void)
int irq_m_user_b_handler(void)
void irq_handleException()
Definition mtrap.c:264
int irq_m_spi0_handler(void)
int irq_m_uart2_handler(void)
int irq_m_spi2_handler(void)
int irq_m_user_d_handler(void)
int irq_m_i2c4_handler(void)
int irq_m_user_a_handler(void)
Trap (Interrupt) and Exception Handling Definitions.