hli_vectors.S 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /*
  2. * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <xtensa/coreasm.h>
  7. #include <xtensa/corebits.h>
  8. #include <xtensa/config/system.h>
  9. #include "freertos/xtensa_context.h"
  10. #include "sdkconfig.h"
  11. #include "soc/soc.h"
  12. #if CONFIG_BTDM_CTRL_HLI
  13. /* Interrupt stack size, for C code.
  14. * TODO: reduce and make configurable.
  15. */
  16. #define L4_INTR_STACK_SIZE 4096
  17. /* Save area for the CPU state:
  18. * - 64 words for the general purpose registers
  19. * - 7 words for some of the special registers:
  20. * - WINDOWBASE, WINDOWSTART — only WINDOWSTART is truly needed
  21. * - SAR, LBEG, LEND, LCOUNT — since the C code might use these
  22. * - EPC1 — since the C code might cause window overflow exceptions
  23. * This is not laid out as standard exception frame structure
  24. * for simplicity of the save/restore code.
  25. */
  26. #define REG_FILE_SIZE (64 * 4)
  27. #define SPECREG_OFFSET REG_FILE_SIZE
  28. #define SPECREG_SIZE (7 * 4)
  29. #define REG_SAVE_AREA_SIZE (SPECREG_OFFSET + SPECREG_SIZE)
  30. .data
  31. _l4_intr_stack:
  32. .space L4_INTR_STACK_SIZE
  33. _l4_save_ctx:
  34. .space REG_SAVE_AREA_SIZE
  35. .section .iram1,"ax"
  36. .global xt_highint4
  37. .type xt_highint4,@function
  38. .align 4
  39. xt_highint4:
  40. #if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX
  41. /*
  42. Here, Timer2 is used to count a little time(50us).
  43. The subsequent dram0 write operation is blocked due to live lock, which will
  44. cause timer2 to timeout and trigger a level 5 interrupt.
  45. */
  46. rsr.ccount a0
  47. addmi a0, a0, (CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ*50)
  48. wsr a0, CCOMPARE2
  49. /* Enable Timer 2 interrupt */
  50. rsr a0, INTENABLE
  51. extui a0, a0, 16, 1
  52. bnez a0, 1f
  53. movi a0, 0
  54. xsr a0, INTENABLE /* disable all interrupts */
  55. /* And a0 with (1 << 16) for Timer 2 interrupt mask */
  56. addmi a0, a0, (1<<14)
  57. addmi a0, a0, (1<<14)
  58. addmi a0, a0, (1<<14)
  59. addmi a0, a0, (1<<14)
  60. wsr a0, INTENABLE /* Enable Timer 2 */
  61. 1:
  62. #endif
  63. movi a0, _l4_save_ctx
  64. /* save 4 lower registers */
  65. s32i a1, a0, 4
  66. s32i a2, a0, 8
  67. s32i a3, a0, 12
  68. rsr a2, EXCSAVE_4 /* holds the value of a0 */
  69. s32i a2, a0, 0
  70. /* Save special registers */
  71. addi a0, a0, SPECREG_OFFSET
  72. rsr a2, WINDOWBASE
  73. s32i a2, a0, 0
  74. rsr a2, WINDOWSTART
  75. s32i a2, a0, 4
  76. rsr a2, SAR
  77. s32i a2, a0, 8
  78. rsr a2, LBEG
  79. s32i a2, a0, 12
  80. rsr a2, LEND
  81. s32i a2, a0, 16
  82. rsr a2, LCOUNT
  83. s32i a2, a0, 20
  84. rsr a2, EPC1
  85. s32i a2, a0, 24
  86. #if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX
  87. movi a0, 0
  88. xsr a0, INTENABLE /* disable all interrupts */
  89. movi a2, ~(1<<16)
  90. and a0, a2, a0
  91. wsr a0, INTENABLE
  92. #endif
  93. /* disable exception mode, window overflow */
  94. movi a0, PS_INTLEVEL(5) | PS_EXCM
  95. wsr a0, PS
  96. rsync
  97. /* Save the remaining physical registers.
  98. * 4 registers are already saved, which leaves 60 registers to save.
  99. * (FIXME: consider the case when the CPU is configured with physical 32 registers)
  100. * These 60 registers are saved in 5 iterations, 12 registers at a time.
  101. */
  102. movi a1, 5
  103. movi a3, _l4_save_ctx + 4 * 4
  104. /* This is repeated 5 times, each time the window is shifted by 12 registers.
  105. * We come here with a1 = downcounter, a3 = save pointer, a2 and a0 unused.
  106. */
  107. 1:
  108. s32i a4, a3, 0
  109. s32i a5, a3, 4
  110. s32i a6, a3, 8
  111. s32i a7, a3, 12
  112. s32i a8, a3, 16
  113. s32i a9, a3, 20
  114. s32i a10, a3, 24
  115. s32i a11, a3, 28
  116. s32i a12, a3, 32
  117. s32i a13, a3, 36
  118. s32i a14, a3, 40
  119. s32i a15, a3, 44
  120. /* We are about to rotate the window, so that a12-a15 will become the new a0-a3.
  121. * Copy a0-a3 to a12-15 to still have access to these values.
  122. * At the same time we can decrement the counter and adjust the save area pointer
  123. */
  124. /* a0 is constant (_l4_save_ctx), no need to copy */
  125. addi a13, a1, -1 /* copy and decrement the downcounter */
  126. /* a2 is scratch so no need to copy */
  127. addi a15, a3, 48 /* copy and adjust the save area pointer */
  128. beqz a13, 2f /* have saved all registers ? */
  129. rotw 3 /* rotate the window and go back */
  130. j 1b
  131. /* the loop is complete */
  132. 2:
  133. rotw 4 /* this brings us back to the original window */
  134. /* a0 still points to _l4_save_ctx */
  135. /* Can clear WINDOWSTART now, all registers are saved */
  136. rsr a2, WINDOWBASE
  137. /* WINDOWSTART = (1 << WINDOWBASE) */
  138. movi a3, 1
  139. ssl a2
  140. sll a3, a3
  141. wsr a3, WINDOWSTART
  142. _highint4_stack_switch:
  143. movi a0, 0
  144. movi sp, _l4_intr_stack + L4_INTR_STACK_SIZE - 16
  145. s32e a0, sp, -12 /* For GDB: set null SP */
  146. s32e a0, sp, -16 /* For GDB: set null PC */
  147. movi a0, _highint4_stack_switch /* For GDB: cosmetics, for the frame where stack switch happened */
  148. /* Set up PS for C, disable all interrupts except NMI and debug, and clear EXCM. */
  149. movi a6, PS_INTLEVEL(4) | PS_UM | PS_WOE
  150. wsr a6, PS
  151. rsync
  152. /* Call C handler */
  153. mov a6, sp
  154. call4 hli_c_handler
  155. l32e sp, sp, -12 /* switch back to the original stack */
  156. /* Done with C handler; re-enable exception mode, disabling window overflow */
  157. movi a2, PS_INTLEVEL(5) | PS_EXCM /* TOCHECK */
  158. wsr a2, PS
  159. rsync
  160. /* Restore the special registers.
  161. * WINDOWSTART will be restored near the end.
  162. */
  163. movi a0, _l4_save_ctx + SPECREG_OFFSET
  164. l32i a2, a0, 8
  165. wsr a2, SAR
  166. l32i a2, a0, 12
  167. wsr a2, LBEG
  168. l32i a2, a0, 16
  169. wsr a2, LEND
  170. l32i a2, a0, 20
  171. wsr a2, LCOUNT
  172. l32i a2, a0, 24
  173. wsr a2, EPC1
  174. /* Restoring the physical registers.
  175. * This is the reverse to the saving process above.
  176. */
  177. /* Rotate back to the final window, then start loading 12 registers at a time,
  178. * in 5 iterations.
  179. * Again, a1 is the downcounter and a3 is the save area pointer.
  180. * After each rotation, a1 and a3 are copied from a13 and a15.
  181. * To simplify the loop, we put the initial values into a13 and a15.
  182. */
  183. rotw -4
  184. movi a15, _l4_save_ctx + 64 * 4 /* point to the end of the save area */
  185. movi a13, 5
  186. 1:
  187. /* Copy a1 and a3 from their previous location,
  188. * at the same time decrementing and adjusting the save area pointer.
  189. */
  190. addi a1, a13, -1
  191. addi a3, a15, -48
  192. /* Load 12 registers */
  193. l32i a4, a3, 0
  194. l32i a5, a3, 4
  195. l32i a6, a3, 8
  196. l32i a7, a3, 12
  197. l32i a8, a3, 16
  198. l32i a9, a3, 20
  199. l32i a10, a3, 24
  200. l32i a11, a3, 28 /* ensure PS and EPC written */
  201. l32i a12, a3, 32
  202. l32i a13, a3, 36
  203. l32i a14, a3, 40
  204. l32i a15, a3, 44
  205. /* Done with the loop? */
  206. beqz a1, 2f
  207. /* If no, rotate the window and repeat */
  208. rotw -3
  209. j 1b
  210. 2:
  211. /* Done with the loop. Only 4 registers (a0-a3 in the original window) remain
  212. * to be restored. Also need to restore WINDOWSTART, since all the general
  213. * registers are now in place.
  214. */
  215. movi a0, _l4_save_ctx
  216. l32i a2, a0, SPECREG_OFFSET + 4
  217. wsr a2, WINDOWSTART
  218. l32i a1, a0, 4
  219. l32i a2, a0, 8
  220. l32i a3, a0, 12
  221. rsr a0, EXCSAVE_4 /* holds the value of a0 before the interrupt handler */
  222. /* Return from the interrupt, restoring PS from EPS_4 */
  223. rfi 4
  224. #endif /* CONFIG_BTDM_CTRL_HLI */
  225. /* The linker has no reason to link in this file; all symbols it exports are already defined
  226. (weakly!) in the default int handler. Define a symbol here so we can use it to have the
  227. linker inspect this anyway. */
  228. .global ld_include_hli_vectors_bt
  229. ld_include_hli_vectors_bt: