context_gcc.S 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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 LICENSE in this
  10. * 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. *********************************************************************/
  17. /******************************************************************//**
  18. * @addtogroup cortex-m3
  19. * @{
  20. *********************************************************************/
  21. .cpu cortex-m3
  22. .fpu softvfp
  23. .syntax unified
  24. .thumb
  25. .text
  26. .equ ICSR, 0xE000ED04 /* interrupt control state register */
  27. .equ PENDSVSET_BIT, 0x10000000 /* value to trigger PendSV exception */
  28. .equ SHPR3, 0xE000ED20 /* system priority register (3) */
  29. .equ PENDSV_PRI_LOWEST, 0x00FF0000 /* PendSV priority value (lowest) */
  30. /*
  31. * rt_base_t rt_hw_interrupt_disable();
  32. */
  33. .global rt_hw_interrupt_disable
  34. .type rt_hw_interrupt_disable, %function
  35. rt_hw_interrupt_disable:
  36. MRS R0, PRIMASK
  37. CPSID I
  38. BX LR
  39. /*
  40. * void rt_hw_interrupt_enable(rt_base_t level);
  41. */
  42. .global rt_hw_interrupt_enable
  43. .type rt_hw_interrupt_enable, %function
  44. rt_hw_interrupt_enable:
  45. MSR PRIMASK, R0
  46. BX LR
  47. /*
  48. * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
  49. * R0 --> from
  50. * R1 --> to
  51. */
  52. .global rt_hw_context_switch_interrupt
  53. .type rt_hw_context_switch_interrupt, %function
  54. .global rt_hw_context_switch
  55. .type rt_hw_context_switch, %function
  56. rt_hw_context_switch_interrupt:
  57. rt_hw_context_switch:
  58. /* set rt_thread_switch_interrput_flag to 1 */
  59. LDR R2, =rt_thread_switch_interrput_flag
  60. LDR R3, [R2]
  61. CMP R3, #1
  62. BEQ _reswitch
  63. MOV R3, #1
  64. STR R3, [R2]
  65. LDR R2, =rt_interrupt_from_thread /* set rt_interrupt_from_thread */
  66. STR R0, [R2]
  67. _reswitch:
  68. LDR R2, =rt_interrupt_to_thread /* set rt_interrupt_to_thread */
  69. STR R1, [R2]
  70. LDR R0, =ICSR /* trigger the PendSV exception (causes context switch) */
  71. LDR R1, =PENDSVSET_BIT
  72. STR R1, [R0]
  73. BX LR
  74. /* R0 --> swith from thread stack
  75. * R1 --> swith to thread stack
  76. * psr, pc, LR, R12, R3, R2, R1, R0 are pushed into [from] stack
  77. */
  78. .global rt_hw_pend_sv
  79. .type rt_hw_pend_sv, %function
  80. rt_hw_pend_sv:
  81. /* disable interrupt to protect context switch */
  82. MRS R2, PRIMASK
  83. CPSID I
  84. /* get rt_thread_switch_interrupt_flag */
  85. LDR R0, =rt_thread_switch_interrput_flag
  86. LDR R1, [R0]
  87. CBZ R1, pendsv_exit /* pendsv aLReady handled */
  88. /* clear rt_thread_switch_interrput_flag to 0 */
  89. MOV R1, #0
  90. STR R1, [R0]
  91. LDR R0, =rt_interrupt_from_thread
  92. LDR R1, [R0]
  93. CBZ R1, swtich_to_thread /* skip register save at the first time */
  94. MRS R1, PSP /* get from thread stack pointer */
  95. STMFD R1!, {R4 - R11} /* push R4 - R11 register */
  96. LDR R0, [R0]
  97. STR R1, [R0] /* update from thread stack pointer */
  98. swtich_to_thread:
  99. LDR R1, =rt_interrupt_to_thread
  100. LDR R1, [R1]
  101. LDR R1, [R1] /* load thread stack pointer */
  102. LDMFD R1!, {R4 - R11} /* pop R4 - R11 register */
  103. MSR PSP, R1 /* update stack pointer */
  104. pendsv_exit:
  105. /* restore interrupt */
  106. MSR PRIMASK, R2
  107. ORR LR, LR, #0x04
  108. BX LR
  109. /*
  110. * void rt_hw_context_switch_to(rt_uint32 to);
  111. * R0 --> to
  112. */
  113. .global rt_hw_context_switch_to
  114. .type rt_hw_context_switch_to, %function
  115. rt_hw_context_switch_to:
  116. LDR R1, =rt_interrupt_to_thread
  117. STR R0, [R1]
  118. /* set from thread to 0 */
  119. LDR R1, =rt_interrupt_from_thread
  120. MOV R0, #0
  121. STR R0, [R1]
  122. /* set interrupt flag to 1 */
  123. LDR R1, =rt_thread_switch_interrput_flag
  124. MOV R0, #1
  125. STR R0, [R1]
  126. /* set the PendSV exception priority */
  127. LDR R0, =SHPR3
  128. LDR R1, =PENDSV_PRI_LOWEST
  129. LDR.W R2, [R0,#0] /* read */
  130. ORR R1, R1, R2 /* modify */
  131. STR R1, [R0] /* write-back */
  132. LDR R0, =ICSR /* trigger the PendSV exception (causes context switch) */
  133. LDR R1, =PENDSVSET_BIT
  134. STR R1, [R0]
  135. CPSIE I /* enable interrupts at processor level */
  136. /* never reach here! */
  137. /* compatible with old version */
  138. .global rt_hw_interrupt_thread_switch
  139. .type rt_hw_interrupt_thread_switch, %function
  140. rt_hw_interrupt_thread_switch:
  141. BX LR
  142. NOP
  143. /******************************************************************//**
  144. * @}
  145. *********************************************************************/