start_gcc.S 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /*
  2. * File : start.S
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2011-01-13 weety first version
  23. */
  24. #define CONFIG_STACKSIZE 512
  25. #define S_FRAME_SIZE 72
  26. #define S_OLD_R0 68
  27. #define S_PSR 64
  28. #define S_PC 60
  29. #define S_LR 56
  30. #define S_SP 52
  31. #define S_IP 48
  32. #define S_FP 44
  33. #define S_R10 40
  34. #define S_R9 36
  35. #define S_R8 32
  36. #define S_R7 28
  37. #define S_R6 24
  38. #define S_R5 20
  39. #define S_R4 16
  40. #define S_R3 12
  41. #define S_R2 8
  42. #define S_R1 4
  43. #define S_R0 0
  44. .equ USERMODE, 0x10
  45. .equ FIQMODE, 0x11
  46. .equ IRQMODE, 0x12
  47. .equ SVCMODE, 0x13
  48. .equ ABORTMODE, 0x17
  49. .equ UNDEFMODE, 0x1b
  50. .equ MODEMASK, 0x1f
  51. .equ NOINT, 0xc0
  52. .equ RAM_BASE, 0x00000000 /*Start address of RAM */
  53. .equ ROM_BASE, 0x20000000 /*Start address of Flash */
  54. #define AT91_RSTC_PROCRST (1 << 0) /* Processor Reset */
  55. #define AT91_RSTC_PERRST (1 << 2)
  56. #define AT91_RSTC_KEY (0xa5 << 24)
  57. #define AT91_MATRIX_BASE 0xffffee00
  58. #define AT91_MATRIX_MRCR (AT91_MATRIX_BASE + 0x100) /* Master Remap Control Register */
  59. #define AT91_MATRIX_RCB0 (1 << 0) /* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */
  60. #define AT91_MATRIX_RCB1 (1 << 1) /* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
  61. #define AT91_AIC_BASE 0xfffff000
  62. #define AT91_AIC_IDCR 0x124 /* Interrupt Disable Command Register */
  63. #define AT91_AIC_ICCR 0x128 /* Interrupt Clear Command Register */
  64. /*
  65. *************************************************************************
  66. *
  67. * Jump vector table
  68. *
  69. *************************************************************************
  70. */
  71. .section .init, "ax"
  72. .code 32
  73. .globl _start
  74. _start:
  75. b reset
  76. ldr pc, _vector_undef
  77. ldr pc, _vector_swi
  78. ldr pc, _vector_pabt
  79. ldr pc, _vector_dabt
  80. ldr pc, _vector_resv
  81. ldr pc, _vector_irq
  82. ldr pc, _vector_fiq
  83. _vector_undef: .word vector_undef
  84. _vector_swi: .word vector_swi
  85. _vector_pabt: .word vector_pabt
  86. _vector_dabt: .word vector_dabt
  87. _vector_resv: .word vector_resv
  88. _vector_irq: .word vector_irq
  89. _vector_fiq: .word vector_fiq
  90. .balignl 16,0xdeadbeef
  91. /*
  92. *************************************************************************
  93. *
  94. * Startup Code (reset vector)
  95. * relocate armboot to ram
  96. * setup stack
  97. * jump to second stage
  98. *
  99. *************************************************************************
  100. */
  101. _TEXT_BASE:
  102. .word TEXT_BASE
  103. /*
  104. * rtthread kernel start and end
  105. * which are defined in linker script
  106. */
  107. .globl _rtthread_start
  108. _rtthread_start:
  109. .word _start
  110. .globl _rtthread_end
  111. _rtthread_end:
  112. .word _end
  113. /*
  114. * rtthread bss start and end which are defined in linker script
  115. */
  116. .globl _bss_start
  117. _bss_start:
  118. .word __bss_start
  119. .globl _bss_end
  120. _bss_end:
  121. .word __bss_end
  122. /* IRQ stack memory (calculated at run-time) */
  123. .globl IRQ_STACK_START
  124. IRQ_STACK_START:
  125. .word _irq_stack_start + 1024
  126. .globl FIQ_STACK_START
  127. FIQ_STACK_START:
  128. .word _fiq_stack_start + 1024
  129. .globl UNDEFINED_STACK_START
  130. UNDEFINED_STACK_START:
  131. .word _undefined_stack_start + CONFIG_STACKSIZE
  132. .globl ABORT_STACK_START
  133. ABORT_STACK_START:
  134. .word _abort_stack_start + CONFIG_STACKSIZE
  135. .globl _STACK_START
  136. _STACK_START:
  137. .word _svc_stack_start + 4096
  138. /* ----------------------------------entry------------------------------*/
  139. reset:
  140. /* set the cpu to SVC32 mode */
  141. mrs r0,cpsr
  142. bic r0,r0,#MODEMASK
  143. orr r0,r0,#SVCMODE
  144. msr cpsr,r0
  145. /* mask all IRQs by clearing all bits in the INTMRs */
  146. ldr r1, =AT91_AIC_BASE
  147. ldr r0, =0xffffffff
  148. str r0, [r1, #AT91_AIC_IDCR]
  149. str r0, [r1, #AT91_AIC_ICCR]
  150. /*remap internal ram to 0x00000000 address*/
  151. ldr r0, =AT91_MATRIX_MRCR
  152. ldr r1, =(AT91_MATRIX_RCB0|AT91_MATRIX_RCB1)
  153. str r1, [r0]
  154. /* set interrupt vector */
  155. ldr r0, _TEXT_BASE
  156. mov r1, #0x00
  157. add r2, r0, #0x40 /* size, 32bytes */
  158. copy_loop:
  159. ldmia r0!, {r3-r10} /* copy from source address [r0] */
  160. stmia r1!, {r3-r10} /* copy to target address [r1] */
  161. cmp r0, r2 /* until source end addreee [r2] */
  162. ble copy_loop
  163. /* setup stack */
  164. bl stack_setup
  165. /* clear .bss */
  166. mov r0,#0 /* get a zero */
  167. ldr r1,=__bss_start /* bss start */
  168. ldr r2,=__bss_end /* bss end */
  169. bss_loop:
  170. cmp r1,r2 /* check if data to clear */
  171. strlo r0,[r1],#4 /* clear 4 bytes */
  172. blo bss_loop /* loop until done */
  173. /* call C++ constructors of global objects */
  174. ldr r0, =__ctors_start__
  175. ldr r1, =__ctors_end__
  176. ctor_loop:
  177. cmp r0, r1
  178. beq ctor_end
  179. ldr r2, [r0], #4
  180. stmfd sp!, {r0-r1}
  181. mov lr, pc
  182. bx r2
  183. ldmfd sp!, {r0-r1}
  184. b ctor_loop
  185. ctor_end:
  186. /* start RT-Thread Kernel */
  187. ldr pc, _rtthread_startup
  188. _rtthread_startup:
  189. .word rtthread_startup
  190. #if defined (__FLASH_BUILD__)
  191. _load_address:
  192. .word ROM_BASE + _TEXT_BASE
  193. #else
  194. _load_address:
  195. .word RAM_BASE + _TEXT_BASE
  196. #endif
  197. .global cpu_reset
  198. cpu_reset:
  199. ldr r0, =0xfffffd00
  200. ldr r1, =(AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST)
  201. str r1, [r0]
  202. mov pc, lr
  203. /*
  204. *************************************************************************
  205. *
  206. * Interrupt handling
  207. *
  208. *************************************************************************
  209. */
  210. /* exception handlers */
  211. .align 5
  212. vector_undef:
  213. sub sp, sp, #S_FRAME_SIZE
  214. stmia sp, {r0 - r12} /* Calling r0-r12 */
  215. add r8, sp, #S_PC
  216. stmdb r8, {sp, lr}^ /* Calling SP, LR */
  217. str lr, [r8, #0] /* Save calling PC */
  218. mrs r6, spsr
  219. str r6, [r8, #4] /* Save CPSR */
  220. str r0, [r8, #8] /* Save OLD_R0 */
  221. mov r0, sp
  222. bl rt_hw_trap_udef
  223. .align 5
  224. vector_swi:
  225. bl rt_hw_trap_swi
  226. .align 5
  227. vector_pabt:
  228. bl rt_hw_trap_pabt
  229. .align 5
  230. vector_dabt:
  231. sub sp, sp, #S_FRAME_SIZE
  232. stmia sp, {r0 - r12} /* Calling r0-r12 */
  233. add r8, sp, #S_PC
  234. stmdb r8, {sp, lr}^ /* Calling SP, LR */
  235. str lr, [r8, #0] /* Save calling PC */
  236. mrs r6, spsr
  237. str r6, [r8, #4] /* Save CPSR */
  238. str r0, [r8, #8] /* Save OLD_R0 */
  239. mov r0, sp
  240. bl rt_hw_trap_dabt
  241. .align 5
  242. vector_resv:
  243. bl rt_hw_trap_resv
  244. .globl rt_interrupt_enter
  245. .globl rt_interrupt_leave
  246. .globl rt_thread_switch_interrupt_flag
  247. .globl rt_interrupt_from_thread
  248. .globl rt_interrupt_to_thread
  249. vector_irq:
  250. stmfd sp!, {r0-r12,lr}
  251. bl rt_interrupt_enter
  252. bl rt_hw_trap_irq
  253. bl rt_interrupt_leave
  254. /* if rt_thread_switch_interrupt_flag set, jump to _interrupt_thread_switch and don't return */
  255. ldr r0, =rt_thread_switch_interrupt_flag
  256. ldr r1, [r0]
  257. cmp r1, #1
  258. beq _interrupt_thread_switch
  259. ldmfd sp!, {r0-r12,lr}
  260. subs pc, lr, #4
  261. .align 5
  262. vector_fiq:
  263. stmfd sp!,{r0-r7,lr}
  264. bl rt_hw_trap_fiq
  265. ldmfd sp!,{r0-r7,lr}
  266. subs pc,lr,#4
  267. _interrupt_thread_switch:
  268. mov r1, #0 /* clear rt_thread_switch_interrupt_flag*/
  269. str r1, [r0]
  270. ldmfd sp!, {r0-r12,lr} /* reload saved registers */
  271. stmfd sp!, {r0-r3} /* save r0-r3 */
  272. mov r1, sp
  273. add sp, sp, #16 /* restore sp */
  274. sub r2, lr, #4 /* save old task's pc to r2 */
  275. mrs r3, spsr /* disable interrupt */
  276. orr r0, r3, #NOINT
  277. msr spsr_c, r0
  278. ldr r0, =.+8 /* switch to interrupted task's stack*/
  279. movs pc, r0
  280. stmfd sp!, {r2} /* push old task's pc */
  281. stmfd sp!, {r4-r12,lr} /* push old task's lr,r12-r4 */
  282. mov r4, r1 /* Special optimised code below */
  283. mov r5, r3
  284. ldmfd r4!, {r0-r3}
  285. stmfd sp!, {r0-r3} /* push old task's r3-r0 */
  286. stmfd sp!, {r5} /* push old task's psr */
  287. mrs r4, spsr
  288. stmfd sp!, {r4} /* push old task's spsr */
  289. ldr r4, =rt_interrupt_from_thread
  290. ldr r5, [r4]
  291. str sp, [r5] /* store sp in preempted tasks's TCB*/
  292. ldr r6, =rt_interrupt_to_thread
  293. ldr r6, [r6]
  294. ldr sp, [r6] /* get new task's stack pointer */
  295. ldmfd sp!, {r4} /* pop new task's spsr */
  296. msr SPSR_cxsf, r4
  297. ldmfd sp!, {r4} /* pop new task's psr */
  298. msr CPSR_cxsf, r4
  299. ldmfd sp!, {r0-r12,lr,pc} /* pop new task's r0-r12,lr & pc */
  300. stack_setup:
  301. mrs r0, cpsr
  302. bic r0, r0, #MODEMASK
  303. orr r1, r0, #UNDEFMODE|NOINT
  304. msr cpsr_cxsf, r1 /* undef mode */
  305. ldr sp, UNDEFINED_STACK_START
  306. orr r1,r0,#ABORTMODE|NOINT
  307. msr cpsr_cxsf,r1 /* abort mode */
  308. ldr sp, ABORT_STACK_START
  309. orr r1,r0,#IRQMODE|NOINT
  310. msr cpsr_cxsf,r1 /* IRQ mode */
  311. ldr sp, IRQ_STACK_START
  312. orr r1,r0,#FIQMODE|NOINT
  313. msr cpsr_cxsf,r1 /* FIQ mode */
  314. ldr sp, FIQ_STACK_START
  315. bic r0,r0,#MODEMASK
  316. orr r1,r0,#SVCMODE|NOINT
  317. msr cpsr_cxsf,r1 /* SVC mode */
  318. ldr sp, _STACK_START
  319. /* USER mode is not initialized. */
  320. mov pc,lr /* The LR register may be not valid for the mode changes.*/
  321. /*/*}*/