startup_evalsoc.S 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. /*
  2. * Copyright (c) 2019 Nuclei Limited. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the License); you may
  7. * not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  14. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. /******************************************************************************
  19. * \file startup_evalsoc.S
  20. * \brief NMSIS Nuclei N/NX Class Core based Core Device Startup File for
  21. * Nuclei Eval SoC which support Nuclei N/NX class cores
  22. * \version V1.00
  23. * \date 17. Dec 2019
  24. *
  25. ******************************************************************************/
  26. /* Please check the TODO items */
  27. #include "riscv_encoding.h"
  28. /* TODO: Require Nuclei SDK >= 0.6.0, which introduced this cpufeature.h */
  29. #include "cpufeature.h"
  30. /* If BOOT_HARTID is not defined, default value is 0 */
  31. #ifndef BOOT_HARTID
  32. .equ BOOT_HARTID, 0
  33. #endif
  34. .macro DECLARE_INT_HANDLER INT_HDL_NAME
  35. #if defined(__riscv_xlen) && (__riscv_xlen == 32)
  36. .word \INT_HDL_NAME
  37. #else
  38. .dword \INT_HDL_NAME
  39. #endif
  40. .endm
  41. #ifdef CFG_HAS_CLIC
  42. .section .text.vtable
  43. .weak eclic_msip_handler
  44. .weak eclic_mtip_handler
  45. .weak eclic_uart0_int_handler
  46. .weak eclic_inter_core_int_handler
  47. .globl vector_base
  48. .type vector_base, @object
  49. .option push
  50. .option norelax
  51. vector_base:
  52. #ifndef VECTOR_TABLE_REMAPPED
  53. j _start /* 0: Reserved, Jump to _start when reset for vector table not remapped cases.*/
  54. .align LOG_REGBYTES /* Need to align 4 byte for RV32, 8 Byte for RV64 */
  55. #else
  56. DECLARE_INT_HANDLER default_intexc_handler /* 0: Reserved, default handler for vector table remapped cases */
  57. #endif
  58. DECLARE_INT_HANDLER default_intexc_handler /* 1: Reserved */
  59. DECLARE_INT_HANDLER default_intexc_handler /* 2: Reserved */
  60. DECLARE_INT_HANDLER eclic_msip_handler /* 3: Machine software interrupt */
  61. DECLARE_INT_HANDLER default_intexc_handler /* 4: Reserved */
  62. DECLARE_INT_HANDLER default_intexc_handler /* 5: Reserved */
  63. DECLARE_INT_HANDLER default_intexc_handler /* 6: Reserved */
  64. DECLARE_INT_HANDLER eclic_mtip_handler /* 7: Machine timer interrupt */
  65. DECLARE_INT_HANDLER default_intexc_handler /* 8: Reserved */
  66. DECLARE_INT_HANDLER default_intexc_handler /* 9: Reserved */
  67. DECLARE_INT_HANDLER default_intexc_handler /* 10: Reserved */
  68. DECLARE_INT_HANDLER default_intexc_handler /* 11: Reserved */
  69. DECLARE_INT_HANDLER default_intexc_handler /* 12: Reserved */
  70. DECLARE_INT_HANDLER default_intexc_handler /* 13: Reserved */
  71. DECLARE_INT_HANDLER default_intexc_handler /* 14: Reserved */
  72. DECLARE_INT_HANDLER default_intexc_handler /* 15: Reserved */
  73. DECLARE_INT_HANDLER eclic_inter_core_int_handler /* 16: Reserved */
  74. DECLARE_INT_HANDLER default_intexc_handler /* 17: Reserved */
  75. DECLARE_INT_HANDLER default_intexc_handler /* 18: Reserved */
  76. /* TODO Below are external interrupt handlers, please define them as your requirements, you need to increase or decrease it, and define correct interrupt handler name */
  77. DECLARE_INT_HANDLER default_intexc_handler /* 19: Interrupt 19 */
  78. DECLARE_INT_HANDLER default_intexc_handler /* 20: Interrupt 20 */
  79. DECLARE_INT_HANDLER default_intexc_handler /* 21: Interrupt 21 */
  80. DECLARE_INT_HANDLER default_intexc_handler /* 22: Interrupt 22 */
  81. DECLARE_INT_HANDLER default_intexc_handler /* 23: Interrupt 23 */
  82. DECLARE_INT_HANDLER default_intexc_handler /* 24: Interrupt 24 */
  83. DECLARE_INT_HANDLER default_intexc_handler /* 25: Interrupt 25 */
  84. DECLARE_INT_HANDLER default_intexc_handler /* 26: Interrupt 26 */
  85. DECLARE_INT_HANDLER default_intexc_handler /* 27: Interrupt 27 */
  86. DECLARE_INT_HANDLER default_intexc_handler /* 28: Interrupt 28 */
  87. DECLARE_INT_HANDLER default_intexc_handler /* 29: Interrupt 29 */
  88. DECLARE_INT_HANDLER default_intexc_handler /* 30: Interrupt 30 */
  89. DECLARE_INT_HANDLER default_intexc_handler /* 31: Interrupt 31 */
  90. DECLARE_INT_HANDLER default_intexc_handler /* 32: Interrupt 32 */
  91. DECLARE_INT_HANDLER default_intexc_handler /* 33: Interrupt 33 */
  92. DECLARE_INT_HANDLER default_intexc_handler /* 34: Interrupt 34 */
  93. DECLARE_INT_HANDLER default_intexc_handler /* 35: Interrupt 35 */
  94. DECLARE_INT_HANDLER default_intexc_handler /* 36: Interrupt 36 */
  95. DECLARE_INT_HANDLER default_intexc_handler /* 37: Interrupt 37 */
  96. DECLARE_INT_HANDLER default_intexc_handler /* 38: Interrupt 38 */
  97. DECLARE_INT_HANDLER default_intexc_handler /* 39: Interrupt 39 */
  98. DECLARE_INT_HANDLER default_intexc_handler /* 40: Interrupt 40 */
  99. DECLARE_INT_HANDLER default_intexc_handler /* 41: Interrupt 41 */
  100. DECLARE_INT_HANDLER default_intexc_handler /* 42: Interrupt 42 */
  101. DECLARE_INT_HANDLER default_intexc_handler /* 43: Interrupt 43 */
  102. DECLARE_INT_HANDLER default_intexc_handler /* 44: Interrupt 44 */
  103. DECLARE_INT_HANDLER default_intexc_handler /* 45: Interrupt 45 */
  104. DECLARE_INT_HANDLER default_intexc_handler /* 46: Interrupt 46 */
  105. DECLARE_INT_HANDLER default_intexc_handler /* 47: Interrupt 47 */
  106. DECLARE_INT_HANDLER default_intexc_handler /* 48: Interrupt 48 */
  107. DECLARE_INT_HANDLER default_intexc_handler /* 49: Interrupt 49 */
  108. DECLARE_INT_HANDLER default_intexc_handler /* 50: Interrupt 50 */
  109. DECLARE_INT_HANDLER eclic_uart0_int_handler /* 51: Interrupt 51 */
  110. DECLARE_INT_HANDLER default_intexc_handler /* 52: Interrupt 52 */
  111. DECLARE_INT_HANDLER default_intexc_handler /* 53: Interrupt 53 */
  112. DECLARE_INT_HANDLER default_intexc_handler /* 54: Interrupt 54 */
  113. DECLARE_INT_HANDLER default_intexc_handler /* 55: Interrupt 55 */
  114. DECLARE_INT_HANDLER default_intexc_handler /* 56: Interrupt 56 */
  115. DECLARE_INT_HANDLER default_intexc_handler /* 57: Interrupt 57 */
  116. DECLARE_INT_HANDLER default_intexc_handler /* 58: Interrupt 58 */
  117. DECLARE_INT_HANDLER default_intexc_handler /* 59: Interrupt 59 */
  118. DECLARE_INT_HANDLER default_intexc_handler /* 60: Interrupt 60 */
  119. DECLARE_INT_HANDLER default_intexc_handler /* 61: Interrupt 61 */
  120. DECLARE_INT_HANDLER default_intexc_handler /* 62: Interrupt 62 */
  121. DECLARE_INT_HANDLER default_intexc_handler /* 63: Interrupt 63 */
  122. .option pop
  123. .size vector_base, . - vector_base
  124. #endif
  125. .section .text.init
  126. .globl _start
  127. .type _start, @function
  128. /**
  129. * Reset Handler called on controller reset
  130. */
  131. _start:
  132. /* ===== Startup Stage 1 ===== */
  133. /* Disable Global Interrupt */
  134. csrc CSR_MSTATUS, MSTATUS_MIE
  135. /* If SMP_CPU_CNT is not defined,
  136. * assume that only 1 core is allowed to run,
  137. * the core hartid is defined via BOOT_HARTID.
  138. * other harts if run to here, just do wfi in __amp_wait
  139. */
  140. #ifndef SMP_CPU_CNT
  141. /* take bit 0-7 for hart id in a local cluster */
  142. csrr a0, CSR_MHARTID
  143. andi a0, a0, 0xFF
  144. /* BOOT_HARTID is configurable in Makefile via BOOT_HARTID variable */
  145. li a1, BOOT_HARTID
  146. bne a0, a1, __amp_wait
  147. #endif
  148. /* Initialize GP and TP and jump table base when zcmt enabled */
  149. .option push
  150. .option norelax
  151. la gp, __global_pointer$
  152. la tp, __tls_base
  153. #if defined(__riscv_zcmt)
  154. la t0, __jvt_base$
  155. csrw CSR_JVT, t0
  156. #endif
  157. .option pop
  158. /* TODO if don't have SMP, you can remove the SMP_CPU_CNT related code */
  159. #if defined(SMP_CPU_CNT) && (SMP_CPU_CNT > 1)
  160. /* Set correct sp for each cpu
  161. * each stack size is __STACK_SIZE
  162. * defined in linker script */
  163. lui t0, %hi(__STACK_SIZE)
  164. addi t0, t0, %lo(__STACK_SIZE)
  165. la sp, _sp
  166. csrr a0, CSR_MHARTID
  167. andi a0, a0, 0xFF
  168. li a1, 0
  169. 1:
  170. beq a0, a1, 2f
  171. sub sp, sp, t0
  172. addi a1, a1, 1
  173. j 1b
  174. 2:
  175. #else
  176. /* Set correct sp for current cpu */
  177. la sp, _sp
  178. #endif
  179. #if !(defined(CPU_SERIES) && CPU_SERIES == 100)
  180. /*
  181. * Set the the NMI base mnvec to share
  182. * with mtvec by setting CSR_MMISC_CTL
  183. * bit 9 NMI_CAUSE_FFF to 1
  184. */
  185. li t0, MMISC_CTL_NMI_CAUSE_FFF
  186. csrs CSR_MMISC_CTL, t0
  187. /*
  188. * Enable Zc feature when compiled zcmp & zcmt
  189. */
  190. li t0, MMISC_CTL_ZC
  191. #if defined(__riscv_zcmp) || defined(__riscv_zcmt)
  192. csrs CSR_MMISC_CTL, t0
  193. #else
  194. csrc CSR_MMISC_CTL, t0
  195. #endif
  196. #endif
  197. /*
  198. * Set Exception Entry MTVEC to early_exc_entry
  199. * Due to settings above, Exception and NMI
  200. * will share common entry.
  201. * This early_exc_entry is only used during early
  202. * boot stage before main
  203. * Set default interrupt mode to CLINT interrupt mode
  204. */
  205. la t0, early_exc_entry
  206. csrw CSR_MTVEC, t0
  207. /* ===== Startup Stage 2 ===== */
  208. /* Enable FPU and Vector Unit if f/d/v exist in march */
  209. #if defined(__riscv_flen) && __riscv_flen > 0
  210. /* Enable FPU, and set state to initial */
  211. li t0, MSTATUS_FS
  212. csrc mstatus, t0
  213. li t0, MSTATUS_FS_INITIAL
  214. csrs mstatus, t0
  215. #endif
  216. #if defined(__riscv_vector)
  217. /* Enable Vector, and set state to initial */
  218. li t0, MSTATUS_VS
  219. csrc mstatus, t0
  220. li t0, MSTATUS_VS_INITIAL
  221. csrs mstatus, t0
  222. #endif
  223. /* TODO: Enable I/D Cache if present determined by cpufeature.h */
  224. /* This should be only used by nuclei_gen which generate a correct cpufeature.h */
  225. /* We use CPU_ISA macro to determine whether this cpufeature.h is generated or hand written */
  226. /* This is used to speedup data loading */
  227. #if !defined(SMP_CPU_CNT)
  228. #ifdef CPU_ISA
  229. #ifndef CFG_HAS_ECC
  230. /* Only enable i/dcache when ecc not present */
  231. #ifdef CFG_HAS_ICACHE
  232. csrsi CSR_MCACHE_CTL, MCACHE_CTL_IC_EN
  233. #endif
  234. #ifdef CFG_HAS_DCACHE
  235. li t0, MCACHE_CTL_DC_EN
  236. csrs CSR_MCACHE_CTL, t0
  237. #endif
  238. #endif
  239. #endif
  240. #endif
  241. /* Enable mcycle and minstret counter */
  242. csrci CSR_MCOUNTINHIBIT, 0x5
  243. #if defined(SMP_CPU_CNT) && (SMP_CPU_CNT > 1)
  244. csrr a0, CSR_MHARTID
  245. li a1, BOOT_HARTID
  246. bne a0, a1, __skip_init
  247. #endif
  248. .size _start, . - _start
  249. .type __init_common, @function
  250. __init_common:
  251. /* ===== Startup Stage 3 ===== */
  252. /*
  253. * Load text section from CODE ROM to CODE RAM
  254. * when text LMA is different with VMA
  255. */
  256. la a0, _text_lma
  257. la a1, _text
  258. /* If text LMA and VMA are equal
  259. * then no need to copy text section */
  260. beq a0, a1, 2f
  261. la a2, _etext
  262. bgeu a1, a2, 2f
  263. 1:
  264. /* Load code section if necessary */
  265. lw t0, (a0)
  266. sw t0, (a1)
  267. addi a0, a0, 4
  268. addi a1, a1, 4
  269. bltu a1, a2, 1b
  270. /* execute fence.i to make sure cpu can see updated code */
  271. fence.i
  272. 2:
  273. /* Load data section */
  274. la a0, _data_lma
  275. la a1, _data
  276. /* If data vma=lma, no need to copy */
  277. beq a0, a1, 2f
  278. la a2, _edata
  279. bgeu a1, a2, 2f
  280. 1:
  281. lw t0, (a0)
  282. sw t0, (a1)
  283. addi a0, a0, 4
  284. addi a1, a1, 4
  285. bltu a1, a2, 1b
  286. 2:
  287. /* Clear bss section */
  288. la a0, __bss_start
  289. la a1, _end
  290. bgeu a0, a1, 2f
  291. 1:
  292. sw zero, (a0)
  293. addi a0, a0, 4
  294. bltu a0, a1, 1b
  295. 2:
  296. .size __init_common, . - __init_common
  297. .globl _start_premain
  298. .type _start_premain, @function
  299. _start_premain:
  300. /*
  301. * Call vendor defined SystemInit to
  302. * initialize the micro-controller system
  303. * SystemInit will just be called by boot cpu
  304. */
  305. call SystemInit
  306. /*
  307. * Call C/C++ constructor start up code,
  308. * __libc_fini is defined in linker script,
  309. * so register_fini function will be called
  310. * and will run atexit (__libc_fini_array)
  311. * to do previous call atexit function
  312. */
  313. call __libc_init_array
  314. .size _start_premain, . - _start_premain
  315. .type __skip_init, @function
  316. __skip_init:
  317. /* Sync all harts at this function */
  318. call __sync_harts
  319. /* do pre-init steps before main */
  320. /* _premain_init will be called by each cpu
  321. * please make sure the implementation of __premain_int
  322. * considered this
  323. * it will update mtvec according to eclic present or not
  324. * mtvec will set to exc_entry
  325. */
  326. call _premain_init
  327. #if !(defined(CPU_SERIES) && CPU_SERIES == 100)
  328. /* BPU cold bringup need time, so enable BPU before enter to main */
  329. li t0, MMISC_CTL_BPU
  330. csrs CSR_MMISC_CTL, t0
  331. #endif
  332. // Interrupt is still disabled here
  333. /* ===== Call SMP Main Function ===== */
  334. /* argc = argv = 0 */
  335. li a0, 0
  336. li a1, 0
  337. #if defined(SMP_CPU_CNT) && (SMP_CPU_CNT > 1)
  338. /* The weak implementation of smp_main is in this file */
  339. call smp_main
  340. #else
  341. #ifdef RTOS_RTTHREAD
  342. // Call entry function when using RT-Thread
  343. #ifdef SMODE_RTOS
  344. call main_entry
  345. #else
  346. call entry
  347. #endif
  348. #else
  349. call main
  350. #endif
  351. #endif
  352. /* do post-main steps after main
  353. * this function will be called by each cpu */
  354. call _postmain_fini
  355. .size __skip_init, . - __skip_init
  356. .type __amp_wait, @function
  357. __amp_wait:
  358. 1:
  359. wfi
  360. j 1b
  361. .size __amp_wait, . - __amp_wait
  362. #if defined(SMP_CPU_CNT) && (SMP_CPU_CNT > 1)
  363. /*
  364. * You can re-implement smp_main function in your code
  365. * to do smp boot process and handle multi harts
  366. */
  367. .weak smp_main
  368. .type smp_main, @function
  369. smp_main:
  370. addi sp, sp, -2*REGBYTES
  371. STORE ra, 0*REGBYTES(sp)
  372. /* only boot hart goto main, other harts do wfi */
  373. csrr t0, CSR_MHARTID
  374. li t1, BOOT_HARTID
  375. beq t0, t1, 2f
  376. 1:
  377. wfi
  378. j 1b
  379. 2:
  380. #ifdef RTOS_RTTHREAD
  381. // Call entry function when using RT-Thread
  382. #ifdef SMODE_RTOS
  383. call main_entry
  384. #else
  385. call entry
  386. #endif
  387. #else
  388. call main
  389. #endif
  390. LOAD ra, 0*REGBYTES(sp)
  391. addi sp, sp, 2*REGBYTES
  392. ret
  393. .size smp_main, . - smp_main
  394. #endif
  395. /* Early boot exception entry before main */
  396. .align 6
  397. .global early_exc_entry
  398. .type early_exc_entry, @function
  399. early_exc_entry:
  400. wfi
  401. j early_exc_entry
  402. .size early_exc_entry, . - early_exc_entry