context_ccs.asm 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. ;/*
  2. ; * Copyright (c) 2006-2022, RT-Thread Development Team
  3. ; *
  4. ; * SPDX-License-Identifier: Apache-2.0
  5. ; *
  6. ; * Change Logs:
  7. ; * Date Author Notes
  8. ; * 2009-01-20 Bernard first version
  9. ; * 2011-07-22 Bernard added thumb mode porting
  10. ; * 2013-05-24 Grissiom port to CCS
  11. ; * 2013-05-26 Grissiom optimize for ARMv7
  12. ; */
  13. .text
  14. .arm
  15. .ref rt_thread_switch_interrupt_flag
  16. .ref rt_interrupt_from_thread
  17. .ref rt_interrupt_to_thread
  18. .ref rt_interrupt_enter
  19. .ref rt_interrupt_leave
  20. .ref rt_hw_trap_irq
  21. ;/*
  22. ; * rt_base_t rt_hw_interrupt_disable();
  23. ; */
  24. .def rt_hw_interrupt_disable
  25. .asmfunc
  26. rt_hw_interrupt_disable
  27. MRS r0, cpsr
  28. CPSID IF
  29. BX lr
  30. .endasmfunc
  31. ;/*
  32. ; * void rt_hw_interrupt_enable(rt_base_t level);
  33. ; */
  34. .def rt_hw_interrupt_enable
  35. .asmfunc
  36. rt_hw_interrupt_enable
  37. MSR cpsr_c, r0
  38. BX lr
  39. .endasmfunc
  40. ;/*
  41. ; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
  42. ; * r0 --> from
  43. ; * r1 --> to
  44. ; */
  45. .def rt_hw_context_switch
  46. .asmfunc
  47. rt_hw_context_switch
  48. STMDB sp!, {lr} ; push pc (lr should be pushed in place of PC)
  49. STMDB sp!, {r0-r12, lr} ; push lr & register file
  50. MRS r4, cpsr
  51. TST lr, #0x01
  52. ORRNE r4, r4, #0x20 ; it's thumb code
  53. STMDB sp!, {r4} ; push cpsr
  54. .if (__TI_VFP_SUPPORT__)
  55. VMRS r4, fpexc
  56. TST r4, #0x40000000
  57. BEQ __no_vfp_frame1
  58. VSTMDB sp!, {d0-d15}
  59. VMRS r5, fpscr
  60. ; TODO: add support for Common VFPv3.
  61. ; Save registers like FPINST, FPINST2
  62. STMDB sp!, {r5}
  63. __no_vfp_frame1
  64. STMDB sp!, {r4}
  65. .endif
  66. STR sp, [r0] ; store sp in preempted tasks TCB
  67. LDR sp, [r1] ; get new task stack pointer
  68. .if (__TI_VFP_SUPPORT__)
  69. LDMIA sp!, {r0} ; get fpexc
  70. VMSR fpexc, r0 ; restore fpexc
  71. TST r0, #0x40000000
  72. BEQ __no_vfp_frame2
  73. LDMIA sp!, {r1} ; get fpscr
  74. VMSR fpscr, r1
  75. VLDMIA sp!, {d0-d15}
  76. __no_vfp_frame2
  77. .endif
  78. LDMIA sp!, {r4} ; pop new task cpsr to spsr
  79. MSR spsr_cxsf, r4
  80. LDMIA sp!, {r0-r12, lr, pc}^ ; pop new task r0-r12, lr & pc, copy spsr to cpsr
  81. .endasmfunc
  82. ;/*
  83. ; * void rt_hw_context_switch_to(rt_uint32 to);
  84. ; * r0 --> to
  85. ; */
  86. .def rt_hw_context_switch_to
  87. .asmfunc
  88. rt_hw_context_switch_to
  89. LDR sp, [r0] ; get new task stack pointer
  90. .if (__TI_VFP_SUPPORT__)
  91. LDMIA sp!, {r0} ; get fpexc
  92. VMSR fpexc, r0
  93. TST r0, #0x40000000
  94. BEQ __no_vfp_frame_to
  95. LDMIA sp!, {r1} ; get fpscr
  96. VMSR fpscr, r1
  97. VLDMIA sp!, {d0-d15}
  98. __no_vfp_frame_to
  99. .endif
  100. LDMIA sp!, {r4} ; pop new task cpsr to spsr
  101. MSR spsr_cxsf, r4
  102. LDMIA sp!, {r0-r12, lr, pc}^ ; pop new task r0-r12, lr & pc, copy spsr to cpsr
  103. .endasmfunc
  104. ;/*
  105. ; * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
  106. ; */
  107. .def rt_hw_context_switch_interrupt
  108. .asmfunc
  109. rt_hw_context_switch_interrupt
  110. LDR r2, pintflag
  111. LDR r3, [r2]
  112. CMP r3, #1
  113. BEQ _reswitch
  114. MOV r3, #1 ; set rt_thread_switch_interrupt_flag to 1
  115. STR r3, [r2]
  116. LDR r2, pfromthread ; set rt_interrupt_from_thread
  117. STR r0, [r2]
  118. _reswitch
  119. LDR r2, ptothread ; set rt_interrupt_to_thread
  120. STR r1, [r2]
  121. BX lr
  122. .endasmfunc
  123. .def IRQ_Handler
  124. IRQ_Handler
  125. STMDB sp!, {r0-r12,lr}
  126. .if (__TI_VFP_SUPPORT__)
  127. VMRS r0, fpexc
  128. TST r0, #0x40000000
  129. BEQ __no_vfp_frame_str_irq
  130. VSTMDB sp!, {d0-d15}
  131. VMRS r1, fpscr
  132. ; TODO: add support for Common VFPv3.
  133. ; Save registers like FPINST, FPINST2
  134. STMDB sp!, {r1}
  135. __no_vfp_frame_str_irq
  136. STMDB sp!, {r0}
  137. .endif
  138. BL rt_interrupt_enter
  139. BL rt_hw_trap_irq
  140. BL rt_interrupt_leave
  141. ; if rt_thread_switch_interrupt_flag set, jump to
  142. ; rt_hw_context_switch_interrupt_do and don't return
  143. LDR r0, pintflag
  144. LDR r1, [r0]
  145. CMP r1, #1
  146. BEQ rt_hw_context_switch_interrupt_do
  147. .if (__TI_VFP_SUPPORT__)
  148. LDMIA sp!, {r0} ; get fpexc
  149. VMSR fpexc, r0
  150. TST r0, #0x40000000
  151. BEQ __no_vfp_frame_ldr_irq
  152. LDMIA sp!, {r1} ; get fpscr
  153. VMSR fpscr, r1
  154. VLDMIA sp!, {d0-d15}
  155. __no_vfp_frame_ldr_irq
  156. .endif
  157. LDMIA sp!, {r0-r12,lr}
  158. SUBS pc, lr, #4
  159. ; /*
  160. ; * void rt_hw_context_switch_interrupt_do(rt_base_t flag)
  161. ; */
  162. .def rt_hw_context_switch_interrupt_do
  163. rt_hw_context_switch_interrupt_do
  164. MOV r1, #0 ; clear flag
  165. STR r1, [r0]
  166. .if (__TI_VFP_SUPPORT__)
  167. LDMIA sp!, {r0} ; get fpexc
  168. VMSR fpexc, r0
  169. TST r0, #0x40000000
  170. BEQ __no_vfp_frame_do1
  171. LDMIA sp!, {r1} ; get fpscr
  172. VMSR fpscr, r1
  173. VLDMIA sp!, {d0-d15}
  174. __no_vfp_frame_do1
  175. .endif
  176. LDMIA sp!, {r0-r12,lr} ; reload saved registers
  177. STMDB sp, {r0-r3} ; save r0-r3. We will restore r0-r3 in the SVC
  178. ; mode so there is no need to update SP.
  179. SUB r1, sp, #16 ; save the right SP value in r1, so we could restore r0-r3.
  180. SUB r2, lr, #4 ; save old task's pc to r2
  181. MRS r3, spsr ; get cpsr of interrupt thread
  182. ; switch to SVC mode and no interrupt
  183. CPSID IF, #0x13
  184. STMDB sp!, {r2} ; push old task's pc
  185. STMDB sp!, {r4-r12,lr} ; push old task's lr,r12-r4
  186. LDMIA r1!, {r4-r7} ; restore r0-r3 of the interrupted thread
  187. STMDB sp!, {r4-r7} ; push old task's r3-r0. We don't need to push/pop them to
  188. ; r0-r3 because we just want to transfer the data and don't
  189. ; use them here.
  190. STMDB sp!, {r3} ; push old task's cpsr
  191. .if (__TI_VFP_SUPPORT__)
  192. VMRS r0, fpexc
  193. TST r0, #0x40000000
  194. BEQ __no_vfp_frame_do2
  195. VSTMDB sp!, {d0-d15}
  196. VMRS r1, fpscr
  197. ; TODO: add support for Common VFPv3.
  198. ; Save registers like FPINST, FPINST2
  199. STMDB sp!, {r1}
  200. __no_vfp_frame_do2
  201. STMDB sp!, {r0}
  202. .endif
  203. LDR r4, pfromthread
  204. LDR r5, [r4]
  205. STR sp, [r5] ; store sp in preempted tasks's TCB
  206. LDR r6, ptothread
  207. LDR r6, [r6]
  208. LDR sp, [r6] ; get new task's stack pointer
  209. .if (__TI_VFP_SUPPORT__)
  210. LDMIA sp!, {r0} ; get fpexc
  211. VMSR fpexc, r0
  212. TST r0, #0x40000000
  213. BEQ __no_vfp_frame_do3
  214. LDMIA sp!, {r1} ; get fpscr
  215. VMSR fpscr, r1
  216. VLDMIA sp!, {d0-d15}
  217. __no_vfp_frame_do3
  218. .endif
  219. LDMIA sp!, {r4} ; pop new task's cpsr to spsr
  220. MSR spsr_cxsf, r4
  221. LDMIA sp!, {r0-r12,lr,pc}^ ; pop new task's r0-r12,lr & pc, copy spsr to cpsr
  222. pintflag .word rt_thread_switch_interrupt_flag
  223. pfromthread .word rt_interrupt_from_thread
  224. ptothread .word rt_interrupt_to_thread