context_gcc.S 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  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_switch_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, -120
  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. sw sp, rt_cur_thread_sp, a4 //store sp in preempted tasks tcb
  76. .endm
  77. /* Macro for restoring task context */
  78. .macro restore_context
  79. la a5, rt_cur_thread_sp
  80. lw sp, 0(a5) //get new task stack pointer
  81. /* Load task program counter EPC*/
  82. lw a5, 116(sp)
  83. sw a5, EPC(zero)
  84. /* Restore registers,
  85. Skip global pointer because that does not change */
  86. lw x1, 0(sp)
  87. lw x4, 4(sp)
  88. lw x5, 8(sp)
  89. lw x6, 12(sp)
  90. lw x7, 16(sp)
  91. lw x8, 20(sp)
  92. lw x9, 24(sp)
  93. lw x10, 28(sp)
  94. lw x11, 32(sp)
  95. lw x12, 36(sp)
  96. lw x13, 40(sp)
  97. lw x14, 44(sp)
  98. lw x15, 48(sp)
  99. lw x16, 52(sp)
  100. lw x17, 56(sp)
  101. lw x18, 60(sp)
  102. lw x19, 64(sp)
  103. lw x20, 68(sp)
  104. lw x21, 72(sp)
  105. lw x22, 76(sp)
  106. lw x23, 80(sp)
  107. lw x24, 84(sp)
  108. lw x25, 88(sp)
  109. lw x26, 92(sp)
  110. lw x27, 96(sp)
  111. lw x28, 100(sp)
  112. lw x29, 104(sp)
  113. lw x30, 108(sp)
  114. lw x31, 112(sp)
  115. addi sp, sp, 120
  116. mret
  117. .endm
  118. /*
  119. * void rt_hw_context_switch_to(rt_uint32 to);
  120. * r0 --> to
  121. */
  122. .globl rt_hw_context_switch_to
  123. rt_hw_context_switch_to:
  124. sw zero, rt_interrupt_from_thread, a4 /*set from thread to 0*/
  125. sw a0, rt_interrupt_to_thread, a4 /*set rt_interrupt_to_thread*/
  126. sb zero, rt_interrupt_nest, a4 /*rt_interrupt_nest = 0*/
  127. li a5, 1
  128. sw a5, rt_switch_flag, a4 // rt_switch_flag = 1;
  129. SWINT /*kick soft interrupt*/
  130. lw a5, PICCON(zero) /*enable interrupt*/
  131. ori a5, a5, 1
  132. sw a5, PICCON(zero)
  133. ret
  134. /*
  135. * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
  136. * a0 --> from
  137. * a1 --> to
  138. */
  139. .globl rt_hw_context_switch
  140. rt_hw_context_switch:
  141. sw a0, rt_interrupt_from_thread, a4 /*set rt_interrupt_from_thread*/
  142. sw a1, rt_interrupt_to_thread, a4 /*set rt_interrupt_to_thread*/
  143. li a5, 1
  144. sw a5, rt_switch_flag, a4 // rt_switch_flag = 1;
  145. SWINT /*kick soft interrupt*/
  146. ret
  147. /*
  148. * void rt_switch_to_thread(void);
  149. * r0 --> to
  150. */
  151. .globl rt_switch_to_thread
  152. rt_switch_to_thread:
  153. lw a0, rt_interrupt_from_thread
  154. lw a5, rt_cur_thread_sp
  155. sw a5, 0(a0)
  156. lw a0, rt_interrupt_to_thread
  157. lw a5, 0(a0)
  158. sw a5, rt_cur_thread_sp, a4
  159. ret
  160. /*
  161. * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
  162. * a0 --> from
  163. * a1 --> to
  164. */
  165. .global rt_hw_context_switch_interrupt
  166. rt_hw_context_switch_interrupt:
  167. lw a5, rt_switch_flag
  168. bnez a5, _reswitch
  169. li a5, 0x01
  170. sw a5, rt_switch_flag, a4
  171. sw a0, rt_interrupt_from_thread, a4 /*set rt_interrupt_from_thread*/
  172. _reswitch:
  173. sw a1, rt_interrupt_to_thread, a4 /*set rt_interrupt_to_thread*/
  174. ret
  175. //软中断服务
  176. .global rt_soft_isr
  177. rt_soft_isr:
  178. li a5, 0x4 // PICPND = BIT(IRQ_SW_VECTOR); 清软中断Pending
  179. sw a5, PICPND(zero)
  180. ret
  181. .globl low_prio_irq
  182. low_prio_irq:
  183. save_context
  184. li a5, 1
  185. sb a5, rt_interrupt_nest, a4 // rt_interrupt_nest = 1;
  186. lw a5, cpu_irq_comm_hook
  187. jalr a5
  188. lw a5, rt_switch_flag
  189. beqz a5, _low_prio_irq_exit // if (rt_switch_flag)
  190. jal rt_switch_to_thread
  191. sw zero, rt_switch_flag, a4 // rt_switch_flag = 0;
  192. _low_prio_irq_exit:
  193. sb zero, rt_interrupt_nest, a4 // rt_interrupt_nest = 0;
  194. restore_context