context_gcc.S 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /*
  2. * Copyright (c) 2020-2020, Bluetrum Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020/11/18 greedyhao The first version.
  9. */
  10. #include "ab32vg1.h"
  11. .global rt_interrupt_from_thread
  12. .global rt_interrupt_to_thread
  13. .global rt_cur_thread_sp
  14. .global rt_thread_switch_interrupt_flag
  15. .global rt_interrupt_nest
  16. /*
  17. * rt_base_t rt_hw_interrupt_disable();
  18. * a0 -> return
  19. */
  20. .global rt_hw_interrupt_disable
  21. rt_hw_interrupt_disable:
  22. lw a5, PICCON(zero)
  23. mv a0, a5
  24. andi a5, a5, -2
  25. sw a5, PICCON(zero)
  26. ret
  27. /*
  28. * void rt_hw_interrupt_enable(rt_base_t level);
  29. * a0 -> level
  30. */
  31. .global rt_hw_interrupt_enable
  32. rt_hw_interrupt_enable:
  33. andi a0, a0, 1
  34. beqz a0,enable_int_ret
  35. lw a5, PICCON(zero)
  36. ori a5, a5, 1
  37. sw a5,PICCON(zero)
  38. enable_int_ret:
  39. ret
  40. /* Macro for saving task context */
  41. .macro save_context
  42. addi sp, sp, -124
  43. /* Save Context */
  44. sw x1, 0(sp)
  45. sw x4, 4(sp)
  46. sw x5, 8(sp)
  47. sw x6, 12(sp)
  48. sw x7, 16(sp)
  49. sw x8, 20(sp)
  50. sw x9, 24(sp)
  51. sw x10, 28(sp)
  52. sw x11, 32(sp)
  53. sw x12, 36(sp)
  54. sw x13, 40(sp)
  55. sw x14, 44(sp)
  56. sw x15, 48(sp)
  57. sw x16, 52(sp)
  58. sw x17, 56(sp)
  59. sw x18, 60(sp)
  60. sw x19, 64(sp)
  61. sw x20, 68(sp)
  62. sw x21, 72(sp)
  63. sw x22, 76(sp)
  64. sw x23, 80(sp)
  65. sw x24, 84(sp)
  66. sw x25, 88(sp)
  67. sw x26, 92(sp)
  68. sw x27, 96(sp)
  69. sw x28, 100(sp)
  70. sw x29, 104(sp)
  71. sw x30, 108(sp)
  72. sw x31, 112(sp)
  73. lw a5, EPC(zero) //Saves current program counter (EPC) as task program counter
  74. sw a5, 116(sp)
  75. lw a5, EPICCON(zero)
  76. sw a5, 120(sp)
  77. sw sp, rt_cur_thread_sp, a4 //store sp in preempted tasks tcb
  78. .endm
  79. /* Macro for restoring task context */
  80. .macro restore_context
  81. la a5, rt_cur_thread_sp
  82. lw sp, 0(a5) //get new task stack pointer
  83. /* Load task program counter EPC*/
  84. lw a5, 116(sp)
  85. sw a5, EPC(zero)
  86. lw a5, 120(sp)
  87. sw a5, EPICCON(zero)
  88. /* Restore registers,
  89. Skip global pointer because that does not change */
  90. lw x1, 0(sp)
  91. lw x4, 4(sp)
  92. lw x5, 8(sp)
  93. lw x6, 12(sp)
  94. lw x7, 16(sp)
  95. lw x8, 20(sp)
  96. lw x9, 24(sp)
  97. lw x10, 28(sp)
  98. lw x11, 32(sp)
  99. lw x12, 36(sp)
  100. lw x13, 40(sp)
  101. lw x14, 44(sp)
  102. lw x15, 48(sp)
  103. lw x16, 52(sp)
  104. lw x17, 56(sp)
  105. lw x18, 60(sp)
  106. lw x19, 64(sp)
  107. lw x20, 68(sp)
  108. lw x21, 72(sp)
  109. lw x22, 76(sp)
  110. lw x23, 80(sp)
  111. lw x24, 84(sp)
  112. lw x25, 88(sp)
  113. lw x26, 92(sp)
  114. lw x27, 96(sp)
  115. lw x28, 100(sp)
  116. lw x29, 104(sp)
  117. lw x30, 108(sp)
  118. lw x31, 112(sp)
  119. addi sp, sp, 124
  120. mret
  121. .endm
  122. /*
  123. * void rt_hw_context_switch_to(rt_uint32 to);
  124. * r0 --> to
  125. */
  126. .globl rt_hw_context_switch_to
  127. rt_hw_context_switch_to:
  128. sw zero, rt_interrupt_from_thread, a4 /*set from thread to 0*/
  129. sw a0, rt_interrupt_to_thread, a4 /*set rt_interrupt_to_thread*/
  130. sb zero, rt_interrupt_nest, a4 /*rt_interrupt_nest = 0*/
  131. li a5, 1
  132. sw a5, rt_thread_switch_interrupt_flag, a4 // rt_thread_switch_interrupt_flag = 1;
  133. SWINT /*kick soft interrupt*/
  134. lw a5, PICCON(zero) /*enable interrupt*/
  135. ori a5, a5, 1
  136. sw a5, PICCON(zero)
  137. ret
  138. /*
  139. * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
  140. * a0 --> from
  141. * a1 --> to
  142. */
  143. .globl rt_hw_context_switch
  144. rt_hw_context_switch:
  145. sw a0, rt_interrupt_from_thread, a4 /*set rt_interrupt_from_thread*/
  146. sw a1, rt_interrupt_to_thread, a4 /*set rt_interrupt_to_thread*/
  147. li a5, 1
  148. sw a5, rt_thread_switch_interrupt_flag, a4 /*rt_thread_switch_interrupt_flag = 1*/
  149. SWINT /*kick soft interrupt*/
  150. ret
  151. /*
  152. * void rt_switch_to_thread(void);
  153. * r0 --> to
  154. */
  155. .globl rt_switch_to_thread
  156. rt_switch_to_thread:
  157. lw a0, rt_interrupt_from_thread
  158. lw a5, rt_cur_thread_sp
  159. sw a5, 0(a0)
  160. lw a0, rt_interrupt_to_thread
  161. lw a5, 0(a0)
  162. sw a5, rt_cur_thread_sp, a4
  163. ret
  164. /*
  165. * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
  166. * a0 --> from
  167. * a1 --> to
  168. */
  169. .global rt_hw_context_switch_interrupt
  170. rt_hw_context_switch_interrupt:
  171. lw a5, rt_thread_switch_interrupt_flag
  172. bnez a5, _reswitch
  173. li a5, 0x01
  174. sw a5, rt_thread_switch_interrupt_flag, a4
  175. sw a0, rt_interrupt_from_thread, a4 /*set rt_interrupt_from_thread*/
  176. _reswitch:
  177. sw a1, rt_interrupt_to_thread, a4 /*set rt_interrupt_to_thread*/
  178. ret
  179. //软中断服务
  180. .global rt_soft_isr
  181. rt_soft_isr:
  182. li a5, 0x4 // PICPND = BIT(IRQ_SW_VECTOR); 清软中断Pending
  183. sw a5, PICPND(zero)
  184. ret
  185. .globl low_prio_irq
  186. low_prio_irq:
  187. save_context
  188. lw a5, rt_interrupt_nest
  189. bnez a5, _low_prio_irq_exit
  190. lw a5, cpu_irq_comm_hook
  191. jalr a5
  192. lw a5, rt_thread_switch_interrupt_flag
  193. beqz a5, _low_prio_irq_exit // if (rt_thread_switch_interrupt_flag)
  194. jal rt_switch_to_thread
  195. sw zero, rt_thread_switch_interrupt_flag, a4 // rt_thread_switch_interrupt_flag = 0;
  196. _low_prio_irq_exit:
  197. restore_context