start_gcc.S 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. /*
  2. * This file is part of FH8620 BSP for RT-Thread distribution.
  3. *
  4. * Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
  5. * All rights reserved
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program; if not, write to the Free Software Foundation, Inc.,
  19. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20. *
  21. * Visit http://www.fullhan.com to get contact with Fullhan.
  22. *
  23. * Change Logs:
  24. * Date Author Notes
  25. */
  26. #include <rtconfig.h>
  27. #include <armv6.h>
  28. #define CONFIG_STACKSIZE 512
  29. #define FPEXC_EN (1 << 30) /* VFP enable bit */
  30. .equ I_BIT, 0x80 @ when I bit is set, IRQ is disabled
  31. .equ F_BIT, 0x40 @ when F bit is set, FIQ is disabled
  32. #.equ USERMODE, 0x10
  33. #.equ FIQMODE, 0x11
  34. #.equ IRQMODE, 0x12
  35. #.equ SVCMODE, 0x13
  36. #.equ ABORTMODE, 0x17
  37. #.equ UNDEFMODE, 0x1b
  38. #.equ MODEMASK, 0x1f
  39. #.equ NOINT, 0xc0
  40. .equ RAM_BASE, 0x00000000 /*Start address of RAM*/
  41. .equ ROM_BASE, 0xA0000000 /*Start address of Flash*/
  42. #define FH81_INTC_BASE 0xE0200000
  43. /*
  44. *************************************************************************
  45. *
  46. * Jump vector table
  47. *
  48. *************************************************************************
  49. */
  50. .section .init, "ax"
  51. .code 32
  52. .globl _start
  53. _start:
  54. b reset
  55. ldr pc, _vector_undef
  56. ldr pc, _vector_swi
  57. ldr pc, _vector_pabt
  58. ldr pc, _vector_dabt
  59. ldr pc, _vector_resv
  60. ldr pc, _vector_irq
  61. ldr pc, _vector_fiq
  62. _vector_undef: .word vector_undef
  63. _vector_swi: .word vector_swi
  64. _vector_pabt: .word vector_pabt
  65. _vector_dabt: .word vector_dabt
  66. _vector_resv: .word vector_resv
  67. _vector_irq: .word vector_irq
  68. _vector_fiq: .word vector_fiq
  69. .balignl 16,0xdeadbeef
  70. /*
  71. *************************************************************************
  72. *
  73. * Startup Code (reset vector)
  74. * relocate armboot to ram
  75. * setup stack
  76. * jump to second stage
  77. *
  78. *************************************************************************
  79. */
  80. /*
  81. * rtthread kernel start and end
  82. * which are defined in linker script
  83. */
  84. .globl _rtthread_start
  85. _rtthread_start:
  86. .word _start
  87. .globl _rtthread_end
  88. _rtthread_end:
  89. .word _end
  90. /*
  91. * rtthread bss start and end which are defined in linker script
  92. */
  93. .globl _bss_start
  94. _bss_start:
  95. .word __bss_start
  96. .globl _bss_end
  97. _bss_end:
  98. .word __bss_end
  99. /* IRQ stack memory (calculated at run-time) */
  100. .globl IRQ_STACK_START
  101. IRQ_STACK_START:
  102. .word _irq_stack_start + 1024
  103. .globl FIQ_STACK_START
  104. FIQ_STACK_START:
  105. .word _fiq_stack_start + 1024
  106. .globl UNDEFINED_STACK_START
  107. UNDEFINED_STACK_START:
  108. .word _undefined_stack_start + CONFIG_STACKSIZE
  109. .globl ABORT_STACK_START
  110. ABORT_STACK_START:
  111. .word _abort_stack_start + CONFIG_STACKSIZE
  112. .globl _STACK_START
  113. _STACK_START:
  114. .word _svc_stack_start + 4096
  115. /* ----------------------------------entry------------------------------*/
  116. reset:
  117. /* set the cpu to SVC32 mode */
  118. mrs r0,cpsr
  119. bic r0,r0,#MODEMASK
  120. orr r0,r0,#SVCMODE
  121. msr cpsr,r0
  122. @vector 0x0
  123. @enable icaches
  124. @little endian
  125. @disable dcaches, mmu
  126. //ldr r0, =0x00400078
  127. @ldr r0, =0x0000107a
  128. // mcr p15, 0, r0, c1, c0, 0
  129. //read
  130. ldr r0, =0x0
  131. mrc p15, 0, r0, c1, c0, 0
  132. //change
  133. ldr r0, =0x00400078
  134. mcr p15, 0, r0, c1, c0, 0
  135. //check
  136. ldr r0, =0x0
  137. mrc p15, 0, r0, c1, c0, 0
  138. ldr r0, =0x00000000
  139. mcr p15, 0, r0, c8, c7, 0 @ Flush TLB
  140. mcr p15, 0, r0, c7, c7, 0 @ Flush Caches
  141. mcr p15, 0, r0, c7, c10, 4 @ Flush Write Buffer
  142. /* mask all IRQs by clearing all bits in the INTMRs set low and high to 0 */
  143. ldr r1, =FH81_INTC_BASE
  144. ldr r0, =0x0
  145. str r0, [r1]
  146. str r0, [r1, #4]
  147. /* setup stack */
  148. bl stack_setup
  149. /* clear .bss */
  150. mov r0,#0 /* get a zero */
  151. ldr r1,=__bss_start /* bss start */
  152. ldr r2,=__bss_end /* bss end */
  153. bss_loop:
  154. cmp r1,r2 /* check if data to clear */
  155. strlo r0,[r1],#4 /* clear 4 bytes */
  156. blo bss_loop /* loop until done */
  157. /* call C++ constructors of global objects */
  158. ldr r0, =__ctors_start__
  159. ldr r1, =__ctors_end__
  160. ctor_loop:
  161. cmp r0, r1
  162. beq ctor_end
  163. ldr r2, [r0], #4
  164. stmfd sp!, {r0-r1}
  165. mov lr, pc
  166. bx r2
  167. ldmfd sp!, {r0-r1}
  168. b ctor_loop
  169. ctor_end:
  170. /* enable_unaligned_access */
  171. mrc p15, 0, r0, c1, c0, 0
  172. bic r0, r0, #0x02 /*Clear the A bit, bit 1*/
  173. and r0, r0, #(1 << 22) /*Set the U bit, bit 22*/
  174. mcr p15, 0, r0, c1, c0, 0
  175. #ifdef RT_USING_VFP
  176. bl vfp_init
  177. #endif
  178. /* start RT-Thread Kernel */
  179. ldr pc, _rtthread_startup
  180. _rtthread_startup:
  181. .word rtthread_startup
  182. .global cpu_reset
  183. cpu_reset:
  184. #ldr r0, =0xfffffd00
  185. #ldr r1, =(AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST)
  186. #str r1, [r0]
  187. #mov pc, lr
  188. B cpu_reset
  189. /*
  190. *************************************************************************
  191. *
  192. * Interrupt handling
  193. *
  194. *************************************************************************
  195. */
  196. .macro push_exp_reg
  197. sub sp, sp, #S_FRAME_SIZE @/* Sizeof(struct rt_hw_stack) */
  198. stmib sp, {r0 - r12} @/* Calling r0-r12 */
  199. mov r0, sp
  200. mrs r6, spsr @/* Save CPSR */
  201. str lr, [r0, #S_PC] @/* Push PC */
  202. str r6, [r0, #S_CPSR] @/* Push CPSR */
  203. @ switch to SVC mode with no interrupt
  204. msr cpsr_c, #I_BIT|F_BIT|SVCMODE
  205. str sp, [r0, #S_SP] @/* Save calling SP */
  206. str lr, [r0, #S_LR] @/* Save calling PC */
  207. .endm
  208. #ifdef RT_USING_VFP
  209. __ret_to_undef:
  210. ldmfd sp!, {r4} @ pop task's cpsr to spsr
  211. msr spsr_cxsf, r4
  212. ldmfd sp!, {r0-r12}
  213. add sp, sp, #4
  214. ldmfd sp!, {lr,pc}^
  215. #endif
  216. /* exception handlers */
  217. .align 5
  218. vector_undef:
  219. push_exp_reg
  220. #ifdef RT_USING_VFP
  221. cps #UNDEFMODE
  222. ldr r2, [r0, #S_PC] @ r2=faulted PC+4
  223. adr r9, __ret_to_undef @ r9=exception success return
  224. sub r1, r2, #4
  225. ldr r0, [r1] @ r0=faulted instruction
  226. bl undef_entry
  227. mov r0, sp
  228. #endif
  229. bl rt_hw_trap_udef
  230. .align 5
  231. vector_swi:
  232. push_exp_reg
  233. bl rt_hw_trap_swi
  234. .align 5
  235. vector_pabt:
  236. push_exp_reg
  237. bl rt_hw_trap_pabt
  238. .align 5
  239. vector_dabt:
  240. push_exp_reg
  241. bl rt_hw_trap_dabt
  242. .align 5
  243. vector_resv:
  244. push_exp_reg
  245. bl rt_hw_trap_resv
  246. .globl rt_interrupt_enter
  247. .globl rt_interrupt_leave
  248. .globl rt_thread_switch_interrupt_flag
  249. .globl rt_interrupt_from_thread
  250. .globl rt_interrupt_to_thread
  251. vector_irq:
  252. stmfd sp!, {r0-r12,lr}
  253. @
  254. #ifdef RT_USING_VFP
  255. vmrs r0, fpexc
  256. stmfd sp!, {r0} @ save VFP status -- irq_fpexc = fpexc
  257. bic r0, r0, #FPEXC_EN @ always disable VFP so we can
  258. @ lazily save/restore the old state.
  259. vmsr fpexc, r0
  260. #endif
  261. bl rt_interrupt_enter
  262. bl rt_hw_trap_irq
  263. bl rt_interrupt_leave
  264. #ifdef RT_USING_VFP
  265. ldmfd sp!, {r1}
  266. vmrs r0, fpexc
  267. tst r0, #FPEXC_EN @ irq used VFP?
  268. bicne r1, r0, #FPEXC_EN @ if irq used VFP, then clear fpexc.en bit
  269. vmsr fpexc, r1 @ restore VFP status
  270. @ if irq not used VFP, then fpexc = irq_fpexc
  271. @ if irq used VFP, then disable VFP
  272. #endif
  273. @ if rt_thread_switch_interrupt_flag set, jump to
  274. @ rt_hw_context_switch_interrupt_do and don't return
  275. ldr r0, =rt_thread_switch_interrupt_flag
  276. ldr r1, [r0]
  277. cmp r1, #1
  278. beq rt_hw_context_switch_interrupt_do
  279. ldmfd sp!, {r0-r12,lr}
  280. @mrs r8,spsr
  281. @msr cpsr, r8
  282. subs pc, lr, #4
  283. .align 5
  284. vector_fiq:
  285. stmfd sp!,{r0-r7,lr}
  286. bl rt_hw_trap_fiq
  287. ldmfd sp!,{r0-r7,lr}
  288. subs pc,lr,#4
  289. rt_hw_context_switch_interrupt_do:
  290. mov r1, #0 @ clear flag
  291. str r1, [r0]
  292. ldmfd sp!, {r0-r12,lr}@ reload saved registers
  293. stmfd sp, {r0-r2} @ save r0-r2
  294. mrs r0, spsr @ get cpsr of interrupt thread
  295. sub r1, sp, #4*3
  296. sub r2, lr, #4 @ save old task's pc to r2
  297. @ switch to SVC mode with no interrupt
  298. msr cpsr_c, #I_BIT|F_BIT|SVCMODE
  299. stmfd sp!, {r2} @ push old task's pc
  300. stmfd sp!, {r3-r12,lr}@ push old task's lr,r12-r4
  301. ldmfd r1, {r1-r3} @ restore r0-r2 of the interrupt thread
  302. stmfd sp!, {r1-r3} @ push old task's r0-r2
  303. stmfd sp!, {r0} @ push old task's cpsr
  304. ldr r4, =rt_interrupt_from_thread
  305. ldr r5, [r4]
  306. str sp, [r5] @ store sp in preempted tasks's TCB
  307. ldr r6, =rt_interrupt_to_thread
  308. ldr r6, [r6]
  309. ldr sp, [r6] @ get new task's stack pointer
  310. ldmfd sp!, {r4} @ pop new task's cpsr to spsr
  311. msr spsr_cxsf, r4
  312. #ifdef RT_USING_VFP
  313. vmrs r0, fpexc
  314. bic r0, r0, #FPEXC_EN @ always disable VFP so we can
  315. @ lazily save/restore the old state.
  316. vmsr fpexc, r0
  317. #endif
  318. ldmfd sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr
  319. stack_setup:
  320. mrs r0, cpsr
  321. bic r0, r0, #MODEMASK
  322. orr r1, r0, #UNDEFMODE|NOINT
  323. msr cpsr_cxsf, r1 /* undef mode */
  324. ldr sp, UNDEFINED_STACK_START
  325. orr r1,r0,#ABORTMODE|NOINT
  326. msr cpsr_cxsf,r1 /* abort mode */
  327. ldr sp, ABORT_STACK_START
  328. orr r1,r0,#IRQMODE|NOINT
  329. msr cpsr_cxsf,r1 /* IRQ mode */
  330. ldr sp, IRQ_STACK_START
  331. orr r1,r0,#FIQMODE|NOINT
  332. msr cpsr_cxsf,r1 /* FIQ mode */
  333. ldr sp, FIQ_STACK_START
  334. bic r0,r0,#MODEMASK
  335. orr r1,r0,#SVCMODE|NOINT
  336. msr cpsr_cxsf,r1 /* SVC mode */
  337. ldr sp, _STACK_START
  338. /* USER mode is not initialized. */
  339. bx lr /* The LR register may be not valid for the mode changes.*/
  340. /*/*}*/