startup_gcc.S 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  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. */
  9. .extern main /* 引入外部C入口 */
  10. .extern rt_interrupt_enter
  11. .extern rt_interrupt_leave
  12. .extern rt_thread_switch_interrupt_flag
  13. .extern rt_interrupt_from_thread
  14. .extern rt_interrupt_to_thread
  15. .extern rt_hw_trap_irq
  16. .global start
  17. .global endless_loop
  18. .global rt_hw_context_switch_interrupt_do
  19. /* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs */
  20. .set MODE_USR, 0x10 /* User Mode */
  21. .set MODE_FIQ, 0x11 /* FIQ Mode */
  22. .set MODE_IRQ, 0x12 /* IRQ Mode */
  23. .set MODE_SVC, 0x13 /* Supervisor Mode */
  24. .set MODE_ABT, 0x17 /* Abort Mode */
  25. .set MODE_UND, 0x1B /* Undefined Mode */
  26. .set MODE_SYS, 0x1F /* System Mode */
  27. .equ I_BIT, 0x80 /* when I bit is set, IRQ is disabled */
  28. .equ F_BIT, 0x40 /* when F bit is set, FIQ is disabled */
  29. .equ I_Bit, 0x80 /* when I bit is set, IRQ is disabled */
  30. .equ F_Bit, 0x40 /* when F bit is set, FIQ is disabled */
  31. /* VPBDIV definitions*/
  32. .equ VPBDIV, 0xE01FC100
  33. .set VPBDIV_VALUE, 0x00000000
  34. /* Phase Locked Loop (PLL) definitions*/
  35. .equ PLL_BASE, 0xE01FC080 /* PLL Base Address */
  36. .equ PLLCON_OFS, 0x00 /* PLL Control Offset */
  37. .equ PLLCFG_OFS, 0x04 /* PLL Configuration Offset */
  38. .equ PLLSTAT_OFS, 0x08 /* PLL Status Offset */
  39. .equ PLLFEED_OFS, 0x0C /* PLL Feed Offset */
  40. .equ PLLCON_PLLE, (1<<0) /* PLL Enable */
  41. .equ PLLCON_PLLC, (1<<1) /* PLL Connect */
  42. .equ PLLCFG_MSEL, (0x1F<<0) /* PLL Multiplier */
  43. .equ PLLCFG_PSEL, (0x03<<5) /* PLL Divider */
  44. .equ PLLSTAT_PLOCK, (1<<10) /* PLL Lock Status */
  45. .equ PLLCFG_Val, 0x00000024 /* <o1.0..4> MSEL: PLL Multiplier Selection,<o1.5..6> PSEL: PLL Divider Selection */
  46. .equ MEMMAP, 0xE01FC040 /*Memory Mapping Control*/
  47. /* Memory Accelerator Module (MAM) definitions*/
  48. .equ MAM_BASE, 0xE01FC000
  49. .equ MAMCR_OFS, 0x00
  50. .equ MAMTIM_OFS, 0x04
  51. .equ MAMCR_Val, 0x00000002
  52. .equ MAMTIM_Val, 0x00000004
  53. .equ VICIntEnClr, 0xFFFFF014
  54. .equ VICIntSelect, 0xFFFFF00C
  55. /************* 目标配置结束 *************/
  56. /* Setup the operating mode & stack.*/
  57. /* --------------------------------- */
  58. .global _reset
  59. _reset:
  60. .code 32
  61. .align 0
  62. /************************* PLL_SETUP **********************************/
  63. ldr r0, =PLL_BASE
  64. mov r1, #0xAA
  65. mov r2, #0x55
  66. /* Configure and Enable PLL */
  67. mov r3, #PLLCFG_Val
  68. str r3, [r0, #PLLCFG_OFS]
  69. mov r3, #PLLCON_PLLE
  70. str r3, [r0, #PLLCON_OFS]
  71. str r1, [r0, #PLLFEED_OFS]
  72. str r2, [r0, #PLLFEED_OFS]
  73. /* Wait until PLL Locked */
  74. PLL_Locked_loop:
  75. ldr r3, [r0, #PLLSTAT_OFS]
  76. ands r3, r3, #PLLSTAT_PLOCK
  77. beq PLL_Locked_loop
  78. /* Switch to PLL Clock */
  79. mov r3, #(PLLCON_PLLE|PLLCON_PLLC)
  80. str r3, [r0, #PLLCON_OFS]
  81. str r1, [r0, #PLLFEED_OFS]
  82. str R2, [r0, #PLLFEED_OFS]
  83. /************************* PLL_SETUP **********************************/
  84. /************************ Setup VPBDIV ********************************/
  85. ldr r0, =VPBDIV
  86. ldr r1, =VPBDIV_VALUE
  87. str r1, [r0]
  88. /************************ Setup VPBDIV ********************************/
  89. /************** Setup MAM **************/
  90. ldr r0, =MAM_BASE
  91. mov r1, #MAMTIM_Val
  92. str r1, [r0, #MAMTIM_OFS]
  93. mov r1, #MAMCR_Val
  94. str r1, [r0, #MAMCR_OFS]
  95. /************** Setup MAM **************/
  96. /************************ setup stack *********************************/
  97. ldr r0, .undefined_stack_top
  98. sub r0, r0, #4
  99. msr CPSR_c, #MODE_UND|I_BIT|F_BIT /* Undefined Instruction Mode */
  100. mov sp, r0
  101. ldr r0, .abort_stack_top
  102. sub r0, r0, #4
  103. msr CPSR_c, #MODE_ABT|I_BIT|F_BIT /* Abort Mode */
  104. mov sp, r0
  105. ldr r0, .fiq_stack_top
  106. sub r0, r0, #4
  107. msr CPSR_c, #MODE_FIQ|I_BIT|F_BIT /* FIQ Mode */
  108. mov sp, r0
  109. ldr r0, .irq_stack_top
  110. sub r0, r0, #4
  111. msr CPSR_c, #MODE_IRQ|I_BIT|F_BIT /* IRQ Mode */
  112. mov sp, r0
  113. ldr r0, .svc_stack_top
  114. sub r0, r0, #4
  115. msr CPSR_c, #MODE_SVC|I_BIT|F_BIT /* Supervisor Mode */
  116. mov sp, r0
  117. /************************ setup stack ********************************/
  118. /* copy .data to SRAM */
  119. ldr r1, =_sidata /* .data start in image */
  120. ldr r2, =_edata /* .data end in image */
  121. ldr r3, =_sdata /* sram data start */
  122. data_loop:
  123. ldr r0, [r1, #0]
  124. str r0, [r3]
  125. add r1, r1, #4
  126. add r3, r3, #4
  127. cmp r3, r2 /* check if data to clear */
  128. blo data_loop /* loop until done */
  129. /* clear .bss */
  130. mov r0,#0 /* get a zero */
  131. ldr r1,=__bss_start /* bss start */
  132. ldr r2,=__bss_end /* bss end */
  133. bss_loop:
  134. cmp r1,r2 /* check if data to clear */
  135. strlo r0,[r1],#4 /* clear 4 bytes */
  136. blo bss_loop /* loop until done */
  137. /* call C++ constructors of global objects */
  138. ldr r0, =__ctors_start__
  139. ldr r1, =__ctors_end__
  140. ctor_loop:
  141. cmp r0, r1
  142. beq ctor_end
  143. ldr r2, [r0], #4
  144. stmfd sp!, {r0-r1}
  145. mov lr, pc
  146. bx r2
  147. ldmfd sp!, {r0-r1}
  148. b ctor_loop
  149. ctor_end:
  150. /* enter C code */
  151. bl main
  152. .align 0
  153. .undefined_stack_top:
  154. .word _undefined_stack_top
  155. .abort_stack_top:
  156. .word _abort_stack_top
  157. .fiq_stack_top:
  158. .word _fiq_stack_top
  159. .irq_stack_top:
  160. .word _irq_stack_top
  161. .svc_stack_top:
  162. .word _svc_stack_top
  163. /*********************** END Clear BSS ******************************/
  164. .section .init,"ax"
  165. .code 32
  166. .align 0
  167. .globl _start
  168. _start:
  169. ldr pc, __start /* reset - _start */
  170. ldr pc, _undf /* undefined - _undf */
  171. ldr pc, _swi /* SWI - _swi */
  172. ldr pc, _pabt /* program abort - _pabt */
  173. ldr pc, _dabt /* data abort - _dabt */
  174. .word 0xB8A06F58 /* reserved */
  175. ldr pc, __IRQ_Handler /* IRQ - read the VIC */
  176. ldr pc, _fiq /* FIQ - _fiq */
  177. __start:.word _reset
  178. _undf: .word __undf /* undefined */
  179. _swi: .word __swi /* SWI */
  180. _pabt: .word __pabt /* program abort */
  181. _dabt: .word __dabt /* data abort */
  182. temp1: .word 0
  183. __IRQ_Handler: .word IRQ_Handler
  184. _fiq: .word __fiq /* FIQ */
  185. __undf: b . /* undefined */
  186. __swi : b .
  187. __pabt: b . /* program abort */
  188. __dabt: b . /* data abort */
  189. __fiq : b . /* FIQ */
  190. /* IRQ入口 */
  191. IRQ_Handler :
  192. stmfd sp!, {r0-r12,lr} /* 对R0 – R12,LR寄存器压栈 */
  193. bl rt_interrupt_enter /* 通知RT-Thread进入中断模式 */
  194. bl rt_hw_trap_irq /* 相应中断服务例程处理 */
  195. bl rt_interrupt_leave /* ; 通知RT-Thread要离开中断模式 */
  196. /* 如果设置了rt_thread_switch_interrupt_flag,进行中断中的线程上下文处理 */
  197. ldr r0, =rt_thread_switch_interrupt_flag
  198. ldr r1, [r0]
  199. cmp r1, #1
  200. beq rt_hw_context_switch_interrupt_do /* 中断中切换发生 */
  201. /* 如果跳转了,将不会回来 */
  202. ldmfd sp!, {r0-r12,lr} /* 恢复栈 */
  203. subs pc, lr, #4 /* 从IRQ中返回 */
  204. /*
  205. * void rt_hw_context_switch_interrupt_do(rt_base_t flag)
  206. * 中断结束后的上下文切换
  207. */
  208. rt_hw_context_switch_interrupt_do:
  209. mov r1, #0 /* clear flag */
  210. /* 清楚中断中切换标志 */
  211. str r1, [r0] /* */
  212. ldmfd sp!, {r0-r12,lr}/* reload saved registers */
  213. /* 先恢复被中断线程的上下文 */
  214. stmfd sp!, {r0-r3} /* save r0-r3 */
  215. /* 对R0 – R3压栈,因为后面会用到 */
  216. mov r1, sp /* 把此处的栈值保存到R1 */
  217. add sp, sp, #16 /* restore sp */
  218. /* 恢复IRQ的栈,后面会跳出IRQ模式 */
  219. sub r2, lr, #4 /* save old task's pc to r2 */
  220. /* 保存切换出线程的PC到R2 */
  221. mrs r3, spsr /* disable interrupt 保存中断前的CPSR到R3寄存器 */
  222. /* 获得SPSR寄存器值 */
  223. orr r0, r3, #I_BIT|F_BIT
  224. msr spsr_c, r0 /* 关闭SPSR中的IRQ/FIQ中断 */
  225. ldr r0, =.+8 /* 把当前地址+8载入到R0寄存器中 switch to interrupted task's stack */
  226. movs pc, r0 /* 退出IRQ模式,由于SPSR被设置成关中断模式 */
  227. /* 所以从IRQ返回后,中断并没有打开
  228. ; R0寄存器中的位置实际就是下一条指令,
  229. ; 即PC继续往下走
  230. ; 此时
  231. ; 模式已经换成中断前的SVC模式,
  232. ; SP寄存器也是SVC模式下的栈寄存器
  233. ; R1保存IRQ模式下的栈指针
  234. ; R2保存切换出线程的PC
  235. ; R3保存切换出线程的CPSR */
  236. stmfd sp!, {r2} /* push old task's pc */
  237. /* 保存切换出任务的PC */
  238. stmfd sp!, {r4-r12,lr}/* push old task's lr,r12-r4 */
  239. /* 保存R4 – R12,LR寄存器 */
  240. mov r4, r1 /* Special optimised code below */
  241. /* R1保存有压栈R0 – R3处的栈位置 */
  242. mov r5, r3 /* R3切换出线程的CPSR */
  243. ldmfd r4!, {r0-r3} /* 恢复R0 – R3 */
  244. stmfd sp!, {r0-r3} /* push old task's r3-r0 */
  245. /* R0 – R3压栈到切换出线程 */
  246. stmfd sp!, {r5} /* push old task's psr */
  247. /* 切换出线程CPSR压栈 */
  248. mrs r4, spsr
  249. stmfd sp!, {r4} /* push old task's spsr */
  250. /* 切换出线程SPSR压栈 */
  251. ldr r4, =rt_interrupt_from_thread
  252. ldr r5, [r4]
  253. str sp, [r5] /* store sp in preempted tasks's TCB */
  254. /* 保存切换出线程的SP指针 */
  255. ldr r6, =rt_interrupt_to_thread
  256. ldr r6, [r6]
  257. ldr sp, [r6] /* get new task's stack pointer */
  258. /* 获得切换到线程的栈 */
  259. ldmfd sp!, {r4} /* pop new task's spsr */
  260. /* 恢复SPSR */
  261. msr SPSR_cxsf, r4
  262. ldmfd sp!, {r4} /* pop new task's psr */
  263. /* 恢复CPSR */
  264. msr CPSR_cxsf, r4
  265. ldmfd sp!, {r0-r12,lr,pc} /* pop new task's r0-r12,lr & pc */
  266. /* 恢复R0 – R12,LR及PC寄存器 */
  267. /* 代码加密功能 */
  268. #if defined(CODE_PROTECTION)
  269. .org 0x01FC
  270. .word 0x87654321
  271. #endif