portasm.S 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. /*
  2. * FreeRTOS Kernel Port For Nuclei RISC-V Processor
  3. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a copy of
  6. * this software and associated documentation files (the "Software"), to deal in
  7. * the Software without restriction, including without limitation the rights to
  8. * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  9. * the Software, and to permit persons to whom the Software is furnished to do so,
  10. * subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in all
  13. * copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  17. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  18. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  19. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  20. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. *
  22. * http://www.FreeRTOS.org
  23. * http://aws.amazon.com/freertos
  24. *
  25. * 1 tab == 4 spaces!
  26. */
  27. #include "riscv_encoding.h"
  28. #ifndef __riscv_32e
  29. #define portRegNum 32
  30. #else
  31. #define portRegNum 14
  32. #endif
  33. #define portCONTEXT_SIZE ( portRegNum * REGBYTES )
  34. // If you want to use SMP freertos
  35. // configNUMBER_OF_CORES must be defined to the number of cores in your system.
  36. // If you define configNUMBER_OF_CORES using -D option, you must make sure that
  37. // asm option must contains this macro defined
  38. #ifndef configNUMBER_OF_CORES
  39. #define configNUMBER_OF_CORES 1
  40. #endif
  41. DISABLE_MIE MACRO
  42. csrci CSR_MSTATUS, MSTATUS_MIE
  43. ENDM
  44. SAVE_CONTEXT MACRO
  45. #if defined(ECLIC_HW_CTX_AUTO) && defined(CFG_HAS_ECLICV2)
  46. #else
  47. csrrw sp, CSR_MSCRATCHCSWL, sp
  48. /* Allocate stack space for context saving */
  49. #ifndef __riscv_32e
  50. addi sp, sp, -20*REGBYTES
  51. #else
  52. addi sp, sp, -14*REGBYTES
  53. #endif /* __riscv_32e */
  54. STORE x1, 0*REGBYTES(sp)
  55. STORE x4, 1*REGBYTES(sp)
  56. STORE x5, 2*REGBYTES(sp)
  57. STORE x6, 3*REGBYTES(sp)
  58. STORE x7, 4*REGBYTES(sp)
  59. STORE x10, 5*REGBYTES(sp)
  60. STORE x11, 6*REGBYTES(sp)
  61. STORE x12, 7*REGBYTES(sp)
  62. STORE x13, 8*REGBYTES(sp)
  63. STORE x14, 9*REGBYTES(sp)
  64. STORE x15, 10*REGBYTES(sp)
  65. #ifndef __riscv_32e
  66. STORE x16, 14*REGBYTES(sp)
  67. STORE x17, 15*REGBYTES(sp)
  68. STORE x28, 16*REGBYTES(sp)
  69. STORE x29, 17*REGBYTES(sp)
  70. STORE x30, 18*REGBYTES(sp)
  71. STORE x31, 19*REGBYTES(sp)
  72. #endif /* __riscv_32e */
  73. #endif
  74. ENDM
  75. RESTORE_CONTEXT MACRO
  76. #if defined(ECLIC_HW_CTX_AUTO) && defined(CFG_HAS_ECLICV2)
  77. #else
  78. LOAD x1, 0*REGBYTES(sp)
  79. LOAD x4, 1*REGBYTES(sp)
  80. LOAD x5, 2*REGBYTES(sp)
  81. LOAD x6, 3*REGBYTES(sp)
  82. LOAD x7, 4*REGBYTES(sp)
  83. LOAD x10, 5*REGBYTES(sp)
  84. LOAD x11, 6*REGBYTES(sp)
  85. LOAD x12, 7*REGBYTES(sp)
  86. LOAD x13, 8*REGBYTES(sp)
  87. LOAD x14, 9*REGBYTES(sp)
  88. LOAD x15, 10*REGBYTES(sp)
  89. #ifndef __riscv_32e
  90. LOAD x16, 14*REGBYTES(sp)
  91. LOAD x17, 15*REGBYTES(sp)
  92. LOAD x28, 16*REGBYTES(sp)
  93. LOAD x29, 17*REGBYTES(sp)
  94. LOAD x30, 18*REGBYTES(sp)
  95. LOAD x31, 19*REGBYTES(sp)
  96. /* De-allocate the stack space */
  97. addi sp, sp, 20*REGBYTES
  98. #else
  99. /* De-allocate the stack space */
  100. addi sp, sp, 14*REGBYTES
  101. #endif /* __riscv_32e */
  102. csrrw sp, CSR_MSCRATCHCSWL, sp
  103. #endif
  104. ENDM
  105. SAVE_CSR_CONTEXT MACRO
  106. #if defined(ECLIC_HW_CTX_AUTO) && defined(CFG_HAS_ECLICV2)
  107. #else
  108. /* Store CSR mcause to stack using pushmcause */
  109. csrrwi x0, CSR_PUSHMCAUSE, 11
  110. /* Store CSR mepc to stack using pushmepc */
  111. csrrwi x0, CSR_PUSHMEPC, 12
  112. /* Store CSR msub to stack using pushmsub */
  113. csrrwi x0, CSR_PUSHMSUBM, 13
  114. #endif
  115. ENDM
  116. RESTORE_CSR_CONTEXT MACRO
  117. #if defined(ECLIC_HW_CTX_AUTO) && defined(CFG_HAS_ECLICV2)
  118. #else
  119. LOAD x5, 13*REGBYTES(sp)
  120. csrw CSR_MSUBM, x5
  121. LOAD x5, 12*REGBYTES(sp)
  122. csrw CSR_MEPC, x5
  123. LOAD x5, 11*REGBYTES(sp)
  124. csrw CSR_MCAUSE, x5
  125. #endif
  126. ENDM
  127. PUBLIC exc_entry, irq_entry, default_intexc_handler
  128. PUBLIC Undef_Handler
  129. PUBLIC prvPortStartFirstTask, eclic_msip_handler
  130. EXTERN core_exception_handler
  131. EXTERN xPortTaskSwitch
  132. #if ( configNUMBER_OF_CORES == 1 )
  133. EXTERN pxCurrentTCB
  134. #else
  135. EXTERN pxCurrentTCBs
  136. #endif
  137. EXTERN CSTACK$$Limit
  138. SECTION `.text`:CODE:NOROOT(2)
  139. CODE
  140. ALIGN 6
  141. exc_entry:
  142. /* Save the caller saving registers (context) */
  143. SAVE_CONTEXT
  144. /* Save the necessary CSR registers */
  145. SAVE_CSR_CONTEXT
  146. /*
  147. * Set the exception handler function arguments
  148. * argument 1: mcause value
  149. * argument 2: current stack point(SP) value
  150. */
  151. csrr a0, mcause
  152. mv a1, sp
  153. /*
  154. * TODO: Call the exception handler function
  155. * By default, the function template is provided in
  156. * system_Device.c, you can adjust it as you want
  157. */
  158. call core_exception_handler
  159. /* Restore the necessary CSR registers */
  160. RESTORE_CSR_CONTEXT
  161. /* Restore the caller saving registers (context) */
  162. RESTORE_CONTEXT
  163. /* Return to regular code */
  164. #if defined(ECLIC_HW_CTX_AUTO) && defined(CFG_HAS_ECLICV2)
  165. csrrwi x0, CSR_POPXRET, 0
  166. #else
  167. mret
  168. #endif
  169. ALIGN 2
  170. irq_entry:
  171. /* Save the caller saving registers (context) */
  172. SAVE_CONTEXT
  173. /* Save the necessary CSR registers */
  174. SAVE_CSR_CONTEXT
  175. /* This special CSR read/write operation, which is actually
  176. * claim the CLIC to find its pending highest ID, if the ID
  177. * is not 0, then automatically enable the mstatus.MIE, and
  178. * jump to its vector-entry-label, and update the link register
  179. */
  180. csrrw ra, CSR_JALMNXTI, ra
  181. /* Critical section with interrupts disabled */
  182. DISABLE_MIE
  183. /* Restore the necessary CSR registers */
  184. RESTORE_CSR_CONTEXT
  185. /* Restore the caller saving registers (context) */
  186. RESTORE_CONTEXT
  187. /* Return to regular code */
  188. #if defined(ECLIC_HW_CTX_AUTO) && defined(CFG_HAS_ECLICV2)
  189. csrrwi x0, CSR_POPXRET, 0
  190. #else
  191. mret
  192. #endif
  193. /* Start the first task. This also clears the bit that indicates the FPU is
  194. in use in case the FPU was used before the scheduler was started - which
  195. would otherwise result in the unnecessary leaving of space in the stack
  196. for lazy saving of FPU registers. */
  197. ALIGN 3
  198. prvPortStartFirstTask:
  199. /* Setup Interrupt Stack using
  200. The stack that was used by main()
  201. before the scheduler is started is
  202. no longer required after the scheduler is started.
  203. Interrupt stack pointer is stored in CSR_MSCRATCH */
  204. #if defined(SMP_CPU_CNT) && (SMP_CPU_CNT > 1)
  205. /* Set correct sp for each cpu
  206. * each stack size is __STACK_SIZE
  207. * defined in linker script */
  208. EXTERN __STACK_SIZE
  209. lui t1, %hi(__STACK_SIZE)
  210. addi t1, t1, %lo(__STACK_SIZE)
  211. la t0, CSTACK$$Limit
  212. csrr a0, mhartid
  213. andi a0, a0, 0xFF
  214. li a1, 0
  215. _per_cpu_init_sp_cont:
  216. beq a0, a1, _per_cpu_init_sp_fin
  217. sub t0, t0, t1
  218. addi a1, a1, 1
  219. j _per_cpu_init_sp_cont
  220. _per_cpu_init_sp_fin:
  221. #else
  222. la t0, CSTACK$$Limit
  223. #endif
  224. csrw CSR_MSCRATCH, t0
  225. #if ( configNUMBER_OF_CORES == 1 )
  226. LOAD t0, pxCurrentTCB /* Load pxCurrentTCB. */
  227. #else
  228. la t0, pxCurrentTCBs /* Load pxCurrentTCBs[core] */
  229. csrr t1, CSR_MHARTID
  230. slli t1, t1, LOG_REGBYTES
  231. add t0, t0, t1
  232. LOAD t0, 0(t0)
  233. #endif
  234. LOAD sp, 0x0(t0) /* Read sp from first TCB member */
  235. /* Pop PC from stack and set MEPC */
  236. LOAD t0, 0 * REGBYTES(sp)
  237. csrw CSR_MEPC, t0
  238. /* Pop mstatus from stack and set it */
  239. LOAD t0, (portRegNum - 1) * REGBYTES(sp)
  240. csrw CSR_MSTATUS, t0
  241. /* Interrupt still disable here */
  242. /* Restore Registers from Stack */
  243. LOAD x1, 1 * REGBYTES(sp) /* RA */
  244. LOAD x5, 2 * REGBYTES(sp)
  245. LOAD x6, 3 * REGBYTES(sp)
  246. LOAD x7, 4 * REGBYTES(sp)
  247. LOAD x8, 5 * REGBYTES(sp)
  248. LOAD x9, 6 * REGBYTES(sp)
  249. LOAD x10, 7 * REGBYTES(sp)
  250. LOAD x11, 8 * REGBYTES(sp)
  251. LOAD x12, 9 * REGBYTES(sp)
  252. LOAD x13, 10 * REGBYTES(sp)
  253. LOAD x14, 11 * REGBYTES(sp)
  254. LOAD x15, 12 * REGBYTES(sp)
  255. #ifndef __riscv_32e
  256. LOAD x16, 13 * REGBYTES(sp)
  257. LOAD x17, 14 * REGBYTES(sp)
  258. LOAD x18, 15 * REGBYTES(sp)
  259. LOAD x19, 16 * REGBYTES(sp)
  260. LOAD x20, 17 * REGBYTES(sp)
  261. LOAD x21, 18 * REGBYTES(sp)
  262. LOAD x22, 19 * REGBYTES(sp)
  263. LOAD x23, 20 * REGBYTES(sp)
  264. LOAD x24, 21 * REGBYTES(sp)
  265. LOAD x25, 22 * REGBYTES(sp)
  266. LOAD x26, 23 * REGBYTES(sp)
  267. LOAD x27, 24 * REGBYTES(sp)
  268. LOAD x28, 25 * REGBYTES(sp)
  269. LOAD x29, 26 * REGBYTES(sp)
  270. LOAD x30, 27 * REGBYTES(sp)
  271. LOAD x31, 28 * REGBYTES(sp)
  272. #endif
  273. addi sp, sp, portCONTEXT_SIZE
  274. mret
  275. ALIGN 2
  276. eclic_msip_handler:
  277. addi sp, sp, -portCONTEXT_SIZE
  278. STORE x1, 1 * REGBYTES(sp) /* RA */
  279. STORE x5, 2 * REGBYTES(sp)
  280. STORE x6, 3 * REGBYTES(sp)
  281. STORE x7, 4 * REGBYTES(sp)
  282. STORE x8, 5 * REGBYTES(sp)
  283. STORE x9, 6 * REGBYTES(sp)
  284. STORE x10, 7 * REGBYTES(sp)
  285. STORE x11, 8 * REGBYTES(sp)
  286. STORE x12, 9 * REGBYTES(sp)
  287. STORE x13, 10 * REGBYTES(sp)
  288. STORE x14, 11 * REGBYTES(sp)
  289. STORE x15, 12 * REGBYTES(sp)
  290. #ifndef __riscv_32e
  291. STORE x16, 13 * REGBYTES(sp)
  292. STORE x17, 14 * REGBYTES(sp)
  293. STORE x18, 15 * REGBYTES(sp)
  294. STORE x19, 16 * REGBYTES(sp)
  295. STORE x20, 17 * REGBYTES(sp)
  296. STORE x21, 18 * REGBYTES(sp)
  297. STORE x22, 19 * REGBYTES(sp)
  298. STORE x23, 20 * REGBYTES(sp)
  299. STORE x24, 21 * REGBYTES(sp)
  300. STORE x25, 22 * REGBYTES(sp)
  301. STORE x26, 23 * REGBYTES(sp)
  302. STORE x27, 24 * REGBYTES(sp)
  303. STORE x28, 25 * REGBYTES(sp)
  304. STORE x29, 26 * REGBYTES(sp)
  305. STORE x30, 27 * REGBYTES(sp)
  306. STORE x31, 28 * REGBYTES(sp)
  307. #endif
  308. /* Push mstatus to stack */
  309. csrr t0, CSR_MSTATUS
  310. STORE t0, (portRegNum - 1) * REGBYTES(sp)
  311. /* Push additional registers */
  312. /* Store sp to task stack */
  313. #if ( configNUMBER_OF_CORES == 1 )
  314. LOAD t0, pxCurrentTCB /* Load pxCurrentTCB. */
  315. #else
  316. la t0, pxCurrentTCBs /* Load pxCurrentTCBs[core] */
  317. csrr t1, CSR_MHARTID
  318. slli t1, t1, LOG_REGBYTES
  319. add t0, t0, t1
  320. LOAD t0, 0(t0)
  321. #endif
  322. STORE sp, 0(t0)
  323. csrr t0, CSR_MEPC
  324. STORE t0, 0(sp)
  325. jal xPortTaskSwitch
  326. /* Switch task context */
  327. #if ( configNUMBER_OF_CORES == 1 )
  328. LOAD t0, pxCurrentTCB /* Load pxCurrentTCB. */
  329. #else
  330. la t0, pxCurrentTCBs /* Load pxCurrentTCBs[core] */
  331. csrr t1, CSR_MHARTID
  332. slli t1, t1, LOG_REGBYTES
  333. add t0, t0, t1
  334. LOAD t0, 0(t0)
  335. #endif
  336. LOAD sp, 0x0(t0) /* Read sp from first TCB member */
  337. /* Pop PC from stack and set MEPC */
  338. LOAD t0, 0 * REGBYTES(sp)
  339. csrw CSR_MEPC, t0
  340. /* Pop additional registers */
  341. /* Pop mstatus from stack and set it */
  342. LOAD t0, (portRegNum - 1) * REGBYTES(sp)
  343. csrw CSR_MSTATUS, t0
  344. /* Interrupt still disable here */
  345. /* Restore Registers from Stack */
  346. LOAD x1, 1 * REGBYTES(sp) /* RA */
  347. LOAD x5, 2 * REGBYTES(sp)
  348. LOAD x6, 3 * REGBYTES(sp)
  349. LOAD x7, 4 * REGBYTES(sp)
  350. LOAD x8, 5 * REGBYTES(sp)
  351. LOAD x9, 6 * REGBYTES(sp)
  352. LOAD x10, 7 * REGBYTES(sp)
  353. LOAD x11, 8 * REGBYTES(sp)
  354. LOAD x12, 9 * REGBYTES(sp)
  355. LOAD x13, 10 * REGBYTES(sp)
  356. LOAD x14, 11 * REGBYTES(sp)
  357. LOAD x15, 12 * REGBYTES(sp)
  358. #ifndef __riscv_32e
  359. LOAD x16, 13 * REGBYTES(sp)
  360. LOAD x17, 14 * REGBYTES(sp)
  361. LOAD x18, 15 * REGBYTES(sp)
  362. LOAD x19, 16 * REGBYTES(sp)
  363. LOAD x20, 17 * REGBYTES(sp)
  364. LOAD x21, 18 * REGBYTES(sp)
  365. LOAD x22, 19 * REGBYTES(sp)
  366. LOAD x23, 20 * REGBYTES(sp)
  367. LOAD x24, 21 * REGBYTES(sp)
  368. LOAD x25, 22 * REGBYTES(sp)
  369. LOAD x26, 23 * REGBYTES(sp)
  370. LOAD x27, 24 * REGBYTES(sp)
  371. LOAD x28, 25 * REGBYTES(sp)
  372. LOAD x29, 26 * REGBYTES(sp)
  373. LOAD x30, 27 * REGBYTES(sp)
  374. LOAD x31, 28 * REGBYTES(sp)
  375. #endif
  376. addi sp, sp, portCONTEXT_SIZE
  377. mret
  378. default_intexc_handler:
  379. Undef_Handler:
  380. j Undef_Handler
  381. END