context_gcc.S 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*
  2. * Copyright (c) 2006-2019, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2013-07-05 Bernard the first version
  9. * 2019-07-28 zdzn add smp support
  10. */
  11. #include "../rtconfig.h"
  12. .section .text, "ax"
  13. #ifdef RT_USING_SMP
  14. #define rt_hw_interrupt_disable rt_hw_local_irq_disable
  15. #define rt_hw_interrupt_enable rt_hw_local_irq_enable
  16. #endif
  17. /*
  18. * rt_base_t rt_hw_interrupt_disable();
  19. */
  20. .globl rt_hw_interrupt_disable
  21. rt_hw_interrupt_disable:
  22. mrs r0, cpsr
  23. cpsid i
  24. bx lr
  25. /*
  26. * void rt_hw_interrupt_enable(rt_base_t level);
  27. */
  28. .globl rt_hw_interrupt_enable
  29. rt_hw_interrupt_enable:
  30. msr cpsr, r0
  31. bx lr
  32. /*
  33. * void rt_hw_context_switch_to(rt_uint32 to, struct rt_thread *to_thread);
  34. * r0 --> to (thread stack)
  35. * r1 --> to_thread
  36. */
  37. .globl rt_hw_context_switch_to
  38. rt_hw_context_switch_to:
  39. ldr sp, [r0] @ get new task stack pointer
  40. #ifdef RT_USING_SMP
  41. mov r0, r1
  42. bl rt_cpus_lock_status_restore
  43. #endif /*RT_USING_SMP*/
  44. b rt_hw_context_switch_exit
  45. .section .bss.share.isr
  46. _guest_switch_lvl:
  47. .word 0
  48. .globl vmm_virq_update
  49. .section .text.isr, "ax"
  50. /*
  51. * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to, struct rt_thread *to_thread);
  52. * r0 --> from (from_thread stack)
  53. * r1 --> to (to_thread stack)
  54. * r2 --> to_thread
  55. */
  56. .globl rt_hw_context_switch
  57. rt_hw_context_switch:
  58. stmfd sp!, {lr} @ push pc (lr should be pushed in place of PC)
  59. stmfd sp!, {r0-r12, lr} @ push lr & register file
  60. mrs r4, cpsr
  61. tst lr, #0x01
  62. orrne r4, r4, #0x20 @ it's thumb code
  63. stmfd sp!, {r4} @ push cpsr
  64. #ifdef RT_USING_LWP
  65. stmfd sp, {r13, r14}^ @ push usr_sp usr_lr
  66. sub sp, #8
  67. #endif
  68. #ifdef RT_USING_FPU
  69. /* fpu context */
  70. vmrs r6, fpexc
  71. tst r6, #(1<<30)
  72. beq 1f
  73. vstmdb sp!, {d0-d15}
  74. vstmdb sp!, {d16-d31}
  75. vmrs r5, fpscr
  76. stmfd sp!, {r5}
  77. 1:
  78. stmfd sp!, {r6}
  79. #endif
  80. str sp, [r0] @ store sp in preempted tasks TCB
  81. ldr sp, [r1] @ get new task stack pointer
  82. #ifdef RT_USING_SMP
  83. mov r0, r2
  84. bl rt_cpus_lock_status_restore
  85. #endif /*RT_USING_SMP*/
  86. b rt_hw_context_switch_exit
  87. /*
  88. * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
  89. */
  90. .equ Mode_USR, 0x10
  91. .equ Mode_FIQ, 0x11
  92. .equ Mode_IRQ, 0x12
  93. .equ Mode_SVC, 0x13
  94. .equ Mode_ABT, 0x17
  95. .equ Mode_UND, 0x1B
  96. .equ Mode_SYS, 0x1F
  97. .equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled
  98. .equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled
  99. .globl rt_thread_switch_interrupt_flag
  100. .globl rt_interrupt_from_thread
  101. .globl rt_interrupt_to_thread
  102. .globl rt_hw_context_switch_interrupt
  103. rt_hw_context_switch_interrupt:
  104. #ifdef RT_USING_SMP
  105. /* r0 :svc_mod context
  106. * r1 :addr of from_thread's sp
  107. * r2 :addr of to_thread's sp
  108. * r3 :to_thread's tcb
  109. */
  110. str r0, [r1]
  111. ldr sp, [r2]
  112. mov r0, r3
  113. bl rt_cpus_lock_status_restore
  114. b rt_hw_context_switch_exit
  115. #else /*RT_USING_SMP*/
  116. ldr r2, =rt_thread_switch_interrupt_flag
  117. ldr r3, [r2]
  118. cmp r3, #1
  119. beq _reswitch
  120. ldr ip, =rt_interrupt_from_thread @ set rt_interrupt_from_thread
  121. mov r3, #1 @ set rt_thread_switch_interrupt_flag to 1
  122. str r0, [ip]
  123. str r3, [r2]
  124. _reswitch:
  125. ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread
  126. str r1, [r2]
  127. bx lr
  128. #endif /*RT_USING_SMP*/
  129. .global rt_hw_context_switch_exit
  130. rt_hw_context_switch_exit:
  131. #ifdef RT_USING_SMP
  132. #ifdef RT_USING_SIGNALS
  133. mov r0, sp
  134. cps #Mode_IRQ
  135. bl rt_signal_check
  136. cps #Mode_SVC
  137. mov sp, r0
  138. #endif
  139. #endif
  140. #ifdef RT_USING_FPU
  141. /* fpu context */
  142. ldmfd sp!, {r6}
  143. vmsr fpexc, r6
  144. tst r6, #(1<<30)
  145. beq 1f
  146. ldmfd sp!, {r5}
  147. vmsr fpscr, r5
  148. vldmia sp!, {d16-d31}
  149. vldmia sp!, {d0-d15}
  150. #endif
  151. #ifdef RT_USING_LWP
  152. ldmfd sp, {r13, r14}^ /* usr_sp, usr_lr */
  153. add sp, #8
  154. #endif
  155. ldmfd sp!, {r4}
  156. msr spsr_cxsf, r4 /* original mode */
  157. ldmfd sp!, {r0-r12,lr,pc}^ /* irq return */