context_gcc.S 4.5 KB

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