1 /* See LICENSE for license details. */
2 #include <gd32vf103.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 
7 #include "riscv_encoding.h"
8 #include "n200_func.h"
9 
10 /* Configure PMP to make all the address space accesable and executable */
pmp_open_all_space(void)11 void pmp_open_all_space(void){
12     /* Config entry0 addr to all 1s to make the range cover all space */
13     __asm__ volatile ("li x6, 0xffffffff":::"x6");
14     __asm__ volatile ("csrw pmpaddr0, x6":::);
15     /* Config entry0 cfg to make it NAPOT address mode, and R/W/X okay */
16     __asm__ volatile ("li x6, 0x7f":::"x6");
17     __asm__ volatile ("csrw pmpcfg0, x6":::);
18 }
19 
switch_m2u_mode(void)20 void switch_m2u_mode(void){
21 #if   defined (__ICCRISCV__)
22     clear_csr (CSR_MSTATUS,MSTATUS_MPP);
23 #elif defined ( __GNUC__ )
24     clear_csr (mstatus,MSTATUS_MPP);
25 #endif
26     /* printf("\nIn the m2u function, the mstatus is 0x%x\n", read_csr(mstatus)); */
27     /* printf("\nIn the m2u function, the mepc is 0x%x\n", read_csr(mepc)); */
28 #if defined ( __GNUC__ )
29     __asm__ volatile ("la x6, 1f    ":::"x6");
30 #endif
31     __asm__ volatile ("csrw mepc, x6":::);
32     __asm__ volatile ("mret":::);
33     __asm__ volatile ("1:":::);
34 }
35 
mtime_lo(void)36 uint32_t mtime_lo(void)
37 {
38   return *(volatile uint32_t *)(TIMER_CTRL_ADDR + TIMER_MTIME);
39 }
40 
41 
mtime_hi(void)42 uint32_t mtime_hi(void)
43 {
44   return *(volatile uint32_t *)(TIMER_CTRL_ADDR + TIMER_MTIME + 4);
45 }
46 
get_timer_value(void)47 uint64_t get_timer_value(void)
48 {
49   while (1) {
50     uint32_t hi = mtime_hi();
51     uint32_t lo = mtime_lo();
52     if (hi == mtime_hi())
53       return ((uint64_t)hi << 32) | lo;
54   }
55 }
56 
get_timer_freq(void)57 uint32_t get_timer_freq(void)
58 {
59   return TIMER_FREQ;
60 }
61 
get_instret_value(void)62 uint64_t get_instret_value(void)
63 {
64   while (1) {
65 #if   defined (__ICCRISCV__)
66     uint32_t hi = read_csr(CSR_MINSTRETH);
67     uint32_t lo = read_csr(CSR_MINSTRETH);
68     if (hi == read_csr(CSR_MINSTRETH))
69 #elif defined ( __GNUC__ )
70     uint32_t hi = read_csr(minstreth);
71     uint32_t lo = read_csr(minstret);
72     if (hi == read_csr(minstreth))
73 #endif
74 
75       return ((uint64_t)hi << 32) | lo;
76   }
77 }
78 
get_cycle_value(void)79 uint64_t get_cycle_value(void)
80 {
81   while (1) {
82 #if   defined (__ICCRISCV__)
83     uint32_t hi = read_csr(CSR_MCYCLEH);
84     uint32_t lo = read_csr(CSR_MCYCLE);
85     if (hi == read_csr(CSR_MCYCLEH))
86 #elif defined ( __GNUC__ )
87     uint32_t hi = read_csr(mcycleh);
88     uint32_t lo = read_csr(mcycle);
89     if (hi == read_csr(mcycleh))
90 #endif
91 
92       return ((uint64_t)hi << 32) | lo;
93   }
94 }
95 
measure_cpu_freq(size_t n)96 uint32_t __attribute__((noinline)) measure_cpu_freq(size_t n)
97 {
98   uint32_t start_mtime, delta_mtime;
99   uint32_t mtime_freq = get_timer_freq();
100 
101   /* Don't start measuruing until we see an mtime tick */
102   uint32_t tmp = mtime_lo();
103   do {
104     start_mtime = mtime_lo();
105   } while (start_mtime == tmp);
106 
107 #if   defined (__ICCRISCV__)
108   uint32_t start_mcycle = read_csr(CSR_MCYCLE);
109 #elif defined ( __GNUC__ )
110   uint32_t start_mcycle = read_csr(mcycle);
111 #endif
112 
113   do {
114     delta_mtime = mtime_lo() - start_mtime;
115   } while (delta_mtime < n);
116 
117 #if   defined (__ICCRISCV__)
118   uint32_t delta_mcycle = read_csr(CSR_MCYCLE) - start_mcycle;
119 #elif defined ( __GNUC__ )
120   uint32_t delta_mcycle = read_csr(mcycle) - start_mcycle;
121 #endif
122 
123   return (delta_mcycle / delta_mtime) * mtime_freq
124          + ((delta_mcycle % delta_mtime) * mtime_freq) / delta_mtime;
125 }
126 
get_cpu_freq(void)127 uint32_t get_cpu_freq(void)
128 {
129   uint32_t cpu_freq;
130 
131   /* warm up */
132   measure_cpu_freq(1);
133   /* measure for real */
134   cpu_freq = measure_cpu_freq(100);
135 
136   return cpu_freq;
137 }
138 
139 /* Note that there are no assertions or bounds checking on these */
140 /* parameter values. */
eclic_init(uint32_t num_irq)141 void eclic_init ( uint32_t num_irq )
142 {
143 
144   typedef volatile uint32_t vuint32_t;
145 
146   /* clear cfg register */
147   *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_CFG_OFFSET)=0;
148 
149   /* clear minthresh register */
150   *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_MTH_OFFSET)=0;
151 
152   /* clear all IP/IE/ATTR/CTRL bits for all interrupt sources */
153   vuint32_t * ptr;
154 
155   vuint32_t * base = (vuint32_t*)(ECLIC_ADDR_BASE + ECLIC_INT_IP_OFFSET);
156   vuint32_t * upper = (vuint32_t*)(base + num_irq*4);
157 
158   for (ptr = base; ptr < upper; ptr=ptr+4){
159     *ptr = 0;
160   }
161 }
162 
eclic_enable_interrupt(uint32_t source)163 void eclic_enable_interrupt (uint32_t source) {
164     *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_IE_OFFSET+source*4) = 1;
165 }
166 
eclic_disable_interrupt(uint32_t source)167 void eclic_disable_interrupt (uint32_t source){
168     *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_IE_OFFSET+source*4) = 0;
169 }
170 
eclic_set_pending(uint32_t source)171 void eclic_set_pending(uint32_t source){
172     *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_IP_OFFSET+source*4) = 1;
173 }
174 
eclic_clear_pending(uint32_t source)175 void eclic_clear_pending(uint32_t source){
176     *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_IP_OFFSET+source*4) = 0;
177 }
178 
eclic_set_intctrl(uint32_t source,uint8_t intctrl)179 void eclic_set_intctrl (uint32_t source, uint8_t intctrl){
180   *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_CTRL_OFFSET+source*4) = intctrl;
181 }
182 
eclic_get_intctrl(uint32_t source)183 uint8_t eclic_get_intctrl  (uint32_t source){
184   return *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_CTRL_OFFSET+source*4);
185 }
186 
eclic_set_intattr(uint32_t source,uint8_t intattr)187 void eclic_set_intattr (uint32_t source, uint8_t intattr){
188   *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_ATTR_OFFSET+source*4) = intattr;
189 }
190 
eclic_get_intattr(uint32_t source)191 uint8_t eclic_get_intattr  (uint32_t source){
192   return *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_ATTR_OFFSET+source*4);
193 }
194 
eclic_set_cliccfg(uint8_t cliccfg)195 void eclic_set_cliccfg (uint8_t cliccfg){
196   *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_CFG_OFFSET) = cliccfg;
197 }
198 
eclic_get_cliccfg(void)199 uint8_t eclic_get_cliccfg (void){
200   return *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_CFG_OFFSET);
201 }
202 
eclic_set_mth(uint8_t mth)203 void eclic_set_mth (uint8_t mth){
204   *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_MTH_OFFSET) = mth;
205 }
206 
eclic_get_mth(void)207 uint8_t eclic_get_mth (void){
208   return *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_MTH_OFFSET);
209 }
210 
211 /* sets nlbits */
eclic_set_nlbits(uint8_t nlbits)212 void eclic_set_nlbits(uint8_t nlbits) {
213   /* shift nlbits to correct position */
214   uint8_t nlbits_shifted = nlbits << ECLIC_CFG_NLBITS_LSB;
215 
216   /* read the current cliccfg */
217   uint8_t old_cliccfg = eclic_get_cliccfg();
218   uint8_t new_cliccfg = (old_cliccfg & (~ECLIC_CFG_NLBITS_MASK)) | (ECLIC_CFG_NLBITS_MASK & nlbits_shifted);
219 
220   eclic_set_cliccfg(new_cliccfg);
221 }
222 
223 /* get nlbits */
eclic_get_nlbits(void)224 uint8_t eclic_get_nlbits(void) {
225   /* extract nlbits */
226   uint8_t nlbits = eclic_get_cliccfg();
227   nlbits = (nlbits & ECLIC_CFG_NLBITS_MASK) >> ECLIC_CFG_NLBITS_LSB;
228   return nlbits;
229 }
230 
231 /* sets an interrupt level based encoding of nlbits and ECLICINTCTLBITS */
eclic_set_irq_lvl(uint32_t source,uint8_t lvl)232 void eclic_set_irq_lvl(uint32_t source, uint8_t lvl) {
233   /* extract nlbits */
234   uint8_t nlbits = eclic_get_nlbits();
235   if (nlbits > ECLICINTCTLBITS) {
236     nlbits = ECLICINTCTLBITS;
237   }
238 
239   /* shift lvl right to mask off unused bits */
240   lvl = lvl >> (8-nlbits);
241   /* shift lvl into correct bit position */
242   lvl = lvl << (8-nlbits);
243 
244   /* write to clicintctrl */
245   uint8_t current_intctrl = eclic_get_intctrl(source);
246   /* shift intctrl left to mask off unused bits */
247   current_intctrl = current_intctrl << nlbits;
248   /* shift intctrl into correct bit position */
249   current_intctrl = current_intctrl >> nlbits;
250 
251   eclic_set_intctrl(source, (current_intctrl | lvl));
252 }
253 
254 /* gets an interrupt level based encoding of nlbits */
eclic_get_irq_lvl(uint32_t source)255 uint8_t eclic_get_irq_lvl(uint32_t source) {
256   /* extract nlbits */
257   uint8_t nlbits = eclic_get_nlbits();
258   if (nlbits > ECLICINTCTLBITS) {
259     nlbits = ECLICINTCTLBITS;
260   }
261 
262   uint8_t intctrl = eclic_get_intctrl(source);
263 
264   /* shift intctrl */
265   intctrl = intctrl >> (8-nlbits);
266   /* shift intctrl */
267   uint8_t lvl = intctrl << (8-nlbits);
268 
269   return lvl;
270 }
271 
eclic_set_irq_lvl_abs(uint32_t source,uint8_t lvl_abs)272 void eclic_set_irq_lvl_abs(uint32_t source, uint8_t lvl_abs) {
273   /* extract nlbits */
274   uint8_t nlbits = eclic_get_nlbits();
275   if (nlbits > ECLICINTCTLBITS) {
276     nlbits = ECLICINTCTLBITS;
277   }
278 
279   /* shift lvl_abs into correct bit position */
280   uint8_t lvl = lvl_abs << (8-nlbits);
281 
282   /* write to clicintctrl */
283   uint8_t current_intctrl = eclic_get_intctrl(source);
284   /* shift intctrl left to mask off unused bits */
285   current_intctrl = current_intctrl << nlbits;
286   /* shift intctrl into correct bit position */
287   current_intctrl = current_intctrl >> nlbits;
288 
289   eclic_set_intctrl(source, (current_intctrl | lvl));
290 }
291 
eclic_get_irq_lvl_abs(uint32_t source)292 uint8_t eclic_get_irq_lvl_abs(uint32_t source) {
293   /* extract nlbits */
294   uint8_t nlbits = eclic_get_nlbits();
295   if (nlbits > ECLICINTCTLBITS) {
296     nlbits = ECLICINTCTLBITS;
297   }
298 
299   uint8_t intctrl = eclic_get_intctrl(source);
300 
301   /* shift intctrl */
302   intctrl = intctrl >> (8-nlbits);
303   /* shift intctrl */
304   uint8_t lvl_abs = intctrl;
305 
306   return lvl_abs;
307 }
308 
309 /* sets an interrupt priority based encoding of nlbits and ECLICINTCTLBITS */
eclic_set_irq_priority(uint32_t source,uint8_t priority)310 uint8_t eclic_set_irq_priority(uint32_t source, uint8_t priority) {
311     /* extract nlbits */
312     uint8_t nlbits = eclic_get_nlbits();
313     if (nlbits >= ECLICINTCTLBITS) {
314         nlbits = ECLICINTCTLBITS;
315         return 0;
316     }
317 
318     /* shift priority into correct bit position */
319     priority = priority << (8 - ECLICINTCTLBITS);
320 
321     /* write to eclicintctrl */
322     uint8_t current_intctrl = eclic_get_intctrl(source);
323     /* shift intctrl right to mask off unused bits */
324     current_intctrl = current_intctrl >> (8-nlbits);
325     /* shift intctrl into correct bit position */
326     current_intctrl = current_intctrl << (8-nlbits);
327 
328     eclic_set_intctrl(source, (current_intctrl | priority));
329 
330     return priority;
331 }
332 
333 /* gets an interrupt priority based encoding of nlbits */
eclic_get_irq_priority(uint32_t source)334 uint8_t eclic_get_irq_priority(uint32_t source) {
335     /* extract nlbits */
336     uint8_t nlbits = eclic_get_nlbits();
337     if (nlbits > ECLICINTCTLBITS) {
338           nlbits = ECLICINTCTLBITS;
339     }
340 
341     uint8_t intctrl = eclic_get_intctrl(source);
342 
343     /* shift intctrl */
344     intctrl = intctrl << nlbits;
345     /* shift intctrl */
346     uint8_t priority = intctrl >> (nlbits+(8 - ECLICINTCTLBITS));
347 
348     return priority;
349 }
350 
eclic_mode_enable()351 void eclic_mode_enable() {
352 #if   defined (__ICCRISCV__)
353   uint32_t mtvec_value = read_csr(CSR_MTVEC);
354   mtvec_value = mtvec_value & 0xFFFFFFC0;
355   mtvec_value = mtvec_value | 0x00000003;
356   write_csr(CSR_MTVEC,mtvec_value);
357 #elif defined ( __GNUC__ )
358   uint32_t mtvec_value = read_csr(mtvec);
359   mtvec_value = mtvec_value & 0xFFFFFFC0;
360   mtvec_value = mtvec_value | 0x00000003;
361   write_csr(mtvec,mtvec_value);
362 #endif
363 
364 }
365 
366 /* sets vector-mode or non-vector mode */
eclic_set_vmode(uint32_t source)367 void eclic_set_vmode(uint32_t source) {
368   /* read the current attr */
369   uint8_t old_intattr = eclic_get_intattr(source);
370       /*  Keep other bits unchanged and only set the LSB bit */
371   uint8_t new_intattr = (old_intattr | 0x1);
372 
373   eclic_set_intattr(source,new_intattr);
374 }
375 
eclic_set_nonvmode(uint32_t source)376 void eclic_set_nonvmode(uint32_t source) {
377   /* read the current attr */
378   uint8_t old_intattr = eclic_get_intattr(source);
379       /* Keep other bits unchanged and only clear the LSB bit*/
380   uint8_t new_intattr = (old_intattr & (~0x1));
381 
382   eclic_set_intattr(source,new_intattr);
383 }
384 
385 /* sets interrupt as level sensitive
386 Bit 1, trig[0], is defined as "edge-triggered" (0: level-triggered, 1: edge-triggered);
387 Bit 2, trig[1], is defined as "negative-edge" (0: positive-edge, 1: negative-edge).*/
388 
eclic_set_level_trig(uint32_t source)389 void eclic_set_level_trig(uint32_t source) {
390   /* read the current attr */
391   uint8_t old_intattr = eclic_get_intattr(source);
392       /* Keep other bits unchanged and only clear the bit 1 */
393   uint8_t new_intattr = (old_intattr & (~0x2));
394 
395   eclic_set_intattr(source,new_intattr);
396 }
397 
eclic_set_posedge_trig(uint32_t source)398 void eclic_set_posedge_trig(uint32_t source) {
399   /* read the current attr */
400   uint8_t old_intattr = eclic_get_intattr(source);
401       /* Keep other bits unchanged and only set the bit 1 */
402   uint8_t new_intattr = (old_intattr | 0x2);
403       /* Keep other bits unchanged and only clear the bit 2 */
404   new_intattr = (old_intattr & (~0x4));
405 
406   eclic_set_intattr(source,new_intattr);
407 }
408 
eclic_set_negedge_trig(uint32_t source)409 void eclic_set_negedge_trig(uint32_t source) {
410   /*read the current attr */
411   uint8_t old_intattr = eclic_get_intattr(source);
412       /* Keep other bits unchanged and only set the bit 1*/
413   uint8_t new_intattr = (old_intattr | 0x2);
414       /* Keep other bits unchanged and only set the bit 2*/
415   new_intattr = (old_intattr | 0x4);
416 
417   eclic_set_intattr(source,new_intattr);
418 }
419