os_cpu_a.S 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. #include "riscv_encoding.h"
  2. #ifndef __riscv_32e
  3. #define portRegNum 32
  4. #else
  5. #define portRegNum 14
  6. #endif
  7. #define portCONTEXT_SIZE ( portRegNum * REGBYTES )
  8. DISABLE_MIE MACRO
  9. csrci CSR_MSTATUS, MSTATUS_MIE
  10. ENDM
  11. SAVE_CONTEXT MACRO
  12. #if defined(ECLIC_HW_CTX_AUTO) && defined(CFG_HAS_ECLICV2)
  13. #else
  14. csrrw sp, CSR_MSCRATCHCSWL, sp
  15. /* Allocate stack space for context saving */
  16. #ifndef __riscv_32e
  17. addi sp, sp, -20*REGBYTES
  18. #else
  19. addi sp, sp, -14*REGBYTES
  20. #endif /* __riscv_32e */
  21. STORE x1, 0*REGBYTES(sp)
  22. STORE x4, 1*REGBYTES(sp)
  23. STORE x5, 2*REGBYTES(sp)
  24. STORE x6, 3*REGBYTES(sp)
  25. STORE x7, 4*REGBYTES(sp)
  26. STORE x10, 5*REGBYTES(sp)
  27. STORE x11, 6*REGBYTES(sp)
  28. STORE x12, 7*REGBYTES(sp)
  29. STORE x13, 8*REGBYTES(sp)
  30. STORE x14, 9*REGBYTES(sp)
  31. STORE x15, 10*REGBYTES(sp)
  32. #ifndef __riscv_32e
  33. STORE x16, 14*REGBYTES(sp)
  34. STORE x17, 15*REGBYTES(sp)
  35. STORE x28, 16*REGBYTES(sp)
  36. STORE x29, 17*REGBYTES(sp)
  37. STORE x30, 18*REGBYTES(sp)
  38. STORE x31, 19*REGBYTES(sp)
  39. #endif /* __riscv_32e */
  40. #endif
  41. ENDM
  42. RESTORE_CONTEXT MACRO
  43. #if defined(ECLIC_HW_CTX_AUTO) && defined(CFG_HAS_ECLICV2)
  44. #else
  45. LOAD x1, 0*REGBYTES(sp)
  46. LOAD x4, 1*REGBYTES(sp)
  47. LOAD x5, 2*REGBYTES(sp)
  48. LOAD x6, 3*REGBYTES(sp)
  49. LOAD x7, 4*REGBYTES(sp)
  50. LOAD x10, 5*REGBYTES(sp)
  51. LOAD x11, 6*REGBYTES(sp)
  52. LOAD x12, 7*REGBYTES(sp)
  53. LOAD x13, 8*REGBYTES(sp)
  54. LOAD x14, 9*REGBYTES(sp)
  55. LOAD x15, 10*REGBYTES(sp)
  56. #ifndef __riscv_32e
  57. LOAD x16, 14*REGBYTES(sp)
  58. LOAD x17, 15*REGBYTES(sp)
  59. LOAD x28, 16*REGBYTES(sp)
  60. LOAD x29, 17*REGBYTES(sp)
  61. LOAD x30, 18*REGBYTES(sp)
  62. LOAD x31, 19*REGBYTES(sp)
  63. /* De-allocate the stack space */
  64. addi sp, sp, 20*REGBYTES
  65. #else
  66. /* De-allocate the stack space */
  67. addi sp, sp, 14*REGBYTES
  68. #endif /* __riscv_32e */
  69. csrrw sp, CSR_MSCRATCHCSWL, sp
  70. #endif
  71. ENDM
  72. SAVE_CSR_CONTEXT MACRO
  73. #if defined(ECLIC_HW_CTX_AUTO) && defined(CFG_HAS_ECLICV2)
  74. #else
  75. /* Store CSR mcause to stack using pushmcause */
  76. csrrwi x0, CSR_PUSHMCAUSE, 11
  77. /* Store CSR mepc to stack using pushmepc */
  78. csrrwi x0, CSR_PUSHMEPC, 12
  79. /* Store CSR msub to stack using pushmsub */
  80. csrrwi x0, CSR_PUSHMSUBM, 13
  81. #endif
  82. ENDM
  83. RESTORE_CSR_CONTEXT MACRO
  84. #if defined(ECLIC_HW_CTX_AUTO) && defined(CFG_HAS_ECLICV2)
  85. #else
  86. LOAD x5, 13*REGBYTES(sp)
  87. csrw CSR_MSUBM, x5
  88. LOAD x5, 12*REGBYTES(sp)
  89. csrw CSR_MEPC, x5
  90. LOAD x5, 11*REGBYTES(sp)
  91. csrw CSR_MCAUSE, x5
  92. #endif
  93. ENDM
  94. PUBLIC exc_entry, irq_entry, default_intexc_handler
  95. PUBLIC Undef_Handler
  96. PUBLIC prvPortStartFirstTask, eclic_msip_handler
  97. EXTERN core_exception_handler
  98. EXTERN xPortTaskSwitch
  99. EXTERN OSTCBCur
  100. EXTERN OSTCBHighRdy
  101. EXTERN CSTACK$$Limit
  102. SECTION `.text`:CODE:NOROOT(2)
  103. CODE
  104. ALIGN 6
  105. exc_entry:
  106. /* Save the caller saving registers (context) */
  107. SAVE_CONTEXT
  108. /* Save the necessary CSR registers */
  109. SAVE_CSR_CONTEXT
  110. /*
  111. * Set the exception handler function arguments
  112. * argument 1: mcause value
  113. * argument 2: current stack point(SP) value
  114. */
  115. csrr a0, mcause
  116. mv a1, sp
  117. /*
  118. * TODO: Call the exception handler function
  119. * By default, the function template is provided in
  120. * system_Device.c, you can adjust it as you want
  121. */
  122. call core_exception_handler
  123. /* Restore the necessary CSR registers */
  124. RESTORE_CSR_CONTEXT
  125. /* Restore the caller saving registers (context) */
  126. RESTORE_CONTEXT
  127. /* Return to regular code */
  128. #if defined(ECLIC_HW_CTX_AUTO) && defined(CFG_HAS_ECLICV2)
  129. csrrwi x0, CSR_POPXRET, 0
  130. #else
  131. mret
  132. #endif
  133. ALIGN 2
  134. irq_entry:
  135. /* Save the caller saving registers (context) */
  136. SAVE_CONTEXT
  137. /* Save the necessary CSR registers */
  138. SAVE_CSR_CONTEXT
  139. /* This special CSR read/write operation, which is actually
  140. * claim the CLIC to find its pending highest ID, if the ID
  141. * is not 0, then automatically enable the mstatus.MIE, and
  142. * jump to its vector-entry-label, and update the link register
  143. */
  144. csrrw ra, CSR_JALMNXTI, ra
  145. /* Critical section with interrupts disabled */
  146. DISABLE_MIE
  147. /* Restore the necessary CSR registers */
  148. RESTORE_CSR_CONTEXT
  149. /* Restore the caller saving registers (context) */
  150. RESTORE_CONTEXT
  151. /* Return to regular code */
  152. #if defined(ECLIC_HW_CTX_AUTO) && defined(CFG_HAS_ECLICV2)
  153. csrrwi x0, CSR_POPXRET, 0
  154. #else
  155. mret
  156. #endif
  157. /* Start the first task. This also clears the bit that indicates the FPU is
  158. in use in case the FPU was used before the scheduler was started - which
  159. would otherwise result in the unnecessary leaving of space in the stack
  160. for lazy saving of FPU registers. */
  161. ALIGN 3
  162. prvPortStartFirstTask:
  163. /* Setup Interrupt Stack using
  164. The stack that was used by main()
  165. before the scheduler is started is
  166. no longer required after the scheduler is started.
  167. Interrupt stack pointer is stored in CSR_MSCRATCH */
  168. la t0, CSTACK$$Limit
  169. csrw CSR_MSCRATCH, t0
  170. LOAD sp, OSTCBHighRdy /* Load OSTCBHighRdy. */
  171. LOAD sp, 0x0(sp) /* Read sp from first TCB member */
  172. /* Pop PC from stack and set MEPC */
  173. LOAD t0, 0 * REGBYTES(sp)
  174. csrw CSR_MEPC, t0
  175. /* Pop mstatus from stack and set it */
  176. LOAD t0, (portRegNum - 1) * REGBYTES(sp)
  177. csrw CSR_MSTATUS, t0
  178. /* Interrupt still disable here */
  179. /* Restore Registers from Stack */
  180. LOAD x1, 1 * REGBYTES(sp) /* RA */
  181. LOAD x5, 2 * REGBYTES(sp)
  182. LOAD x6, 3 * REGBYTES(sp)
  183. LOAD x7, 4 * REGBYTES(sp)
  184. LOAD x8, 5 * REGBYTES(sp)
  185. LOAD x9, 6 * REGBYTES(sp)
  186. LOAD x10, 7 * REGBYTES(sp)
  187. LOAD x11, 8 * REGBYTES(sp)
  188. LOAD x12, 9 * REGBYTES(sp)
  189. LOAD x13, 10 * REGBYTES(sp)
  190. LOAD x14, 11 * REGBYTES(sp)
  191. LOAD x15, 12 * REGBYTES(sp)
  192. #ifndef __riscv_32e
  193. LOAD x16, 13 * REGBYTES(sp)
  194. LOAD x17, 14 * REGBYTES(sp)
  195. LOAD x18, 15 * REGBYTES(sp)
  196. LOAD x19, 16 * REGBYTES(sp)
  197. LOAD x20, 17 * REGBYTES(sp)
  198. LOAD x21, 18 * REGBYTES(sp)
  199. LOAD x22, 19 * REGBYTES(sp)
  200. LOAD x23, 20 * REGBYTES(sp)
  201. LOAD x24, 21 * REGBYTES(sp)
  202. LOAD x25, 22 * REGBYTES(sp)
  203. LOAD x26, 23 * REGBYTES(sp)
  204. LOAD x27, 24 * REGBYTES(sp)
  205. LOAD x28, 25 * REGBYTES(sp)
  206. LOAD x29, 26 * REGBYTES(sp)
  207. LOAD x30, 27 * REGBYTES(sp)
  208. LOAD x31, 28 * REGBYTES(sp)
  209. #endif
  210. addi sp, sp, portCONTEXT_SIZE
  211. mret
  212. ALIGN 2
  213. eclic_msip_handler:
  214. addi sp, sp, -portCONTEXT_SIZE
  215. STORE x1, 1 * REGBYTES(sp) /* RA */
  216. STORE x5, 2 * REGBYTES(sp)
  217. STORE x6, 3 * REGBYTES(sp)
  218. STORE x7, 4 * REGBYTES(sp)
  219. STORE x8, 5 * REGBYTES(sp)
  220. STORE x9, 6 * REGBYTES(sp)
  221. STORE x10, 7 * REGBYTES(sp)
  222. STORE x11, 8 * REGBYTES(sp)
  223. STORE x12, 9 * REGBYTES(sp)
  224. STORE x13, 10 * REGBYTES(sp)
  225. STORE x14, 11 * REGBYTES(sp)
  226. STORE x15, 12 * REGBYTES(sp)
  227. #ifndef __riscv_32e
  228. STORE x16, 13 * REGBYTES(sp)
  229. STORE x17, 14 * REGBYTES(sp)
  230. STORE x18, 15 * REGBYTES(sp)
  231. STORE x19, 16 * REGBYTES(sp)
  232. STORE x20, 17 * REGBYTES(sp)
  233. STORE x21, 18 * REGBYTES(sp)
  234. STORE x22, 19 * REGBYTES(sp)
  235. STORE x23, 20 * REGBYTES(sp)
  236. STORE x24, 21 * REGBYTES(sp)
  237. STORE x25, 22 * REGBYTES(sp)
  238. STORE x26, 23 * REGBYTES(sp)
  239. STORE x27, 24 * REGBYTES(sp)
  240. STORE x28, 25 * REGBYTES(sp)
  241. STORE x29, 26 * REGBYTES(sp)
  242. STORE x30, 27 * REGBYTES(sp)
  243. STORE x31, 28 * REGBYTES(sp)
  244. #endif
  245. /* Push mstatus to stack */
  246. csrr t0, CSR_MSTATUS
  247. STORE t0, (portRegNum - 1) * REGBYTES(sp)
  248. /* Push additional registers */
  249. /* Store sp to task stack */
  250. LOAD t0, OSTCBCur
  251. STORE sp, 0(t0)
  252. csrr t0, CSR_MEPC
  253. STORE t0, 0(sp)
  254. jal xPortTaskSwitch
  255. /* Switch task context */
  256. LOAD t0, OSTCBHighRdy /* Load OSTCBHighRdy. */
  257. LOAD sp, 0x0(t0) /* Read sp from first TCB member */
  258. /* Pop PC from stack and set MEPC */
  259. LOAD t0, 0 * REGBYTES(sp)
  260. csrw CSR_MEPC, t0
  261. /* Pop additional registers */
  262. /* Pop mstatus from stack and set it */
  263. LOAD t0, (portRegNum - 1) * REGBYTES(sp)
  264. csrw CSR_MSTATUS, t0
  265. /* Interrupt still disable here */
  266. /* Restore Registers from Stack */
  267. LOAD x1, 1 * REGBYTES(sp) /* RA */
  268. LOAD x5, 2 * REGBYTES(sp)
  269. LOAD x6, 3 * REGBYTES(sp)
  270. LOAD x7, 4 * REGBYTES(sp)
  271. LOAD x8, 5 * REGBYTES(sp)
  272. LOAD x9, 6 * REGBYTES(sp)
  273. LOAD x10, 7 * REGBYTES(sp)
  274. LOAD x11, 8 * REGBYTES(sp)
  275. LOAD x12, 9 * REGBYTES(sp)
  276. LOAD x13, 10 * REGBYTES(sp)
  277. LOAD x14, 11 * REGBYTES(sp)
  278. LOAD x15, 12 * REGBYTES(sp)
  279. #ifndef __riscv_32e
  280. LOAD x16, 13 * REGBYTES(sp)
  281. LOAD x17, 14 * REGBYTES(sp)
  282. LOAD x18, 15 * REGBYTES(sp)
  283. LOAD x19, 16 * REGBYTES(sp)
  284. LOAD x20, 17 * REGBYTES(sp)
  285. LOAD x21, 18 * REGBYTES(sp)
  286. LOAD x22, 19 * REGBYTES(sp)
  287. LOAD x23, 20 * REGBYTES(sp)
  288. LOAD x24, 21 * REGBYTES(sp)
  289. LOAD x25, 22 * REGBYTES(sp)
  290. LOAD x26, 23 * REGBYTES(sp)
  291. LOAD x27, 24 * REGBYTES(sp)
  292. LOAD x28, 25 * REGBYTES(sp)
  293. LOAD x29, 26 * REGBYTES(sp)
  294. LOAD x30, 27 * REGBYTES(sp)
  295. LOAD x31, 28 * REGBYTES(sp)
  296. #endif
  297. addi sp, sp, portCONTEXT_SIZE
  298. mret
  299. default_intexc_handler:
  300. Undef_Handler:
  301. j Undef_Handler
  302. END