startup_gcc.S 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. .extern main /* 引入外部C入口 */
  2. .extern __bss_beg__
  3. .extern __bss_end__
  4. .extern __stack_end__
  5. .extern __data_beg__
  6. .extern __data_end__
  7. .extern __data+beg_src__
  8. .extern rt_interrupt_enter
  9. .extern rt_interrupt_leave
  10. .extern rt_thread_switch_interrput_flag
  11. .extern rt_interrupt_from_thread
  12. .extern rt_interrupt_to_thread
  13. .extern rt_hw_trap_irq
  14. .global start
  15. .global endless_loop
  16. .global rt_hw_context_switch_interrupt_do
  17. /************* 目标配置 *************/
  18. .set UND_STACK_SIZE, 0x00000004
  19. .set ABT_STACK_SIZE, 0x00000004
  20. .set FIQ_STACK_SIZE, 0x00000004
  21. .set IRQ_STACK_SIZE, 0x00000400
  22. .set SVC_STACK_SIZE, 0x00000400
  23. .set UND_Stack_Size, 0x00000004
  24. .set ABT_Stack_Size, 0x00000004
  25. .set FIQ_Stack_Size, 0x00000004
  26. .set IRQ_Stack_Size, 0x00000400
  27. .set SVC_Stack_Size, 0x00000400
  28. /* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs */
  29. .set MODE_USR, 0x10 /* User Mode */
  30. .set MODE_FIQ, 0x11 /* FIQ Mode */
  31. .set MODE_IRQ, 0x12 /* IRQ Mode */
  32. .set MODE_SVC, 0x13 /* Supervisor Mode */
  33. .set MODE_ABT, 0x17 /* Abort Mode */
  34. .set MODE_UND, 0x1B /* Undefined Mode */
  35. .set MODE_SYS, 0x1F /* System Mode */
  36. .set MODE_USR, 0x10 /* User Mode */
  37. .set Mode_FIQ, 0x11 /* FIQ Mode */
  38. .set Mode_IRQ, 0x12 /* IRQ Mode */
  39. .set Mode_SVC, 0x13 /* Supervisor Mode */
  40. .set Mode_ABT, 0x17 /* Abort Mode */
  41. .set Mode_UND, 0x1B /* Undefined Mode */
  42. .set Mode_SYS, 0x1F /* System Mode */
  43. .equ I_BIT, 0x80 /* when I bit is set, IRQ is disabled */
  44. .equ F_BIT, 0x40 /* when F bit is set, FIQ is disabled */
  45. .equ I_Bit, 0x80 /* when I bit is set, IRQ is disabled */
  46. .equ F_Bit, 0x40 /* when F bit is set, FIQ is disabled */
  47. /* VPBDIV definitions*/
  48. .equ VPBDIV, 0xE01FC100
  49. .set VPBDIV_VALUE, 0x00000000
  50. /* Phase Locked Loop (PLL) definitions*/
  51. .equ PLL_BASE, 0xE01FC080
  52. .equ PLLCON_OFS, 0x00
  53. .equ PLLCFG_OFS, 0x04
  54. .equ PLLSTAT_OFS, 0x08
  55. .equ PLLFEED_OFS, 0x0C
  56. .equ PLLCON_PLLE, (1<<0) /* PLL Enable */
  57. .equ PLLCON_PLLC, (1<<1) /* PLL Connect */
  58. .equ PLLSTAT_LOCK, (1<<10) /* PLL Lock Status */
  59. .equ PLLCFG_MSEL, ((PLL_MUL - 1) << 0)
  60. .equ PLLCFG_PSEL, (0x02 << 5)
  61. .equ PLLCFG_Val, (PLLCFG_MSEL|PLLCFG_PSEL)
  62. .equ MEMMAP, 0xE01FC040 /*Memory Mapping Control*/
  63. /* Memory Accelerator Module (MAM) definitions*/
  64. .equ MAM_BASE, 0xE01FC000
  65. .equ MAMCR_OFS, 0x00
  66. .equ MAMTIM_OFS, 0x04
  67. .equ MAMCR_Val, 0x00000002
  68. .equ MAMTIM_Val, 0x00000004
  69. .equ VICIntEnClr, 0xFFFFF014
  70. .equ VICIntSelect, 0xFFFFF00C
  71. /************* 目标配置结束 *************/
  72. /* Setup the operating mode & stack.*/
  73. /* --------------------------------- */
  74. .global _start, start, _reset, reset,
  75. .func _start,
  76. _start:
  77. start:
  78. _reset:
  79. reset:
  80. .code 32
  81. .align 0
  82. /************************* PLL_SETUP **********************************/
  83. #if (PLL_MUL>1)
  84. ldr r0, =PLL_BASE
  85. mov r1, #0xAA
  86. mov r2, #0x55
  87. /* Configure and Enable PLL */
  88. mov r3, #PLLCFG_Val
  89. str r3, [r0, #PLLCFG_OFS]
  90. mov r3, #PLLCON_PLLE
  91. str r3, [r0, #PLLCON_OFS]
  92. str r1, [r0, #PLLFEED_OFS]
  93. str r2, [r0, #PLLFEED_OFS]
  94. /* Wait until PLL Locked */
  95. PLL_Locked_loop:
  96. ldr r3, [r0, #PLLSTAT_OFS]
  97. ands r3, r3, #PLLSTAT_LOCK
  98. beq PLL_Locked_loop
  99. /* Switch to PLL Clock */
  100. mov r3, #(PLLCON_PLLE|PLLCON_PLLC)
  101. str r3, [r0, #PLLCON_OFS]
  102. str r1, [r0, #PLLFEED_OFS]
  103. str R2, [r0, #PLLFEED_OFS]
  104. #endif
  105. /************************* PLL_SETUP **********************************/
  106. /************************ Setup VPBDIV ********************************/
  107. ldr r0, =VPBDIV
  108. ldr r1, =VPBDIV_VALUE
  109. str r1, [r0]
  110. /************************ Setup VPBDIV ********************************/
  111. /************** Setup MAM **************/
  112. ldr r0, =MAM_BASE
  113. mov r1, #MAMTIM_Val
  114. str r1, [r0, #MAMTIM_OFS]
  115. mov r1, #MAMCR_Val
  116. str r1, [r0, #MAMCR_OFS]
  117. /************** Setup MAM **************/
  118. /************************ setup stack *********************************/
  119. ldr r0, .LC6 /* LC6:__stack_end__ */
  120. msr CPSR_c, #MODE_UND|I_BIT|F_BIT /* Undefined Instruction Mode */
  121. mov sp, r0
  122. sub r0, r0, #UND_STACK_SIZE
  123. msr CPSR_c, #MODE_ABT|I_BIT|F_BIT /* Abort Mode */
  124. mov sp, r0
  125. sub r0, r0, #ABT_STACK_SIZE
  126. msr CPSR_c, #MODE_FIQ|I_BIT|F_BIT /* FIQ Mode */
  127. mov sp, r0
  128. sub r0, r0, #FIQ_STACK_SIZE
  129. msr CPSR_c, #MODE_IRQ|I_BIT|F_BIT /* IRQ Mode */
  130. mov sp, r0
  131. sub r0, r0, #IRQ_STACK_SIZE
  132. msr CPSR_c, #MODE_SVC|I_BIT|F_BIT /* Supervisor Mode */
  133. mov sp, r0
  134. /************************ setup stack ********************************/
  135. /************************ Clear BSS ********************************/
  136. /* Clear BSS. */
  137. mov a2, #0 /* Fill value */
  138. mov fp, a2 /* Null frame pointer */
  139. mov r7, a2 /* Null frame pointer for Thumb */
  140. ldr r1, .LC1 /* Start of memory block */
  141. ldr r3, .LC2 /* End of memory block */
  142. subs r3, r3, r1 /* Length of block */
  143. beq .end_clear_loop
  144. mov r2, #0
  145. .clear_loop:
  146. strb r2, [r1], #1
  147. subs r3, r3, #1
  148. bgt .clear_loop
  149. .end_clear_loop:
  150. /* Initialise data. */
  151. ldr r1, .LC3 /* Start of memory block */
  152. ldr r2, .LC4 /* End of memory block */
  153. ldr r3, .LC5
  154. subs r3, r3, r1 /* Length of block */
  155. beq .end_set_loop
  156. .set_loop:
  157. ldrb r4, [r2], #1
  158. strb r4, [r1], #1
  159. subs r3, r3, #1
  160. bgt .set_loop
  161. .end_set_loop:
  162. mov r0, #0 /* no arguments */
  163. mov r1, #0 /* no argv either */
  164. bl main
  165. endless_loop:
  166. b endless_loop
  167. .align 0
  168. .LC1:
  169. .word __bss_beg__
  170. .LC2:
  171. .word __bss_end__
  172. .LC3:
  173. .word __data_beg__
  174. .LC4:
  175. .word __data_beg_src__
  176. .LC5:
  177. .word __data_end__
  178. .LC6:
  179. .word __stack_end__
  180. /*********************** END Clear BSS ******************************/
  181. /******************** 跳转到 main() ********************/
  182. LDR R0, =main /* 获得main()入口地址 */
  183. BX R0 /* 长跳转到main() */
  184. /******************** 跳转到 main() ********************/
  185. /* 本段为.startup段 在链接脚本中被链接到程序最开头 */
  186. .section .startup,"ax"
  187. .code 32
  188. .align 0
  189. ldr pc, __start /* reset - _start */
  190. ldr pc, _undf /* undefined - _undf */
  191. ldr pc, _swi /* SWI - _swi */
  192. ldr pc, _pabt /* program abort - _pabt */
  193. ldr pc, _dabt /* data abort - _dabt */
  194. //.word 0xB9205F80 /* 默认 0xB9205F80 */
  195. .word 0xB8A06F58 /* 0xB8A06F58 全为 */
  196. ldr pc, __IRQ_Handler /* IRQ - read the VIC */
  197. ldr pc, _fiq /* FIQ - _fiq */
  198. __start:.word _start
  199. _undf: .word __undf /* undefined */
  200. _swi: .word __swi /* SWI */
  201. _pabt: .word __pabt /* program abort */
  202. _dabt: .word __dabt /* data abort */
  203. temp1: .word 0
  204. __IRQ_Handler: .word IRQ_Handler
  205. _fiq: .word __fiq /* FIQ */
  206. __undf: b . /* undefined */
  207. __swi : b .
  208. __pabt: b . /* program abort */
  209. __dabt: b . /* data abort */
  210. __fiq : b . /* FIQ */
  211. /* IRQ入口 */
  212. IRQ_Handler :
  213. stmfd sp!, {r0-r12,lr} /* 对R0 – R12,LR寄存器压栈 */
  214. bl rt_interrupt_enter /* 通知RT-Thread进入中断模式 */
  215. bl rt_hw_trap_irq /* 相应中断服务例程处理 */
  216. bl rt_interrupt_leave /* ; 通知RT-Thread要离开中断模式 */
  217. /* 如果设置了rt_thread_switch_interrput_flag,进行中断中的线程上下文处理 */
  218. ldr r0, =rt_thread_switch_interrput_flag
  219. ldr r1, [r0]
  220. cmp r1, #1
  221. beq rt_hw_context_switch_interrupt_do /* 中断中切换发生 */
  222. /* 如果跳转了,将不会回来 */
  223. ldmfd sp!, {r0-r12,lr} /* 恢复栈 */
  224. subs pc, lr, #4 /* 从IRQ中返回 */
  225. /*
  226. * void rt_hw_context_switch_interrupt_do(rt_base_t flag)
  227. * 中断结束后的上下文切换
  228. */
  229. rt_hw_context_switch_interrupt_do:
  230. mov r1, #0 /* clear flag */
  231. /* 清楚中断中切换标志 */
  232. str r1, [r0] /* */
  233. ldmfd sp!, {r0-r12,lr}/* reload saved registers */
  234. /* 先恢复被中断线程的上下文 */
  235. stmfd sp!, {r0-r3} /* save r0-r3 */
  236. /* 对R0 – R3压栈,因为后面会用到 */
  237. mov r1, sp /* 把此处的栈值保存到R1 */
  238. add sp, sp, #16 /* restore sp */
  239. /* 恢复IRQ的栈,后面会跳出IRQ模式 */
  240. sub r2, lr, #4 /* save old task's pc to r2 */
  241. /* 保存切换出线程的PC到R2 */
  242. mrs r3, spsr /* disable interrupt 保存中断前的CPSR到R3寄存器 */
  243. /* 获得SPSR寄存器值 */
  244. orr r0, r3, #I_BIT|F_BIT
  245. msr spsr_c, r0 /* 关闭SPSR中的IRQ/FIQ中断 */
  246. ldr r0, =.+8 /* 把当前地址+8载入到R0寄存器中 switch to interrupted task's stack */
  247. movs pc, r0 /* 退出IRQ模式,由于SPSR被设置成关中断模式 */
  248. /* 所以从IRQ返回后,中断并没有打开
  249. ; R0寄存器中的位置实际就是下一条指令,
  250. ; 即PC继续往下走
  251. ; 此时
  252. ; 模式已经换成中断前的SVC模式,
  253. ; SP寄存器也是SVC模式下的栈寄存器
  254. ; R1保存IRQ模式下的栈指针
  255. ; R2保存切换出线程的PC
  256. ; R3保存切换出线程的CPSR */
  257. stmfd sp!, {r2} /* push old task's pc */
  258. /* 保存切换出任务的PC */
  259. stmfd sp!, {r4-r12,lr}/* push old task's lr,r12-r4 */
  260. /* 保存R4 – R12,LR寄存器 */
  261. mov r4, r1 /* Special optimised code below */
  262. /* R1保存有压栈R0 – R3处的栈位置 */
  263. mov r5, r3 /* R3切换出线程的CPSR */
  264. ldmfd r4!, {r0-r3} /* 恢复R0 – R3 */
  265. stmfd sp!, {r0-r3} /* push old task's r3-r0 */
  266. /* R0 – R3压栈到切换出线程 */
  267. stmfd sp!, {r5} /* push old task's psr */
  268. /* 切换出线程CPSR压栈 */
  269. mrs r4, spsr
  270. stmfd sp!, {r4} /* push old task's spsr */
  271. /* 切换出线程SPSR压栈 */
  272. ldr r4, =rt_interrupt_from_thread
  273. ldr r5, [r4]
  274. str sp, [r5] /* store sp in preempted tasks's TCB */
  275. /* 保存切换出线程的SP指针 */
  276. ldr r6, =rt_interrupt_to_thread
  277. ldr r6, [r6]
  278. ldr sp, [r6] /* get new task's stack pointer */
  279. /* 获得切换到线程的栈 */
  280. ldmfd sp!, {r4} /* pop new task's spsr */
  281. /* 恢复SPSR */
  282. msr SPSR_cxsf, r4
  283. ldmfd sp!, {r4} /* pop new task's psr */
  284. /* 恢复CPSR */
  285. msr CPSR_cxsf, r4
  286. ldmfd sp!, {r0-r12,lr,pc} /* pop new task's r0-r12,lr & pc */
  287. /* 恢复R0 – R12,LR及PC寄存器 */
  288. /* 代码加密功能 */
  289. #if defined(CODE_PROTECTION)
  290. .org 0x01FC
  291. .word 0x87654321
  292. #endif