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