vectors.S 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. // Copyright 2020 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "soc/soc.h"
  15. #include "soc/interrupt_reg.h"
  16. #include "riscv/rvruntime-frames.h"
  17. #include "soc/soc_caps.h"
  18. #include "sdkconfig.h"
  19. .equ SAVE_REGS, 32
  20. .equ CONTEXT_SIZE, (SAVE_REGS * 4)
  21. .equ panic_from_exception, xt_unhandled_exception
  22. .equ panic_from_isr, panicHandler
  23. .macro save_regs
  24. addi sp, sp, -CONTEXT_SIZE
  25. sw ra, RV_STK_RA(sp)
  26. sw tp, RV_STK_TP(sp)
  27. sw t0, RV_STK_T0(sp)
  28. sw t1, RV_STK_T1(sp)
  29. sw t2, RV_STK_T2(sp)
  30. sw s0, RV_STK_S0(sp)
  31. sw s1, RV_STK_S1(sp)
  32. sw a0, RV_STK_A0(sp)
  33. sw a1, RV_STK_A1(sp)
  34. sw a2, RV_STK_A2(sp)
  35. sw a3, RV_STK_A3(sp)
  36. sw a4, RV_STK_A4(sp)
  37. sw a5, RV_STK_A5(sp)
  38. sw a6, RV_STK_A6(sp)
  39. sw a7, RV_STK_A7(sp)
  40. sw s2, RV_STK_S2(sp)
  41. sw s3, RV_STK_S3(sp)
  42. sw s4, RV_STK_S4(sp)
  43. sw s5, RV_STK_S5(sp)
  44. sw s6, RV_STK_S6(sp)
  45. sw s7, RV_STK_S7(sp)
  46. sw s8, RV_STK_S8(sp)
  47. sw s9, RV_STK_S9(sp)
  48. sw s10, RV_STK_S10(sp)
  49. sw s11, RV_STK_S11(sp)
  50. sw t3, RV_STK_T3(sp)
  51. sw t4, RV_STK_T4(sp)
  52. sw t5, RV_STK_T5(sp)
  53. sw t6, RV_STK_T6(sp)
  54. .endm
  55. .macro save_mepc
  56. csrr t0, mepc
  57. sw t0, RV_STK_MEPC(sp)
  58. .endm
  59. .macro restore_regs
  60. lw ra, RV_STK_RA(sp)
  61. lw tp, RV_STK_TP(sp)
  62. lw t0, RV_STK_T0(sp)
  63. lw t1, RV_STK_T1(sp)
  64. lw t2, RV_STK_T2(sp)
  65. lw s0, RV_STK_S0(sp)
  66. lw s1, RV_STK_S1(sp)
  67. lw a0, RV_STK_A0(sp)
  68. lw a1, RV_STK_A1(sp)
  69. lw a2, RV_STK_A2(sp)
  70. lw a3, RV_STK_A3(sp)
  71. lw a4, RV_STK_A4(sp)
  72. lw a5, RV_STK_A5(sp)
  73. lw a6, RV_STK_A6(sp)
  74. lw a7, RV_STK_A7(sp)
  75. lw s2, RV_STK_S2(sp)
  76. lw s3, RV_STK_S3(sp)
  77. lw s4, RV_STK_S4(sp)
  78. lw s5, RV_STK_S5(sp)
  79. lw s6, RV_STK_S6(sp)
  80. lw s7, RV_STK_S7(sp)
  81. lw s8, RV_STK_S8(sp)
  82. lw s9, RV_STK_S9(sp)
  83. lw s10, RV_STK_S10(sp)
  84. lw s11, RV_STK_S11(sp)
  85. lw t3, RV_STK_T3(sp)
  86. lw t4, RV_STK_T4(sp)
  87. lw t5, RV_STK_T5(sp)
  88. lw t6, RV_STK_T6(sp)
  89. addi sp, sp, CONTEXT_SIZE
  90. .endm
  91. .macro restore_mepc
  92. lw t0, RV_STK_MEPC(sp)
  93. csrw mepc, t0
  94. .endm
  95. .global rtos_int_enter
  96. .global rtos_int_exit
  97. .global _global_interrupt_handler
  98. .section .exception_vectors.text
  99. /* This is the vector table. MTVEC points here.
  100. *
  101. * Use 4-byte intructions here. 1 instruction = 1 entry of the table.
  102. * The CPU jumps to MTVEC (i.e. the first entry) in case of an exception,
  103. * and (MTVEC & 0xfffffffc) + (mcause & 0x7fffffff) * 4, in case of an interrupt.
  104. *
  105. * Note: for our CPU, we need to place this on a 256-byte boundary, as CPU
  106. * only uses the 24 MSBs of the MTVEC, i.e. (MTVEC & 0xffffff00).
  107. */
  108. .balign 0x100
  109. .global _vector_table
  110. .type _vector_table, @function
  111. _vector_table:
  112. .option push
  113. .option norvc
  114. j _panic_handler /* exception handler, entry 0 */
  115. .rept (ETS_T1_WDT_INUM - 1)
  116. j _interrupt_handler /* 24 identical entries, all pointing to the interrupt handler */
  117. .endr
  118. j _panic_handler /* Call panic handler for ETS_T1_WDT_INUM interrupt (soc-level panic)*/
  119. j _panic_handler /* Call panic handler for ETS_CACHEERR_INUM interrupt (soc-level panic)*/
  120. #ifdef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
  121. j _panic_handler /* Call panic handler for ETS_MEMPROT_ERR_INUM interrupt (soc-level panic)*/
  122. .rept (ETS_MAX_INUM - ETS_MEMPROT_ERR_INUM)
  123. #else
  124. .rept (ETS_MAX_INUM - ETS_CACHEERR_INUM)
  125. #endif
  126. j _interrupt_handler /* 6 identical entries, all pointing to the interrupt handler */
  127. .endr
  128. .option pop
  129. .size _vector_table, .-_vector_table
  130. /* Exception handler.*/
  131. .type _panic_handler, @function
  132. _panic_handler:
  133. addi sp, sp, -RV_STK_FRMSZ /* allocate space on stack to store necessary registers */
  134. /* save general registers */
  135. sw ra, RV_STK_RA(sp)
  136. sw gp, RV_STK_GP(sp)
  137. sw tp, RV_STK_TP(sp)
  138. sw t0, RV_STK_T0(sp)
  139. sw t1, RV_STK_T1(sp)
  140. sw t2, RV_STK_T2(sp)
  141. sw s0, RV_STK_S0(sp)
  142. sw s1, RV_STK_S1(sp)
  143. sw a0, RV_STK_A0(sp)
  144. sw a1, RV_STK_A1(sp)
  145. sw a2, RV_STK_A2(sp)
  146. sw a3, RV_STK_A3(sp)
  147. sw a4, RV_STK_A4(sp)
  148. sw a5, RV_STK_A5(sp)
  149. sw a6, RV_STK_A6(sp)
  150. sw a7, RV_STK_A7(sp)
  151. sw s2, RV_STK_S2(sp)
  152. sw s3, RV_STK_S3(sp)
  153. sw s4, RV_STK_S4(sp)
  154. sw s5, RV_STK_S5(sp)
  155. sw s6, RV_STK_S6(sp)
  156. sw s7, RV_STK_S7(sp)
  157. sw s8, RV_STK_S8(sp)
  158. sw s9, RV_STK_S9(sp)
  159. sw s10, RV_STK_S10(sp)
  160. sw s11, RV_STK_S11(sp)
  161. sw t3, RV_STK_T3(sp)
  162. sw t4, RV_STK_T4(sp)
  163. sw t5, RV_STK_T5(sp)
  164. sw t6, RV_STK_T6(sp)
  165. addi t0, sp, RV_STK_FRMSZ /* restore sp with the value when trap happened */
  166. sw t0, RV_STK_SP(sp)
  167. csrr t0, mepc
  168. sw t0, RV_STK_MEPC(sp)
  169. csrr t0, mstatus
  170. sw t0, RV_STK_MSTATUS(sp)
  171. csrr t0, mtvec
  172. sw t0, RV_STK_MTVEC(sp)
  173. csrr t0, mtval
  174. sw t0, RV_STK_MTVAL(sp)
  175. csrr t0, mhartid
  176. sw t0, RV_STK_MHARTID(sp)
  177. /* Call panic_from_exception(sp) or panic_from_isr(sp)
  178. * depending on whether we have a pseudo excause or not.
  179. * If mcause's highest bit is 1, then an interrupt called this routine,
  180. * so we have a pseudo excause. Else, it is due to a exception, we don't
  181. * have an pseudo excause */
  182. mv a0, sp
  183. csrr a1, mcause
  184. /* Branches instructions don't accept immediates values, so use t1 to
  185. * store our comparator */
  186. li t0, 0x80000000
  187. bgeu a1, t0, _call_panic_handler
  188. sw a1, RV_STK_MCAUSE(sp)
  189. /* exception_from_panic never returns */
  190. j panic_from_exception
  191. _call_panic_handler:
  192. /* Remove highest bit from mcause (a1) register and save it in the
  193. * structure */
  194. not t0, t0
  195. and a1, a1, t0
  196. sw a1, RV_STK_MCAUSE(sp)
  197. /* exception_from_isr never returns */
  198. j panic_from_isr
  199. .size panic_from_isr, .-panic_from_isr
  200. /* This is the interrupt handler.
  201. * It saves the registers on the stack,
  202. * prepares for interrupt nesting,
  203. * re-enables the interrupts,
  204. * then jumps to the C dispatcher in interrupt.c.
  205. */
  206. .global _interrupt_handler
  207. .type _interrupt_handler, @function
  208. _interrupt_handler:
  209. /* entry */
  210. save_regs
  211. save_mepc
  212. /* Before doing anythig preserve the stack pointer */
  213. /* It will be saved in current TCB, if needed */
  214. mv a0, sp
  215. call rtos_int_enter
  216. /* Before dispatch c handler, restore interrupt to enable nested intr */
  217. csrr s1, mcause
  218. csrr s2, mstatus
  219. /* Save the interrupt threshold level */
  220. la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG
  221. lw s3, 0(t0)
  222. /* Increase interrupt threshold level */
  223. li t2, 0x7fffffff
  224. and t1, s1, t2 /* t1 = mcause & mask */
  225. slli t1, t1, 2 /* t1 = mcause * 4 */
  226. la t2, INTC_INT_PRIO_REG(0)
  227. add t1, t2, t1 /* t1 = INTC_INT_PRIO_REG + 4 * mcause */
  228. lw t2, 0(t1) /* t2 = INTC_INT_PRIO_REG[mcause] */
  229. addi t2, t2, 1 /* t2 = t2 +1 */
  230. sw t2, 0(t0) /* INTERRUPT_CORE0_CPU_INT_THRESH_REG = t2 */
  231. fence
  232. li t0, 0x8
  233. csrrs t0, mstatus, t0
  234. #ifdef CONFIG_PM_TRACE
  235. li a0, 0 /* = ESP_PM_TRACE_IDLE */
  236. #if SOC_CPU_CORES_NUM == 1
  237. li a1, 0 /* No need to check core ID on single core hardware */
  238. #else
  239. csrr a1, mhartid
  240. #endif
  241. la t0, esp_pm_trace_exit
  242. jalr t0 /* absolute jump, avoid the 1 MiB range constraint */
  243. #endif
  244. #ifdef CONFIG_PM_ENABLE
  245. la t0, esp_pm_impl_isr_hook
  246. jalr t0 /* absolute jump, avoid the 1 MiB range constraint */
  247. #endif
  248. /* call the C dispatcher */
  249. mv a0, sp /* argument 1, stack pointer */
  250. csrr a1, mcause /* argument 2, interrupt number */
  251. /* mask off the interrupt flag of mcause */
  252. li t0, 0x7fffffff
  253. and a1, a1, t0
  254. jal _global_interrupt_handler
  255. /* After dispatch c handler, disable interrupt to make freertos make context switch */
  256. la t0, 0x8
  257. csrrc t0, mstatus, t0
  258. /* restore the interrupt threshold level */
  259. la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG
  260. sw s3, 0(t0)
  261. fence
  262. /* Yield to the next task is needed: */
  263. mv a0, sp
  264. call rtos_int_exit
  265. /* The next (or current) stack pointer is returned in a0 */
  266. mv sp, a0
  267. /* restore the rest of the registers */
  268. csrw mcause, s1
  269. csrw mstatus, s2
  270. restore_mepc
  271. restore_regs
  272. /* exit, this will also re-enable the interrupts */
  273. mret
  274. .size _interrupt_handler, .-_interrupt_handler