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