]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/riscv_hal.c
Add starting point for IGLOO2 RISV-V demo project.
[freertos] / FreeRTOS / Demo / RISC-V_IGLOO2_Creative_SoftConsole / riscv_hal / riscv_hal.c
1 /*******************************************************************************\r
2  * (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.\r
3  *\r
4  * @file riscv_hal.c\r
5  * @author Microsemi SoC Products Group\r
6  * @brief Implementation of Hardware Abstraction Layer for Mi-V soft processors\r
7  *\r
8  * SVN $Revision: 9835 $\r
9  * SVN $Date: 2018-03-19 19:11:35 +0530 (Mon, 19 Mar 2018) $\r
10  */\r
11 #include <stdlib.h>\r
12 #include <stdint.h>\r
13 #include <unistd.h>\r
14 \r
15 #include "riscv_hal.h"\r
16 \r
17 #ifdef __cplusplus\r
18 extern "C" {\r
19 #endif\r
20 \r
21 #define RTC_PRESCALER 100UL\r
22 \r
23 #define SUCCESS 0U\r
24 #define ERROR   1U\r
25 \r
26 /*------------------------------------------------------------------------------\r
27  *\r
28  */\r
29 uint8_t Invalid_IRQHandler(void);\r
30 uint8_t External_1_IRQHandler(void);\r
31 uint8_t External_2_IRQHandler(void);\r
32 uint8_t External_3_IRQHandler(void);\r
33 uint8_t External_4_IRQHandler(void);\r
34 uint8_t External_5_IRQHandler(void);\r
35 uint8_t External_6_IRQHandler(void);\r
36 uint8_t External_7_IRQHandler(void);\r
37 uint8_t External_8_IRQHandler(void);\r
38 uint8_t External_9_IRQHandler(void);\r
39 uint8_t External_10_IRQHandler(void);\r
40 uint8_t External_11_IRQHandler(void);\r
41 uint8_t External_12_IRQHandler(void);\r
42 uint8_t External_13_IRQHandler(void);\r
43 uint8_t External_14_IRQHandler(void);\r
44 uint8_t External_15_IRQHandler(void);\r
45 uint8_t External_16_IRQHandler(void);\r
46 uint8_t External_17_IRQHandler(void);\r
47 uint8_t External_18_IRQHandler(void);\r
48 uint8_t External_19_IRQHandler(void);\r
49 uint8_t External_20_IRQHandler(void);\r
50 uint8_t External_21_IRQHandler(void);\r
51 uint8_t External_22_IRQHandler(void);\r
52 uint8_t External_23_IRQHandler(void);\r
53 uint8_t External_24_IRQHandler(void);\r
54 uint8_t External_25_IRQHandler(void);\r
55 uint8_t External_26_IRQHandler(void);\r
56 uint8_t External_27_IRQHandler(void);\r
57 uint8_t External_28_IRQHandler(void);\r
58 uint8_t External_29_IRQHandler(void);\r
59 uint8_t External_30_IRQHandler(void);\r
60 uint8_t External_31_IRQHandler(void);\r
61 \r
62 /*------------------------------------------------------------------------------\r
63  *\r
64  */\r
65 extern void Software_IRQHandler(void);\r
66 \r
67 /*------------------------------------------------------------------------------\r
68  * Increment value for the mtimecmp register in order to achieve a system tick\r
69  * interrupt as specified through the SysTick_Config() function.\r
70  */\r
71 static uint64_t g_systick_increment = 0U;\r
72 \r
73 /*------------------------------------------------------------------------------\r
74  * Disable all interrupts.\r
75  */\r
76 void __disable_irq(void)\r
77 {\r
78     clear_csr(mstatus, MSTATUS_MPIE);\r
79     clear_csr(mstatus, MSTATUS_MIE);\r
80 }\r
81 \r
82 /*------------------------------------------------------------------------------\r
83  * Enabler all interrupts.\r
84  */\r
85 void __enable_irq(void)\r
86 {\r
87     set_csr(mstatus, MSTATUS_MIE);\r
88 }\r
89 \r
90 /*------------------------------------------------------------------------------\r
91  * Configure the machine timer to generate an interrupt.\r
92  */\r
93 uint32_t SysTick_Config(uint32_t ticks)\r
94 {\r
95     uint32_t ret_val = ERROR;\r
96 \r
97     g_systick_increment = (uint64_t)(ticks) / RTC_PRESCALER;\r
98 \r
99     if (g_systick_increment > 0U)\r
100     {\r
101         uint32_t mhart_id = read_csr(mhartid);\r
102 \r
103         PRCI->MTIMECMP[mhart_id] = PRCI->MTIME + g_systick_increment;\r
104 \r
105         set_csr(mie, MIP_MTIP);\r
106 \r
107         __enable_irq();\r
108 \r
109         ret_val = SUCCESS;\r
110     }\r
111 \r
112     return ret_val;\r
113 }\r
114 \r
115 /*------------------------------------------------------------------------------\r
116  * RISC-V interrupt handler for machine timer interrupts.\r
117  */\r
118 static void handle_m_timer_interrupt(void)\r
119 {\r
120     clear_csr(mie, MIP_MTIP);\r
121 \r
122     SysTick_Handler();\r
123 \r
124     PRCI->MTIMECMP[read_csr(mhartid)] = PRCI->MTIME + g_systick_increment;\r
125 \r
126     set_csr(mie, MIP_MTIP);\r
127 }\r
128 \r
129 /*------------------------------------------------------------------------------\r
130  * RISC-V interrupt handler for external interrupts.\r
131  */\r
132 uint8_t (*ext_irq_handler_table[32])(void) =\r
133 {\r
134     Invalid_IRQHandler,\r
135     External_1_IRQHandler,\r
136     External_2_IRQHandler,\r
137     External_3_IRQHandler,\r
138     External_4_IRQHandler,\r
139     External_5_IRQHandler,\r
140     External_6_IRQHandler,\r
141     External_7_IRQHandler,\r
142     External_8_IRQHandler,\r
143     External_9_IRQHandler,\r
144     External_10_IRQHandler,\r
145     External_11_IRQHandler,\r
146     External_12_IRQHandler,\r
147     External_13_IRQHandler,\r
148     External_14_IRQHandler,\r
149     External_15_IRQHandler,\r
150     External_16_IRQHandler,\r
151     External_17_IRQHandler,\r
152     External_18_IRQHandler,\r
153     External_19_IRQHandler,\r
154     External_20_IRQHandler,\r
155     External_21_IRQHandler,\r
156     External_22_IRQHandler,\r
157     External_23_IRQHandler,\r
158     External_24_IRQHandler,\r
159     External_25_IRQHandler,\r
160     External_26_IRQHandler,\r
161     External_27_IRQHandler,\r
162     External_28_IRQHandler,\r
163     External_29_IRQHandler,\r
164     External_30_IRQHandler,\r
165     External_31_IRQHandler\r
166 };\r
167 \r
168 /*------------------------------------------------------------------------------\r
169  *\r
170  */\r
171 static void handle_m_ext_interrupt(void)\r
172 {\r
173     uint32_t int_num  = PLIC_ClaimIRQ();\r
174     uint8_t disable = EXT_IRQ_KEEP_ENABLED;\r
175 \r
176     disable = ext_irq_handler_table[int_num]();\r
177 \r
178     PLIC_CompleteIRQ(int_num);\r
179 \r
180     if(EXT_IRQ_DISABLE == disable)\r
181     {\r
182         PLIC_DisableIRQ((IRQn_Type)int_num);\r
183     }\r
184 }\r
185 \r
186 static void handle_m_soft_interrupt(void)\r
187 {\r
188     Software_IRQHandler();\r
189 \r
190     /*Clear software interrupt*/\r
191     PRCI->MSIP[0] = 0x00U;\r
192 }\r
193 \r
194 /*------------------------------------------------------------------------------\r
195  * Trap/Interrupt handler\r
196  */\r
197 uintptr_t handle_trap(uintptr_t mcause, uintptr_t mepc)\r
198 {\r
199     if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE)  == IRQ_M_EXT))\r
200     {\r
201         handle_m_ext_interrupt();\r
202     }\r
203     else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE)  == IRQ_M_TIMER))\r
204     {\r
205         handle_m_timer_interrupt();\r
206     }\r
207     else if ( (mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE)  == IRQ_M_SOFT))\r
208     {\r
209         handle_m_soft_interrupt();\r
210     }\r
211     else\r
212     {\r
213 #ifndef NDEBUG\r
214         /*\r
215          Arguments supplied to this function are mcause, mepc (exception PC) and stack pointer\r
216          based onprivileged-isa specification\r
217          mcause values and meanings are:\r
218          0 Instruction address misaligned (mtval/mbadaddr is the address)\r
219          1 Instruction access fault       (mtval/mbadaddr is the address)\r
220          2 Illegal instruction            (mtval/mbadaddr contains the offending instruction opcode)\r
221          3 Breakpoint\r
222          4 Load address misaligned        (mtval/mbadaddr is the address)\r
223          5 Load address fault             (mtval/mbadaddr is the address)\r
224          6 Store/AMO address fault        (mtval/mbadaddr is the address)\r
225          7 Store/AMO access fault         (mtval/mbadaddr is the address)\r
226          8 Environment call from U-mode\r
227          9 Environment call from S-mode\r
228          A Environment call from M-mode\r
229          B Instruction page fault\r
230          C Load page fault                (mtval/mbadaddr is the address)\r
231          E Store page fault               (mtval/mbadaddr is the address)\r
232         */\r
233 \r
234          uintptr_t mip      = read_csr(mip);      /* interrupt pending */\r
235          uintptr_t mbadaddr = read_csr(mbadaddr); /* additional info and meaning depends on mcause */\r
236          uintptr_t mtvec    = read_csr(mtvec);    /* trap vector */\r
237          uintptr_t mscratch = read_csr(mscratch); /* temporary, sometimes might hold temporary value of a0 */\r
238          uintptr_t mstatus  = read_csr(mstatus);  /* status contains many smaller fields: */\r
239 \r
240                 /* breakpoint*/\r
241         __asm("ebreak");\r
242 #else\r
243         _exit(1 + mcause);\r
244 #endif\r
245     }\r
246     return mepc;\r
247 }\r
248 \r
249 #ifdef __cplusplus\r
250 }\r
251 #endif\r