start_gcc.S 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /*
  2. * File : start.S
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006, 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://openlab.rt-thread.com/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2008-12-11 XuXinming first version
  13. * 2011-03-17 Bernard update to 0.4.x
  14. */
  15. #define WDMOD (0xE0000000 + 0x00)
  16. #define VICIntEnClr (0xFFFFF000 + 0x014)
  17. #define VICVectAddr (0xFFFFF000 + 0xF00)
  18. #define VICIntSelect (0xFFFFF000 + 0x00C)
  19. #define PLLCFG (0xE01FC000 + 0x084)
  20. #define PLLCON (0xE01FC000 + 0x080)
  21. #define PLLFEED (0xE01FC000 + 0x08C)
  22. #define PLLSTAT (0xE01FC000 + 0x088)
  23. #define CCLKCFG (0xE01FC000 + 0x104)
  24. #define MEMMAP (0xE01FC000 + 0x040)
  25. #define SCS (0xE01FC000 + 0x1A0)
  26. #define CLKSRCSEL (0xE01FC000 + 0x10C)
  27. #define MAMCR (0xE01FC000 + 0x000)
  28. #define MAMTIM (0xE01FC000 + 0x004)
  29. /* stack memory */
  30. .section .bss.noinit
  31. .equ IRQ_STACK_SIZE, 0x00000200
  32. .equ FIQ_STACK_SIZE, 0x00000100
  33. .equ UDF_STACK_SIZE, 0x00000004
  34. .equ ABT_STACK_SIZE, 0x00000004
  35. .equ SVC_STACK_SIZE, 0x00000200
  36. .space IRQ_STACK_SIZE
  37. IRQ_STACK:
  38. .space FIQ_STACK_SIZE
  39. FIQ_STACK:
  40. .space UDF_STACK_SIZE
  41. UDF_STACK:
  42. .space ABT_STACK_SIZE
  43. ABT_STACK:
  44. .space SVC_STACK_SIZE
  45. SVC_STACK:
  46. .section .init, "ax"
  47. .code 32
  48. .globl _start
  49. _start:
  50. b reset
  51. ldr pc, _vector_undef
  52. ldr pc, _vector_swi
  53. ldr pc, _vector_pabt
  54. ldr pc, _vector_dabt
  55. ldr pc, _vector_resv
  56. ldr pc, _vector_irq
  57. ldr pc, _vector_fiq
  58. _vector_undef: .word vector_undef
  59. _vector_swi: .word vector_swi
  60. _vector_pabt: .word vector_pabt
  61. _vector_dabt: .word vector_dabt
  62. _vector_resv: .word vector_resv
  63. _vector_irq: .word vector_irq
  64. _vector_fiq: .word vector_fiq
  65. .balignl 16,0xdeadbeef
  66. /*
  67. * rtthread kernel start and end
  68. * which are defined in linker script
  69. */
  70. .globl _rtthread_start
  71. _rtthread_start:
  72. .word _start
  73. .globl _rtthread_end
  74. _rtthread_end:
  75. .word _end
  76. /*
  77. * rtthread bss start and end which are defined in linker script
  78. */
  79. .globl _bss_start
  80. _bss_start:
  81. .word __bss_start
  82. .globl _bss_end
  83. _bss_end:
  84. .word __bss_end
  85. .text
  86. .code 32
  87. /* the system entry */
  88. reset:
  89. /* enter svc mode */
  90. msr cpsr_c, #SVCMODE|NOINT
  91. /*watch dog disable */
  92. ldr r0,=WDMOD
  93. ldr r1,=0x0
  94. str r1,[r0]
  95. /* all interrupt disable */
  96. ldr r0,=VICIntEnClr
  97. ldr r1,=0xffffffff
  98. str r1,[r0]
  99. ldr r1, =VICVectAddr
  100. ldr r0, =0x00
  101. str r0, [r1]
  102. ldr r1, =VICIntSelect
  103. ldr r0, =0x00
  104. str r0, [r1]
  105. /* setup stack */
  106. bl stack_setup
  107. /* copy .data to SRAM */
  108. ldr r1, =_sidata /* .data start in image */
  109. ldr r2, =_edata /* .data end in image */
  110. ldr r3, =_sdata /* sram data start */
  111. data_loop:
  112. ldr r0, [r1, #0]
  113. str r0, [r3]
  114. add r1, r1, #4
  115. add r3, r3, #4
  116. cmp r3, r2 /* check if data to clear */
  117. blo data_loop /* loop until done */
  118. /* clear .bss */
  119. mov r0,#0 /* get a zero */
  120. ldr r1,=__bss_start /* bss start */
  121. ldr r2,=__bss_end /* bss end */
  122. bss_loop:
  123. cmp r1,r2 /* check if data to clear */
  124. strlo r0,[r1],#4 /* clear 4 bytes */
  125. blo bss_loop /* loop until done */
  126. /* call C++ constructors of global objects */
  127. ldr r0, =__ctors_start__
  128. ldr r1, =__ctors_end__
  129. ctor_loop:
  130. cmp r0, r1
  131. beq ctor_end
  132. ldr r2, [r0], #4
  133. stmfd sp!, {r0-r1}
  134. mov lr, pc
  135. bx r2
  136. ldmfd sp!, {r0-r1}
  137. b ctor_loop
  138. ctor_end:
  139. /* start RT-Thread Kernel */
  140. ldr pc, _rtthread_startup
  141. _rtthread_startup:
  142. .word rtthread_startup
  143. .equ USERMODE, 0x10
  144. .equ FIQMODE, 0x11
  145. .equ IRQMODE, 0x12
  146. .equ SVCMODE, 0x13
  147. .equ ABORTMODE, 0x17
  148. .equ UNDEFMODE, 0x1b
  149. .equ MODEMASK, 0x1f
  150. .equ NOINT, 0xc0
  151. /* exception handlers */
  152. vector_undef: bl rt_hw_trap_udef
  153. vector_swi: bl rt_hw_trap_swi
  154. vector_pabt: bl rt_hw_trap_pabt
  155. vector_dabt: bl rt_hw_trap_dabt
  156. vector_resv: bl rt_hw_trap_resv
  157. .globl rt_interrupt_enter
  158. .globl rt_interrupt_leave
  159. .globl rt_thread_switch_interrupt_flag
  160. .globl rt_interrupt_from_thread
  161. .globl rt_interrupt_to_thread
  162. vector_irq:
  163. stmfd sp!, {r0-r12,lr}
  164. bl rt_interrupt_enter
  165. bl rt_hw_trap_irq
  166. bl rt_interrupt_leave
  167. /* if rt_thread_switch_interrupt_flag set,
  168. * jump to _interrupt_thread_switch and don't return
  169. */
  170. ldr r0, =rt_thread_switch_interrupt_flag
  171. ldr r1, [r0]
  172. cmp r1, #1
  173. beq _interrupt_thread_switch
  174. ldmfd sp!, {r0-r12,lr}
  175. subs pc, lr, #4
  176. .align 5
  177. vector_fiq:
  178. stmfd sp!,{r0-r7,lr}
  179. bl rt_hw_trap_fiq
  180. ldmfd sp!,{r0-r7,lr}
  181. subs pc,lr,#4
  182. _interrupt_thread_switch:
  183. mov r1, #0 /* clear rt_thread_switch_interrupt_flag */
  184. str r1, [r0]
  185. ldmfd sp!, {r0-r12,lr} /* reload saved registers */
  186. stmfd sp!, {r0-r3} /* save r0-r3 */
  187. mov r1, sp
  188. add sp, sp, #16 /* restore sp */
  189. sub r2, lr, #4 /* save old task's pc to r2 */
  190. mrs r3, spsr /* disable interrupt */
  191. orr r0, r3, #NOINT
  192. msr spsr_c, r0
  193. ldr r0, =.+8 /* switch to interrupted task's stack */
  194. movs pc, r0
  195. stmfd sp!, {r2} /* push old task's pc */
  196. stmfd sp!, {r4-r12,lr} /* push old task's lr,r12-r4 */
  197. mov r4, r1 /* Special optimised code below */
  198. mov r5, r3
  199. ldmfd r4!, {r0-r3}
  200. stmfd sp!, {r0-r3} /* push old task's r3-r0 */
  201. stmfd sp!, {r5} /* push old task's psr */
  202. mrs r4, spsr
  203. stmfd sp!, {r4} /* push old task's spsr */
  204. ldr r4, =rt_interrupt_from_thread
  205. ldr r5, [r4]
  206. str sp, [r5] /* store sp in preempted tasks's TCB */
  207. ldr r6, =rt_interrupt_to_thread
  208. ldr r6, [r6]
  209. ldr sp, [r6] /* get new task's stack pointer */
  210. ldmfd sp!, {r4} /* pop new task's spsr */
  211. msr SPSR_cxsf, r4
  212. ldmfd sp!, {r4} /* pop new task's psr */
  213. msr CPSR_cxsf, r4
  214. ldmfd sp!, {r0-r12,lr,pc} /* pop new task's r0-r12,lr & pc */
  215. stack_setup:
  216. mrs r0, cpsr
  217. bic r0, r0, #MODEMASK
  218. orr r1, r0, #UNDEFMODE|NOINT
  219. msr cpsr_cxsf, r1 /* undef mode */
  220. ldr sp, =UDF_STACK
  221. orr r1,r0,#ABORTMODE|NOINT
  222. msr cpsr_cxsf,r1 /* abort mode */
  223. ldr sp, =ABT_STACK
  224. orr r1,r0,#IRQMODE|NOINT
  225. msr cpsr_cxsf,r1 /* IRQ mode */
  226. ldr sp, =IRQ_STACK
  227. orr r1,r0,#FIQMODE|NOINT
  228. msr cpsr_cxsf,r1 /* FIQ mode */
  229. ldr sp, =FIQ_STACK
  230. bic r0,r0,#MODEMASK
  231. orr r1,r0,#SVCMODE|NOINT
  232. msr cpsr_cxsf,r1 /* SVC mode */
  233. ldr sp, =SVC_STACK
  234. /* USER mode is not initialized. */
  235. mov pc,lr /* The LR register may be not valid for the mode changes.*/