start_iar.s 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  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. * 2015-04-06 zchong the first version
  9. */
  10. MODULE ?cstartup
  11. ; --------------------
  12. ; Mode, correspords to bits 0-5 in CPSR
  13. MODE_MSK DEFINE 0x1F ; Bit mask for mode bits in CPSR
  14. I_Bit DEFINE 0x80 ; when I bit is set, IRQ is disabled
  15. F_Bit DEFINE 0x40 ; when F bit is set, FIQ is disabled
  16. USR_MODE DEFINE 0x10 ; User mode
  17. FIQ_MODE DEFINE 0x11 ; Fast Interrupt Request mode
  18. IRQ_MODE DEFINE 0x12 ; Interrupt Request mode
  19. SVC_MODE DEFINE 0x13 ; Supervisor mode
  20. ABT_MODE DEFINE 0x17 ; Abort mode
  21. UND_MODE DEFINE 0x1B ; Undefined Instruction mode
  22. SYS_MODE DEFINE 0x1F ; System mode
  23. ;; Forward declaration of sections.
  24. SECTION IRQ_STACK:DATA:NOROOT(3)
  25. SECTION FIQ_STACK:DATA:NOROOT(3)
  26. SECTION SVC_STACK:DATA:NOROOT(3)
  27. SECTION ABT_STACK:DATA:NOROOT(3)
  28. SECTION UND_STACK:DATA:NOROOT(3)
  29. SECTION CSTACK:DATA:NOROOT(3)
  30. SECTION .text:CODE
  31. SECTION .intvec:CODE:NOROOT(5)
  32. PUBLIC __vector
  33. PUBLIC __iar_program_start
  34. __iar_init$$done: ; The vector table is not needed
  35. ; until after copy initialization is done
  36. __vector: ; Make this a DATA label, so that stack usage
  37. ; analysis doesn't consider it an uncalled fun
  38. ARM
  39. ; All default exception handlers (except reset) are
  40. ; defined as weak symbol definitions.
  41. ; If a handler is defined by the application it will take precedence.
  42. LDR PC,Reset_Addr ; Reset
  43. LDR PC,Undefined_Addr ; Undefined instructions
  44. LDR PC,SWI_Addr ; Software interrupt (SWI/SVC)
  45. LDR PC,Prefetch_Addr ; Prefetch abort
  46. LDR PC,Abort_Addr ; Data abort
  47. DCD 0 ; RESERVED
  48. LDR PC,IRQ_Addr ; IRQ
  49. LDR PC,FIQ_Addr ; FIQ
  50. DATA
  51. Reset_Addr: DCD __iar_program_start
  52. Undefined_Addr: DCD Undefined_Handler
  53. SWI_Addr: DCD SWI_Handler
  54. Prefetch_Addr: DCD Prefetch_Handler
  55. Abort_Addr: DCD Abort_Handler
  56. IRQ_Addr: DCD IRQ_Handler
  57. FIQ_Addr: DCD FIQ_Handler
  58. ; --------------------------------------------------
  59. ; ?cstartup -- low-level system initialization code.
  60. ;
  61. ; After a reset execution starts here, the mode is ARM, supervisor
  62. ; with interrupts disabled.
  63. ;
  64. SECTION .text:CODE:NOROOT(2)
  65. EXTERN rt_hw_trap_udef
  66. EXTERN rt_hw_trap_swi
  67. EXTERN rt_hw_trap_pabt
  68. EXTERN rt_hw_trap_dabt
  69. EXTERN rt_hw_trap_fiq
  70. EXTERN rt_hw_trap_irq
  71. EXTERN rt_interrupt_enter
  72. EXTERN rt_interrupt_leave
  73. EXTERN rt_thread_switch_interrupt_flag
  74. EXTERN rt_interrupt_from_thread
  75. EXTERN rt_interrupt_to_thread
  76. EXTERN rt_current_thread
  77. EXTERN vmm_thread
  78. EXTERN vmm_virq_check
  79. EXTERN __cmain
  80. REQUIRE __vector
  81. EXTWEAK __iar_init_core
  82. EXTWEAK __iar_init_vfp
  83. ARM
  84. __iar_program_start:
  85. ?cstartup:
  86. ;
  87. ; Add initialization needed before setup of stackpointers here.
  88. ;
  89. ;
  90. ; Initialize the stack pointers.
  91. ; The pattern below can be used for any of the exception stacks:
  92. ; FIQ, IRQ, SVC, ABT, UND, SYS.
  93. ; The USR mode uses the same stack as SYS.
  94. ; The stack segments must be defined in the linker command file,
  95. ; and be declared above.
  96. ;
  97. MRS r0, cpsr ; Original PSR value
  98. ;; Set up the interrupt stack pointer.
  99. BIC r0, r0, #MODE_MSK ; Clear the mode bits
  100. ORR r0, r0, #IRQ_MODE ; Set IRQ mode bits
  101. MSR cpsr_c, r0 ; Change the mode
  102. LDR sp, =SFE(IRQ_STACK) ; End of IRQ_STACK
  103. BIC sp,sp,#0x7 ; Make sure SP is 8 aligned
  104. ;; Set up the fast interrupt stack pointer.
  105. BIC r0, r0, #MODE_MSK ; Clear the mode bits
  106. ORR r0, r0, #FIQ_MODE ; Set FIR mode bits
  107. MSR cpsr_c, r0 ; Change the mode
  108. LDR sp, =SFE(FIQ_STACK) ; End of FIQ_STACK
  109. BIC sp,sp,#0x7 ; Make sure SP is 8 aligned
  110. BIC r0,r0,#MODE_MSK ; Clear the mode bits
  111. ORR r0,r0,#ABT_MODE ; Set Abort mode bits
  112. MSR cpsr_c,r0 ; Change the mode
  113. LDR sp,=SFE(ABT_STACK) ; End of ABT_STACK
  114. BIC sp,sp,#0x7 ; Make sure SP is 8 aligned
  115. BIC r0,r0,#MODE_MSK ; Clear the mode bits
  116. ORR r0,r0,#UND_MODE ; Set Undefined mode bits
  117. MSR cpsr_c,r0 ; Change the mode
  118. LDR sp,=SFE(UND_STACK) ; End of UND_STACK
  119. BIC sp,sp,#0x7 ; Make sure SP is 8 aligned
  120. ;; Set up the normal stack pointer.
  121. BIC r0 ,r0, #MODE_MSK ; Clear the mode bits
  122. ORR r0 ,r0, #SVC_MODE ; Set System mode bits
  123. MSR cpsr_c, r0 ; Change the mode
  124. LDR sp, =SFE(SVC_STACK) ; End of SVC_STACK
  125. BIC sp,sp,#0x7 ; Make sure SP is 8 aligned
  126. ;; Turn on core features assumed to be enabled.
  127. BL __iar_init_core
  128. ;; Initialize VFP (if needed).
  129. BL __iar_init_vfp
  130. ;; Continue to __cmain for C-level initialization.
  131. B __cmain
  132. Undefined_Handler:
  133. SUB sp, sp, #72
  134. STMIA sp, {r0 - r12} ;/* Calling r0-r12 */
  135. ADD r8, sp, #60
  136. MRS r1, cpsr
  137. MRS r2, spsr
  138. ORR r2,r2, #I_Bit | F_Bit
  139. MSR cpsr_c, r2
  140. MOV r0, r0
  141. STMDB r8, {sp, lr} ;/* Calling SP, LR */
  142. MSR cpsr_c, r1 ;/* return to Undefined Instruction mode */
  143. STR lr, [r8, #0] ;/* Save calling PC */
  144. MRS r6, spsr
  145. STR r6, [r8, #4] ;/* Save CPSR */
  146. STR r0, [r8, #8] ;/* Save OLD_R0 */
  147. MOV r0, sp
  148. BL rt_hw_trap_udef
  149. LDMIA sp, {r0 - r12} ;/* Calling r0 - r2 */
  150. MOV r0, r0
  151. LDR lr, [sp, #60] ;/* Get PC */
  152. ADD sp, sp, #72
  153. MOVS pc, lr ;/* return & move spsr_svc into cpsr */
  154. SWI_Handler:
  155. BL rt_hw_trap_swi
  156. Prefetch_Handler:
  157. BL rt_hw_trap_pabt
  158. Abort_Handler:
  159. SUB sp, sp, #72
  160. STMIA sp, {r0 - r12} ;/* Calling r0-r12 */
  161. ADD r8, sp, #60
  162. STMDB r8, {sp, lr} ;/* Calling SP, LR */
  163. STR lr, [r8, #0] ;/* Save calling PC */
  164. MRS r6, spsr
  165. STR r6, [r8, #4] ;/* Save CPSR */
  166. STR r0, [r8, #8] ;/* Save OLD_R0 */
  167. MOV r0, sp
  168. BL rt_hw_trap_dabt
  169. LDMIA sp, {r0 - r12} ;/* Calling r0 - r2 */
  170. MOV r0, r0
  171. LDR lr, [sp, #60] ;/* Get PC */
  172. ADD sp, sp, #72
  173. MOVS pc, lr ;/* return & move spsr_svc into cpsr */
  174. FIQ_Handler:
  175. STMFD sp!,{r0-r7,lr}
  176. BL rt_hw_trap_fiq
  177. LDMFD sp!,{r0-r7,lr}
  178. SUBS pc,lr,#4
  179. IRQ_Handler:
  180. STMFD sp!, {r0-r12,lr}
  181. BL rt_interrupt_enter
  182. BL rt_hw_trap_irq
  183. BL rt_interrupt_leave
  184. ; if rt_thread_switch_interrupt_flag set, jump to
  185. ; rt_hw_context_switch_interrupt_do and don't return
  186. LDR r0, =rt_thread_switch_interrupt_flag
  187. LDR r1, [r0]
  188. CMP r1, #1
  189. BEQ rt_hw_context_switch_interrupt_do
  190. LDMFD sp!, {r0-r12,lr}
  191. SUBS pc, lr, #4
  192. rt_hw_context_switch_interrupt_do:
  193. MOV r1, #0 ; clear flag
  194. STR r1, [r0]
  195. LDMFD sp!, {r0-r12,lr}; reload saved registers
  196. STMFD sp, {r0-r2} ; save r0-r2
  197. MRS r0, spsr ; get cpsr of interrupt thread
  198. SUB r1, sp, #4*3
  199. SUB r2, lr, #4 ; save old task's pc to r2
  200. ; switch to SVC mode with no interrupt
  201. MSR cpsr_c, #I_Bit | F_Bit | SVC_MODE
  202. STMFD sp!, {r2} ; push old task's pc
  203. STMFD sp!, {r3-r12,lr}; push old task's lr,r12-r4
  204. LDMFD r1, {r1-r3} ; restore r0-r2 of the interrupt thread
  205. STMFD sp!, {r1-r3} ; push old task's r0-r2
  206. STMFD sp!, {r0} ; push old task's cpsr
  207. LDR r4, =rt_interrupt_from_thread
  208. LDR r5, [r4]
  209. STR sp, [r5] ; store sp in preempted tasks's TCB
  210. LDR r6, =rt_interrupt_to_thread
  211. LDR r6, [r6]
  212. LDR sp, [r6] ; get new task's stack pointer
  213. LDMFD sp!, {r4} ; pop new task's cpsr to spsr
  214. MSR spsr_cxsf, r4
  215. LDMFD sp!, {r0-r12,lr,pc}^ ; pop new task's r0-r12,lr & pc, copy spsr to cpsr
  216. END