context_gcc.S 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /***************************************************************************//**
  2. * @file context_gcc.S
  3. * @brief Context switch functions
  4. * COPYRIGHT (C) 2011, RT-Thread Development Team
  5. * @author Bernard, onelife
  6. * @version 0.4 beta
  7. *******************************************************************************
  8. * @section License
  9. * The license and distribution terms for this file may be found in the file
  10. * LICENSE in this distribution or at http://www.rt-thread.org/license/LICENSE
  11. *******************************************************************************
  12. * @section Change Logs
  13. * Date Author Notes
  14. * 2009-10-11 Bernard first version
  15. * 2010-12-29 onelife Modify for EFM32
  16. * 2011-06-17 onelife Merge all of the assembly source code into
  17. * context_gcc.S
  18. * 2011-07-12 onelife Add interrupt context check function
  19. ******************************************************************************/
  20. /***************************************************************************//**
  21. * @addtogroup cortex-m3
  22. * @{
  23. ******************************************************************************/
  24. .cpu cortex-m3
  25. .fpu softvfp
  26. .syntax unified
  27. .thumb
  28. .text
  29. .equ ICSR, 0xE000ED04 /* interrupt control state register */
  30. .equ PENDSVSET_BIT, 0x10000000 /* value to trigger PendSV exception */
  31. .equ SHPR3, 0xE000ED20 /* system priority register (3) */
  32. .equ PENDSV_PRI_LOWEST, 0x00FF0000 /* PendSV priority value (lowest) */
  33. /*
  34. * rt_base_t rt_hw_interrupt_disable();
  35. */
  36. .global rt_hw_interrupt_disable
  37. .type rt_hw_interrupt_disable, %function
  38. rt_hw_interrupt_disable:
  39. MRS R0, PRIMASK
  40. CPSID I
  41. BX LR
  42. /*
  43. * void rt_hw_interrupt_enable(rt_base_t level);
  44. */
  45. .global rt_hw_interrupt_enable
  46. .type rt_hw_interrupt_enable, %function
  47. rt_hw_interrupt_enable:
  48. MSR PRIMASK, R0
  49. BX LR
  50. /*
  51. * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
  52. * R0 --> from
  53. * R1 --> to
  54. */
  55. .global rt_hw_context_switch_interrupt
  56. .type rt_hw_context_switch_interrupt, %function
  57. .global rt_hw_context_switch
  58. .type rt_hw_context_switch, %function
  59. rt_hw_context_switch_interrupt:
  60. rt_hw_context_switch:
  61. /* set rt_thread_switch_interrupt_flag to 1 */
  62. LDR R2, =rt_thread_switch_interrupt_flag
  63. LDR R3, [R2]
  64. CMP R3, #1
  65. BEQ _reswitch
  66. MOV R3, #1
  67. STR R3, [R2]
  68. LDR R2, =rt_interrupt_from_thread /* set rt_interrupt_from_thread */
  69. STR R0, [R2]
  70. _reswitch:
  71. LDR R2, =rt_interrupt_to_thread /* set rt_interrupt_to_thread */
  72. STR R1, [R2]
  73. LDR R0, =ICSR /* trigger the PendSV exception (causes context switch) */
  74. LDR R1, =PENDSVSET_BIT
  75. STR R1, [R0]
  76. BX LR
  77. /* R0 --> swith from thread stack
  78. * R1 --> swith to thread stack
  79. * psr, pc, LR, R12, R3, R2, R1, R0 are pushed into [from] stack
  80. */
  81. .global PendSV_Handler
  82. .type PendSV_Handler, %function
  83. PendSV_Handler:
  84. /* disable interrupt to protect context switch */
  85. MRS R2, PRIMASK
  86. CPSID I
  87. /* get rt_thread_switch_interrupt_flag */
  88. LDR R0, =rt_thread_switch_interrupt_flag
  89. LDR R1, [R0]
  90. CBZ R1, pendsv_exit /* pendsv aLReady handled */
  91. /* clear rt_thread_switch_interrupt_flag to 0 */
  92. MOV R1, #0
  93. STR R1, [R0]
  94. LDR R0, =rt_interrupt_from_thread
  95. LDR R1, [R0]
  96. CBZ R1, swtich_to_thread /* skip register save at the first time */
  97. MRS R1, PSP /* get from thread stack pointer */
  98. STMFD R1!, {R4 - R11} /* push R4 - R11 register */
  99. LDR R0, [R0]
  100. STR R1, [R0] /* update from thread stack pointer */
  101. swtich_to_thread:
  102. LDR R1, =rt_interrupt_to_thread
  103. LDR R1, [R1]
  104. LDR R1, [R1] /* load thread stack pointer */
  105. LDMFD R1!, {R4 - R11} /* pop R4 - R11 register */
  106. MSR PSP, R1 /* update stack pointer */
  107. pendsv_exit:
  108. /* restore interrupt */
  109. MSR PRIMASK, R2
  110. ORR LR, LR, #0x04
  111. BX LR
  112. /*
  113. * void rt_hw_context_switch_to(rt_uint32 to);
  114. * R0 --> to
  115. */
  116. .global rt_hw_context_switch_to
  117. .type rt_hw_context_switch_to, %function
  118. rt_hw_context_switch_to:
  119. LDR R1, =rt_interrupt_to_thread
  120. STR R0, [R1]
  121. /* set from thread to 0 */
  122. LDR R1, =rt_interrupt_from_thread
  123. MOV R0, #0
  124. STR R0, [R1]
  125. /* set interrupt flag to 1 */
  126. LDR R1, =rt_thread_switch_interrupt_flag
  127. MOV R0, #1
  128. STR R0, [R1]
  129. /* set the PendSV exception priority */
  130. LDR R0, =SHPR3
  131. LDR R1, =PENDSV_PRI_LOWEST
  132. LDR.W R2, [R0,#0] /* read */
  133. ORR R1, R1, R2 /* modify */
  134. STR R1, [R0] /* write-back */
  135. LDR R0, =ICSR /* trigger the PendSV exception (causes context switch) */
  136. LDR R1, =PENDSVSET_BIT
  137. STR R1, [R0]
  138. CPSIE I /* enable interrupts at processor level */
  139. /* never reach here! */
  140. /* compatible with old version */
  141. .global rt_hw_interrupt_thread_switch
  142. .type rt_hw_interrupt_thread_switch, %function
  143. rt_hw_interrupt_thread_switch:
  144. BX LR
  145. NOP
  146. .global HardFault_Handler
  147. .type HardFault_Handler, %function
  148. HardFault_Handler:
  149. /* get current context */
  150. MRS R0, PSP /* get fault thread stack pointer */
  151. PUSH {LR}
  152. BL rt_hw_hard_fault_exception
  153. POP {LR}
  154. ORR LR, LR, #0x04
  155. BX LR
  156. /*
  157. * rt_uint32_t rt_hw_interrupt_check(void);
  158. * R0 --> state
  159. */
  160. .global rt_hw_interrupt_check
  161. .type rt_hw_interrupt_check, %function
  162. rt_hw_interrupt_check:
  163. MRS R0, IPSR
  164. BX LR
  165. /***************************************************************************//**
  166. * @}
  167. ******************************************************************************/