NMSIS-Core  Version 1.3.1
NMSIS-Core support for Nuclei processor-based devices
system_Device.c
1 /*
2  * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
3  * Copyright (c) 2019 Nuclei Limited. All rights reserved.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  *
7  * Licensed under the Apache License, Version 2.0 (the License); you may
8  * not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
15  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 /******************************************************************************
20  * @file system_<Device>.c
21  * @brief NMSIS Nuclei N/NX Device Peripheral Access Layer Source File for
22  * Device <Device>
23  * @version V2.0.0
24  * @date 30. Dec 2022
25  ******************************************************************************/
26 
27 #include <stdint.h>
28 #include "<Device>.h"
29 #include <stdio.h>
30 
31 /*----------------------------------------------------------------------------
32  Define clocks
33  *----------------------------------------------------------------------------*/
34 /* ToDo: add here your necessary defines for device initialization
35  following is an example for different system frequencies */
36 #ifndef SYSTEM_CLOCK
37 #define SYSTEM_CLOCK (80000000UL)
38 #endif
39 
72 #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
73 
74 typedef void (*fnptr)(void);
75 
76 /* for the following variables, see intexc_evalsoc.S and intexc_evalsoc_s.S */
78 extern fnptr irq_entry_s;
80 extern fnptr exc_entry_s;
82 extern void default_intexc_handler(void);
83 
85 extern void eclic_ssip_handler(void) __WEAK;
87 extern void eclic_stip_handler(void) __WEAK;
88 
89 /* default s-mode exception handler, which user can modify it at your need */
90 static void system_default_exception_handler_s(unsigned long scause, unsigned long sp);
91 
92 #ifndef __ICCRISCV__
93 #define __SMODE_VECTOR_ATTR __attribute__((section (".text.vtable_s"), aligned(512)))
94 #else
95 #define __SMODE_VECTOR_ATTR __attribute__((section (".sintvec"), aligned(512)))
96 #endif
97 // TODO: change the aligned(512) to match stvt alignment requirement according to your eclic max interrupt number
98 // TODO: place your interrupt handler into this vector table, important if your vector table is in flash
115 const unsigned long vector_table_s[SOC_INT_MAX] __SMODE_VECTOR_ATTR =
116 {
117  (unsigned long)(default_intexc_handler), /* 0: Reserved */
118  (unsigned long)(default_intexc_handler), /* 1: Reserved */
119  (unsigned long)(default_intexc_handler), /* 2: Reserved */
120 
121  (unsigned long)(eclic_ssip_handler), /* 3: supervisor software interrupt in eclic mode */
122 
123  (unsigned long)(default_intexc_handler), /* 4: Reserved */
124  (unsigned long)(default_intexc_handler), /* 5: Reserved */
125  (unsigned long)(default_intexc_handler), /* 6: Reserved */
126 
127  (unsigned long)(eclic_stip_handler), /* 7: supervisor timer interrupt in eclic mode */
128 
129  (unsigned long)(default_intexc_handler), /* 8: Reserved */
130  (unsigned long)(default_intexc_handler), /* 9: Reserved */
131  (unsigned long)(default_intexc_handler), /* 10: Reserved */
132  (unsigned long)(default_intexc_handler), /* 11: Reserved */
133 
134  (unsigned long)(default_intexc_handler), /* 12: Reserved */
135  (unsigned long)(default_intexc_handler), /* 13: Reserved */
136  (unsigned long)(default_intexc_handler), /* 14: Reserved */
137  (unsigned long)(default_intexc_handler), /* 15: Reserved */
138 
139  (unsigned long)(default_intexc_handler), /* 16: Reserved */
140  (unsigned long)(default_intexc_handler), /* 17: Reserved */
141  (unsigned long)(default_intexc_handler), /* 18: Reserved */
142  (unsigned long)(default_intexc_handler), /* 19: Interrupt 19 */
143 
144  (unsigned long)(default_intexc_handler), /* 20: Interrupt 20 */
145  (unsigned long)(default_intexc_handler), /* 21: Interrupt 21 */
146  (unsigned long)(default_intexc_handler), /* 22: Interrupt 22 */
147  (unsigned long)(default_intexc_handler), /* 23: Interrupt 23 */
148 
149  (unsigned long)(default_intexc_handler), /* 24: Interrupt 24 */
150  (unsigned long)(default_intexc_handler), /* 25: Interrupt 25 */
151  (unsigned long)(default_intexc_handler), /* 26: Interrupt 26 */
152  (unsigned long)(default_intexc_handler), /* 27: Interrupt 27 */
153 
154  (unsigned long)(default_intexc_handler), /* 28: Interrupt 28 */
155  (unsigned long)(default_intexc_handler), /* 29: Interrupt 29 */
156  (unsigned long)(default_intexc_handler), /* 30: Interrupt 30 */
157  (unsigned long)(default_intexc_handler), /* 31: Interrupt 31 */
158 
159  (unsigned long)(default_intexc_handler), /* 32: Interrupt 32 */
160  (unsigned long)(default_intexc_handler), /* 33: Interrupt 33 */
161  (unsigned long)(default_intexc_handler), /* 34: Interrupt 34 */
162  (unsigned long)(default_intexc_handler), /* 35: Interrupt 35 */
163 
164  (unsigned long)(default_intexc_handler), /* 36: Interrupt 36 */
165  (unsigned long)(default_intexc_handler), /* 37: Interrupt 37 */
166  (unsigned long)(default_intexc_handler), /* 38: Interrupt 38 */
167  (unsigned long)(default_intexc_handler), /* 39: Interrupt 39 */
168 
169  (unsigned long)(default_intexc_handler), /* 40: Interrupt 40 */
170  (unsigned long)(default_intexc_handler), /* 41: Interrupt 41 */
171  (unsigned long)(default_intexc_handler), /* 42: Interrupt 42 */
172  (unsigned long)(default_intexc_handler), /* 43: Interrupt 43 */
173 
174  (unsigned long)(default_intexc_handler), /* 44: Interrupt 44 */
175  (unsigned long)(default_intexc_handler), /* 45: Interrupt 45 */
176  (unsigned long)(default_intexc_handler), /* 46: Interrupt 46 */
177  (unsigned long)(default_intexc_handler), /* 47: Interrupt 47 */
178 
179  (unsigned long)(default_intexc_handler), /* 48: Interrupt 48 */
180  (unsigned long)(default_intexc_handler), /* 49: Interrupt 49 */
181  (unsigned long)(default_intexc_handler), /* 50: Interrupt 50 */
182  (unsigned long)(default_intexc_handler), /* 51: Interrupt 51 */
183 
184  (unsigned long)(default_intexc_handler), /* 52: Interrupt 52 */
185  (unsigned long)(default_intexc_handler), /* 53: Interrupt 53 */
186  (unsigned long)(default_intexc_handler), /* 54: Interrupt 54 */
187  (unsigned long)(default_intexc_handler), /* 55: Interrupt 55 */
188 
189  (unsigned long)(default_intexc_handler), /* 56: Interrupt 56 */
190  (unsigned long)(default_intexc_handler), /* 57: Interrupt 57 */
191  (unsigned long)(default_intexc_handler), /* 58: Interrupt 58 */
192  (unsigned long)(default_intexc_handler), /* 59: Interrupt 59 */
193 
194  (unsigned long)(default_intexc_handler), /* 60: Interrupt 60 */
195  (unsigned long)(default_intexc_handler), /* 61: Interrupt 61 */
196  (unsigned long)(default_intexc_handler), /* 62: Interrupt 62 */
197  (unsigned long)(default_intexc_handler), /* 63: Interrupt 63 */
198 };
199 #endif
200 /*----------------------------------------------------------------------------
201  System Core Clock Variable
202  *----------------------------------------------------------------------------*/
203 /* ToDo: initialize SystemCoreClock with the system core clock frequency value
204  achieved after system intitialization.
205  This means system core clock frequency after call to SystemInit() */
218 volatile uint32_t SystemCoreClock = SYSTEM_CLOCK; /* System Clock Frequency (Core Clock) */
219 
220 /*----------------------------------------------------------------------------
221  Clock functions
222  *----------------------------------------------------------------------------*/
223 
231 void SystemCoreClockUpdate(void) /* Get Core Clock Frequency */
232 {
233  /* ToDo: add code to calculate the system frequency based upon the current
234  * register settings.
235  * Note: This function can be used to retrieve the system core clock frequeny
236  * after user changed register settings.
237  */
238  SystemCoreClock = SYSTEM_CLOCK;
239 }
240 
249 void SystemInit(void)
250 {
251  /* ToDo: add code to initialize the system
252  * Warn: do not use global variables because this function is called before
253  * reaching pre-main. RW section maybe overwritten afterwards.
254  */
255  SystemCoreClock = SYSTEM_CLOCK;
256 }
257 
269 #define MAX_SYSTEM_EXCEPTION_NUM 26
278 static unsigned long SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM + 1];
279 
288 #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
289 static unsigned long SystemExceptionHandlers_S[MAX_SYSTEM_EXCEPTION_NUM];
290 #endif
297 typedef void (*EXC_HANDLER)(unsigned long cause, unsigned long sp);
298 
307 static void system_default_exception_handler(unsigned long mcause, unsigned long sp)
308 {
309  /* TODO: Uncomment this if you have implement printf function */
310  printf("MCAUSE : 0x%lx\r\n", mcause);
311  printf("MDCAUSE: 0x%lx\r\n", __RV_CSR_READ(CSR_MDCAUSE));
312  printf("MEPC : 0x%lx\r\n", __RV_CSR_READ(CSR_MEPC));
313  printf("MTVAL : 0x%lx\r\n", __RV_CSR_READ(CSR_MTVAL));
314  printf("HARTID : %u\r\n", (unsigned int)__get_hart_id());
315  Exception_DumpFrame(sp, PRV_M);
316 #if defined(SIMULATION_MODE)
317  // directly exit if in SIMULATION
318  extern void simulation_exit(int status);
319  simulation_exit(1);
320 #else
321  while (1);
322 #endif
323 }
324 
333 static void Exception_Init(void)
334 {
335  for (int i = 0; i < MAX_SYSTEM_EXCEPTION_NUM; i++) {
336  SystemExceptionHandlers[i] = (unsigned long)system_default_exception_handler;
337 #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
338  SystemExceptionHandlers_S[i] = (unsigned long)system_default_exception_handler_s;
339 #endif
340  }
341  SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM] = (unsigned long)system_default_exception_handler;
342 }
343 
351 void Exception_DumpFrame(unsigned long sp, uint8_t mode)
352 {
353  EXC_Frame_Type *exc_frame = (EXC_Frame_Type *)sp;
354 
355 #ifndef __riscv_32e
356  printf("ra: 0x%lx, tp: 0x%lx, t0: 0x%lx, t1: 0x%lx, t2: 0x%lx, t3: 0x%lx, t4: 0x%lx, t5: 0x%lx, t6: 0x%lx\n" \
357  "a0: 0x%lx, a1: 0x%lx, a2: 0x%lx, a3: 0x%lx, a4: 0x%lx, a5: 0x%lx, a6: 0x%lx, a7: 0x%lx\n" \
358  "cause: 0x%lx, epc: 0x%lx\n", exc_frame->ra, exc_frame->tp, exc_frame->t0, \
359  exc_frame->t1, exc_frame->t2, exc_frame->t3, exc_frame->t4, exc_frame->t5, exc_frame->t6, \
360  exc_frame->a0, exc_frame->a1, exc_frame->a2, exc_frame->a3, exc_frame->a4, exc_frame->a5, \
361  exc_frame->a6, exc_frame->a7, exc_frame->cause, exc_frame->epc);
362 #else
363  printf("ra: 0x%lx, tp: 0x%lx, t0: 0x%lx, t1: 0x%lx, t2: 0x%lx\n" \
364  "a0: 0x%lx, a1: 0x%lx, a2: 0x%lx, a3: 0x%lx, a4: 0x%lx, a5: 0x%lx\n" \
365  "cause: 0x%lx, epc: 0x%lx\n", exc_frame->ra, exc_frame->tp, exc_frame->t0, \
366  exc_frame->t1, exc_frame->t2, exc_frame->a0, exc_frame->a1, exc_frame->a2, exc_frame->a3, \
367  exc_frame->a4, exc_frame->a5, exc_frame->cause, exc_frame->epc);
368 #endif
369 
370  if (PRV_M == mode) {
371  /* msubm is exclusive to machine mode */
372  printf("msubm: 0x%lx\n", exc_frame->msubm);
373  }
374 }
375 
384 void Exception_Register_EXC(uint32_t EXCn, unsigned long exc_handler)
385 {
386  if (EXCn < MAX_SYSTEM_EXCEPTION_NUM) {
387  SystemExceptionHandlers[EXCn] = exc_handler;
388  } else if (EXCn == NMI_EXCn) {
389  SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM] = exc_handler;
390  }
391 }
392 
401 unsigned long Exception_Get_EXC(uint32_t EXCn)
402 {
403  if (EXCn < MAX_SYSTEM_EXCEPTION_NUM) {
404  return SystemExceptionHandlers[EXCn];
405  } else if (EXCn == NMI_EXCn) {
406  return SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM];
407  } else {
408  return 0;
409  }
410 }
411 
425 uint32_t core_exception_handler(unsigned long mcause, unsigned long sp)
426 {
427  uint32_t EXCn = (uint32_t)(mcause & 0X00000fff);
428  EXC_HANDLER exc_handler;
429 
430  if (EXCn < MAX_SYSTEM_EXCEPTION_NUM) {
431  exc_handler = (EXC_HANDLER)SystemExceptionHandlers[EXCn];
432  } else if (EXCn == NMI_EXCn) {
433  exc_handler = (EXC_HANDLER)SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM];
434  } else {
435  exc_handler = (EXC_HANDLER)system_default_exception_handler;
436  }
437  if (exc_handler != NULL) {
438  exc_handler(mcause, sp);
439  }
440  return 0;
441 }
442 
443 #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
452 static void system_default_exception_handler_s(unsigned long scause, unsigned long sp)
453 {
454  /* TODO: Uncomment this if you have implement printf function */
455  printf("SCAUSE : 0x%lx\r\n", scause);
456  printf("SDCAUSE: 0x%lx\r\n", __RV_CSR_READ(CSR_SDCAUSE));
457  printf("SEPC : 0x%lx\r\n", __RV_CSR_READ(CSR_SEPC));
458  printf("STVAL : 0x%lx\r\n", __RV_CSR_READ(CSR_STVAL));
459  Exception_DumpFrame(sp, PRV_S);
460 #if defined(SIMULATION_MODE)
461  // directly exit if in SIMULATION
462  extern void simulation_exit(int status);
463  simulation_exit(1);
464 #else
465  while (1);
466 #endif
467 }
468 
478 void Exception_Register_EXC_S(uint32_t EXCn, unsigned long exc_handler)
479 {
480  if (EXCn < MAX_SYSTEM_EXCEPTION_NUM) {
481  SystemExceptionHandlers_S[EXCn] = exc_handler;
482  }
483 }
484 
492 unsigned long Exception_Get_EXC_S(uint32_t EXCn)
493 {
494  if (EXCn < MAX_SYSTEM_EXCEPTION_NUM) {
495  return SystemExceptionHandlers[EXCn];
496  } else {
497  return 0;
498  }
499 }
500 
514 uint32_t core_exception_handler_s(unsigned long scause, unsigned long sp)
515 {
516  uint32_t EXCn = (uint32_t)(scause & 0X00000fff);
517  EXC_HANDLER exc_handler;
518 
519  if (EXCn < MAX_SYSTEM_EXCEPTION_NUM) {
520  exc_handler = (EXC_HANDLER)SystemExceptionHandlers_S[EXCn];
521  } else {
522  exc_handler = (EXC_HANDLER)system_default_exception_handler_s;
523  }
524  if (exc_handler != NULL) {
525  exc_handler(scause, sp);
526  }
527  return 0;
528 }
529 #endif
530  /* End of Doxygen Group NMSIS_Core_ExceptionAndNMI */
532 
534 void SystemBannerPrint(void)
535 {
536 #if defined(NUCLEI_BANNER) && (NUCLEI_BANNER == 1)
537  printf("Nuclei SDK Build Time: %s, %s\r\n", __DATE__, __TIME__);
538 #ifdef DOWNLOAD_MODE_STRING
539  printf("Download Mode: %s\r\n", DOWNLOAD_MODE_STRING);
540 #endif
541  printf("CPU Frequency %u Hz\r\n", (unsigned int)SystemCoreClock);
542  printf("CPU HartID: %u\r\n", (unsigned int)__get_hart_id());
543 #endif
544 }
545 
553 void ECLIC_Init(void)
554 {
555  /* Global Configuration about MTH and NLBits.
556  * TODO: Please adapt it according to your system requirement.
557  * This function is called in _init function */
558  ECLIC_SetMth(0);
559  ECLIC_SetCfgNlbits(__ECLIC_INTCTLBITS);
560 
561 #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
562  /* Global Configuration about STH */
563  ECLIC_SetSth(0);
564 #endif
565 }
566 
583 int32_t ECLIC_Register_IRQ(IRQn_Type IRQn, uint8_t shv, ECLIC_TRIGGER_Type trig_mode, uint8_t lvl, uint8_t priority, void* handler)
584 {
585  if ((IRQn > SOC_INT_MAX) || (shv > ECLIC_VECTOR_INTERRUPT) \
586  || (trig_mode > ECLIC_NEGTIVE_EDGE_TRIGGER)) {
587  return -1;
588  }
589 
590  /* set interrupt vector mode */
591  ECLIC_SetShvIRQ(IRQn, shv);
592  /* set interrupt trigger mode and polarity */
593  ECLIC_SetTrigIRQ(IRQn, trig_mode);
594  /* set interrupt level */
595  ECLIC_SetLevelIRQ(IRQn, lvl);
596  /* set interrupt priority */
597  ECLIC_SetPriorityIRQ(IRQn, priority);
598  if (handler != NULL) {
599  /* set interrupt handler entry to vector table */
600  ECLIC_SetVector(IRQn, (rv_csr_t)handler);
601  }
602  /* enable interrupt */
603  ECLIC_EnableIRQ(IRQn);
604  return 0;
605 }
606 
607 #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
624 int32_t ECLIC_Register_IRQ_S(IRQn_Type IRQn, uint8_t shv, ECLIC_TRIGGER_Type trig_mode, uint8_t lvl, uint8_t priority, void* handler)
625 {
626  if ((IRQn > SOC_INT_MAX) || (shv > ECLIC_VECTOR_INTERRUPT) \
627  || (trig_mode > ECLIC_NEGTIVE_EDGE_TRIGGER)) {
628  return -1;
629  }
630 
631  /* set interrupt vector mode */
632  ECLIC_SetShvIRQ_S(IRQn, shv);
633  /* set interrupt trigger mode and polarity */
634  ECLIC_SetTrigIRQ_S(IRQn, trig_mode);
635  /* set interrupt level */
636  ECLIC_SetLevelIRQ_S(IRQn, lvl);
637  /* set interrupt priority */
638  ECLIC_SetPriorityIRQ_S(IRQn, priority);
639  if (handler != NULL) {
640  /* set interrupt handler entry to vector table */
641  ECLIC_SetVector_S(IRQn, (rv_csr_t)handler);
642  }
643  /* enable interrupt */
644  ECLIC_EnableIRQ_S(IRQn);
645  return 0;
646 }
647 #endif
648 
649 #define FALLBACK_DEFAULT_ECLIC_BASE 0x0C000000UL
650 #define FALLBACK_DEFAULT_SYSTIMER_BASE 0x02000000UL
651 
653 volatile IRegion_Info_Type SystemIRegionInfo;
662 static void _get_iregion_info(IRegion_Info_Type *iregion)
663 {
664  unsigned long mcfg_info;
665  if (iregion == NULL) {
666  return;
667  }
668  mcfg_info = __RV_CSR_READ(CSR_MCFG_INFO);
669  if (mcfg_info & MCFG_INFO_IREGION_EXIST) { // IRegion Info present
670  iregion->iregion_base = (__RV_CSR_READ(CSR_MIRGB_INFO) >> 10) << 10;
671  iregion->eclic_base = iregion->iregion_base + IREGION_ECLIC_OFS;
672  iregion->systimer_base = iregion->iregion_base + IREGION_TIMER_OFS;
673  iregion->smp_base = iregion->iregion_base + IREGION_SMP_OFS;
674  iregion->idu_base = iregion->iregion_base + IREGION_IDU_OFS;
675  } else {
676  iregion->eclic_base = FALLBACK_DEFAULT_ECLIC_BASE;
677  iregion->systimer_base = FALLBACK_DEFAULT_SYSTIMER_BASE;
678  }
679 }
680 
681 #define CLINT_MSIP(base, hartid) (*(volatile uint32_t *)((uintptr_t)((base) + ((hartid) * 4))))
682 #define SMP_CTRLREG(base, ofs) (*(volatile uint32_t *)((uintptr_t)((base) + (ofs))))
683 
684 void __sync_harts(void) __attribute__((section(".text.init")));
696 void __sync_harts(void)
697 {
698 // Only do synchronize when SMP_CPU_CNT is defined and number > 0
699 #if defined(SMP_CPU_CNT) && (SMP_CPU_CNT > 1)
700  unsigned long hartid = __get_hart_id();
701  unsigned long tmr_hartid = __get_hart_index();
702  unsigned long clint_base, irgb_base, smp_base;
703  unsigned long mcfg_info;
704 
705  mcfg_info = __RV_CSR_READ(CSR_MCFG_INFO);
706  if (mcfg_info & MCFG_INFO_IREGION_EXIST) { // IRegion Info present
707  // clint base = system timer base + 0x1000
708  irgb_base = (__RV_CSR_READ(CSR_MIRGB_INFO) >> 10) << 10;
709  clint_base = irgb_base + IREGION_TIMER_OFS + 0x1000;
710  smp_base = irgb_base + IREGION_SMP_OFS;
711  } else {
712  clint_base = FALLBACK_DEFAULT_SYSTIMER_BASE + 0x1000;
713  smp_base = (__RV_CSR_READ(CSR_MSMPCFG_INFO) >> 4) << 4;
714  }
715  // Enable SMP and L2, disable cluster local memory
716  SMP_CTRLREG(smp_base, 0xc) = 0xFFFFFFFF;
717  SMP_CTRLREG(smp_base, 0x10) = 0x1;
718  SMP_CTRLREG(smp_base, 0xd8) = 0x0;
719  __SMP_RWMB();
720 
721  // pre-condition: interrupt must be disabled, this is done before calling this function
722  // BOOT_HARTID is defined <Device.h>
723  if (hartid == BOOT_HARTID) { // boot hart
724  // clear msip pending
725  for (int i = 0; i < SMP_CPU_CNT; i ++) {
726  CLINT_MSIP(clint_base, i) = 0;
727  }
728  __SMP_RWMB();
729  } else {
730  // Set machine software interrupt pending to 1
731  CLINT_MSIP(clint_base, tmr_hartid) = 1;
732  __SMP_RWMB();
733  // wait for pending bit cleared by boot hart
734  while (CLINT_MSIP(clint_base, tmr_hartid) == 1);
735  }
736 #endif
737 }
738 
744 static void Trap_Init(void)
745 {
746 #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
747  /*
748  * Intialize ECLIC supervisor mode vector interrupt
749  * base address stvt to vector_table_s
750  */
751  __RV_CSR_WRITE(CSR_STVT, (unsigned long)&vector_table_s);
752  /*
753  * Set ECLIC supervisor mode non-vector entry to be controlled
754  * by stvt2 CSR register.
755  * Intialize supervisor mode ECLIC non-vector interrupt
756  * base address stvt2 to irq_entry_s.
757  */
758  __RV_CSR_WRITE(CSR_STVT2, (unsigned long)&irq_entry_s);
759  __RV_CSR_SET(CSR_STVT2, 0x01);
760  /*
761  * Set supervisor exception entry stvec to exc_entry_s */
762  __RV_CSR_WRITE(CSR_STVEC, (unsigned long)&exc_entry_s);
763 #endif
764 }
765 
774 void _premain_init(void)
775 {
776  // TODO to make it possible for configurable boot hartid
777  unsigned long hartid = __get_hart_id();
778 
779  // BOOT_HARTID is defined <Device.h>
780  if (hartid == BOOT_HARTID) { // only done in boot hart
781  // IREGION INFO MUST BE SET BEFORE ANY PREMAIN INIT STEPS
782  _get_iregion_info((IRegion_Info_Type *)(&SystemIRegionInfo));
783  }
784  /* TODO: Add your own initialization code here, called before main */
785  // This code located in RUNMODE_CONTROL ifdef endif block just for internal usage
786  // No need to use in your code
787 #ifdef RUNMODE_CONTROL
788 #if defined(RUNMODE_ILM_EN) && RUNMODE_ILM_EN == 0
789  // Only disable ilm when it is present
790  if (__RV_CSR_READ(CSR_MCFG_INFO) & MCFG_INFO_ILM) {
791  __RV_CSR_CLEAR(CSR_MILM_CTL, MILM_CTL_ILM_EN);
792  }
793 #endif
794 #if defined(RUNMODE_DLM_EN) && RUNMODE_DLM_EN == 0
795  // Only disable dlm when it is present
796  if (__RV_CSR_READ(CSR_MCFG_INFO) & MCFG_INFO_DLM) {
797  __RV_CSR_CLEAR(CSR_MDLM_CTL, MDLM_CTL_DLM_EN);
798  }
799 #endif
800 #endif
801 
802  /* __ICACHE_PRESENT and __DCACHE_PRESENT are defined in demosoc.h */
803  // For our internal cpu testing, they want to set demosoc __ICACHE_PRESENT/__DCACHE_PRESENT to be 1
804  // __CCM_PRESENT is still default to 0 in demosoc.h, since it is used in core_feature_eclic.h to register interrupt, if set to 1, it might cause exception
805  // but in the cpu, icache or dcache might not exist due to cpu configuration, so here
806  // we need to check whether icache/dcache really exist, if yes, then turn on it
807 #if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1)
808  if (ICachePresent()) { // Check whether icache real present or not
809  EnableICache();
810  }
811 #endif
812 #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1)
813  if (DCachePresent()) { // Check whether dcache real present or not
814  EnableDCache();
815  }
816 #endif
817 
818  /* Do fence and fence.i to make sure previous ilm/dlm/icache/dcache control done */
819  __RWMB();
820  __FENCE_I();
821 
822  if (hartid == BOOT_HARTID) { // only required for boot hartid
823  // TODO implement get_cpu_freq function to get real cpu clock freq in HZ or directly give the real cpu HZ
824  SystemCoreClock = get_cpu_freq();
825  uart_init(SOC_DEBUG_UART, 115200);
826  /* Display banner after UART initialized */
827  SystemBannerPrint();
828  /* Initialize exception default handlers */
829  Exception_Init();
830  /* ECLIC initialization, mainly MTH and NLBIT */
831  ECLIC_Init();
832  Trap_Init();
833  // TODO: internal usage for Nuclei
834 #ifdef RUNMODE_CONTROL
835  printf("Current RUNMODE=%s, ilm:%d, dlm %d, icache %d, dcache %d, ccm %d\n", \
836  RUNMODE_STRING, RUNMODE_ILM_EN, RUNMODE_DLM_EN, \
837  RUNMODE_IC_EN, RUNMODE_DC_EN, RUNMODE_CCM_EN);
838  printf("CSR: MILM_CTL 0x%x, MDLM_CTL 0x%x, MCACHE_CTL 0x%x\n", \
839  __RV_CSR_READ(CSR_MILM_CTL), __RV_CSR_READ(CSR_MDLM_CTL), \
840  __RV_CSR_READ(CSR_MCACHE_CTL));
841 #endif
842  }
843 }
844 
854 void _postmain_fini(int status)
855 {
856  /* TODO: Add your own finishing code here, called after main */
857  extern void simulation_exit(int status);
858  simulation_exit(status);
859 }
860 
870 void _init(void)
871 {
872  /* Don't put any code here, please use _premain_init now */
873 }
874 
884 void _fini(void)
885 {
886  /* Don't put any code here, please use _postmain_fini now */
887 }
888  /* End of Doxygen Group NMSIS_Core_SystemConfig */