start_gcc.S 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. #include "rtconfig.h"
  2. .text
  3. .align 4
  4. .section ".EL2_core_exceptions_table", "ax"
  5. .globl EL2_core_exceptions_table
  6. .type EL2_core_exceptions_table, %function
  7. EL2_core_exceptions_table:
  8. b EL2_Reset_Handler /* Reset Handler */
  9. b EL2_Undefined_Handler /* Undefined Handler */
  10. b EL2_HVC_Handler /* SVCall Handler */
  11. b EL2_Prefetch_Handler /* Prefetch Handler */
  12. b EL2_Abort_Handler /* Abort Handler */
  13. b EL2_Trap_Handler /* Reserved */
  14. b EL2_IRQ_Handler /* IRQ Handler */
  15. b EL2_FIQ_Handler /* FIQ Handler */
  16. .arm
  17. .align 4
  18. .section ".EL1_core_exceptions_table", "ax"
  19. EL1_core_exceptions_table:
  20. b EL1_Reset_Handler
  21. b Undefined_Handler
  22. b SVC_Handler
  23. b Prefetch_Handler
  24. b Abort_Handler
  25. b Reserved_Handler
  26. b IRQ_Handler
  27. b FIQ_Handler
  28. /* Reset Handler */
  29. .text
  30. .align 4
  31. .section ".EL2_Reset_Handler", "ax"
  32. .globl EL2_Reset_Handler
  33. .type EL2_Reset_Handler, %function
  34. EL2_Reset_Handler:
  35. mov r0, #0
  36. mov r1, r0
  37. mov r2, r0
  38. mov r3, r0
  39. mov r4, r0
  40. mov r5, r0
  41. mov r6, r0
  42. mov r7, r0
  43. mov r8, r0
  44. mov r9, r0
  45. mov r10, r0
  46. mov r11, r0
  47. mov r12, r0
  48. #ifdef RT_USING_FPU
  49. mrc p15, #0x00, r2, c1, c0, #0x02
  50. orr r2, r2, #0xF00000
  51. mcr p15, #0x00, r2, c1, c0, #0x02
  52. fmrx r2, fpexc
  53. orr r2, r2, #0x40000000
  54. fmxr fpexc, r2
  55. #endif
  56. ldr r0, =0x23000003
  57. MCR p15, 0, r0, c15, c0, 0
  58. /*---------------TCM Initialization-------------------*/
  59. ldr r0, =0x0A000000 /* ATCM base address */
  60. ldr r1, =0x00010000 /* TCM size: 64KB */
  61. mov r2, #0 /* Clear value */
  62. tcm_init_loop:
  63. str r2, [r0], #4 /* Write and increment */
  64. subs r1, r1, #4 /* Decrement counter */
  65. bne tcm_init_loop /* Continue if not zero */
  66. dsb /* Data synchronization barrier */
  67. isb /* Instruction synchronization barrier */
  68. b MPU_Init
  69. MPU_Init:
  70. mrc p15, 4, r0, c1, c0, 0 /* Read HSCTLR */
  71. and r0, r0, #0xFFFFFFFE /* set HSCTLR.M bit to 0, disable EL2 MPU */
  72. mcr p15, 4, r0, c1, c0, 0 /* write HSCTLR */
  73. mrc p15, 0, r0, c1, c0, 0 /* Read SCTLR */
  74. and r0, r0, #0xFFFFFFFE /* set SCTLR.M bit to 0, disable EL1 MPU */
  75. mcr p15, 0, r0, c1, c0, 0 /* write SCTLR */
  76. mrc p15, 0, r0, c1, c0, 0
  77. orr r0, r0, #(0x1 << 12) /*icache */
  78. orr r0, r0, #(0x1 << 2) /*dcache */
  79. mcr p15, 0, r0, c1, c0, 0
  80. disalbe_mpu_region_loop:
  81. mov r0, r3 /* select region */
  82. mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
  83. mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
  84. mrc p15, 4, r0, c6, c3, 1 /* Read From HPRLAR */
  85. and r0, r0, #0xFFFFFFFE
  86. mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
  87. mrc p15, 0, r0, c6, c3, 1 /* Read From PRLAR */
  88. and r0, r0, #0xFFFFFFFE
  89. mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
  90. add r3, r3, #1
  91. cmp r3, #24 /* hsm has only 16 mpu regions */
  92. blt disalbe_mpu_region_loop
  93. /* region 0 cluster0/cluster1 tcm */
  94. /* normal memory attribute */
  95. ldr r0, =0 /* Region 0 */
  96. mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
  97. mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
  98. ldr r0, =0x08000000 /* Start address */
  99. orr r0, r0, #0x2 /* SH=0, AP=1, XN=0*/
  100. mcr p15, 4, r0, c6, c3, 0 /* Write HPRBAR */
  101. mcr p15, 0, r0, c6, c3, 0 /* Write PRBAR */
  102. ldr r0, =0x0AFFFFFF /* End address */
  103. and r0, r0, #0xFFFFFFC0
  104. orr r0, r0, #0x3 /* AttrIndex=1, non-cacheable, enable region */
  105. mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
  106. mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
  107. /*---------------region 1 mcu sram (uncacheable)---------------*/
  108. /* normal memory attribute */
  109. ldr r0, =1 /* Region 1 */
  110. mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
  111. mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
  112. ldr r0, =0x0C800000 /* Start address */
  113. orr r0, r0, #0x2 /* SH=0, AP=1, XN=0*/
  114. mcr p15, 4, r0, c6, c3, 0 /* Write HPRBAR */
  115. mcr p15, 0, r0, c6, c3, 0 /* Write PRBAR */
  116. ldr r0, =0x0CAAFFFF /* End address */
  117. and r0, r0, #0xFFFFFFC0
  118. orr r0, r0, #0x3 /* AttrIndex=1, non-cacheable, enable region */
  119. mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
  120. mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
  121. /*---------------region 2 image read-only (cacheable, executable)---------------*/
  122. /* 0x0CAB0000 ~ (__image_rw_start__ - 64), startup/text/rodata */
  123. ldr r0, =2 /* Region 2 */
  124. mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
  125. mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
  126. ldr r0, =0x0CAB0000 /* Start: FLASH_STARTUP (64-byte aligned) */
  127. orr r0, r0, #0x6 /* SH=0, AP=3, XN=0 */
  128. mcr p15, 4, r0, c6, c3, 0 /* Write HPRBAR */
  129. mcr p15, 0, r0, c6, c3, 0 /* Write PRBAR */
  130. ldr r0, =__image_rw_start__ /* End address: __image_rw_start__ is 64-byte aligned */
  131. sub r0, r0, #0x40 /* Limit = __image_rw_start__ - 64 */
  132. orr r0, r0, #0x1 /* AttrIndex=0, cacheable, enable region */
  133. mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
  134. mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
  135. /*---------------region 4 image read-write (cacheable, XN)----------------*/
  136. ldr r0, =4 /* Region 4 */
  137. mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
  138. mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
  139. ldr r0, =__image_rw_start__ /* __image_rw_start__ is 64-byte aligned */
  140. and r0, r0, #0xFFFFFFC0 /* Ensure 64-byte alignment */
  141. orr r0, r0, #0x12 /* SH=0, AP=1, XN=1 */
  142. mcr p15, 4, r0, c6, c3, 0 /* Write HPRBAR */
  143. mcr p15, 0, r0, c6, c3, 0 /* Write PRBAR */
  144. ldr r0, =__image_rw_end__ /* End address: __image_rw_end__ is 64-byte aligned */
  145. sub r0, r0, #0x40 /* Limit = __image_rw_end__ - 64 */
  146. orr r0, r0, #0x1 /* AttrIndex=0, cacheable, enable region */
  147. mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
  148. mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
  149. /* Keep __image_rw_end__ ~ OS_HEAP_START_ADDR unmapped as a guard gap. */
  150. /*---------------region 5 RTOS heap (cacheable, XN)----------------*/
  151. ldr r0, =5 /* Region 5 */
  152. mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
  153. mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
  154. ldr r0, =OS_HEAP_START_ADDR /* OS_HEAP_START_ADDR is 64-byte aligned */
  155. and r0, r0, #0xFFFFFFC0 /* Ensure 64-byte alignment */
  156. orr r0, r0, #0x12 /* SH=0, AP=1, XN=1 */
  157. mcr p15, 4, r0, c6, c3, 0 /* Write HPRBAR */
  158. mcr p15, 0, r0, c6, c3, 0 /* Write PRBAR */
  159. ldr r0, =OS_HEAP_END_ADDR /* End address: OS_HEAP_END_ADDR is 64-byte aligned */
  160. sub r0, r0, #0x40 /* Limit = OS_HEAP_END_ADDR - 64 */
  161. orr r0, r0, #0x1 /* AttrIndex=0, cacheable, enable region */
  162. mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
  163. mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
  164. /*---------------region 11 shared/reserved SRAM (non-cacheable, XN)----------------*/
  165. ldr r0, =11 /* Region 11 */
  166. mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
  167. mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
  168. ldr r0, =OS_HEAP_END_ADDR /* OS_HEAP_END_ADDR is 64-byte aligned */
  169. and r0, r0, #0xFFFFFFC0 /* Ensure 64-byte alignment */
  170. orr r0, r0, #0x12 /* SH=0, AP=1, XN=1 */
  171. mcr p15, 4, r0, c6, c3, 0 /* Write HPRBAR */
  172. mcr p15, 0, r0, c6, c3, 0 /* Write PRBAR */
  173. ldr r0, =0x0CDFFFFF /* End address */
  174. and r0, r0, #0xFFFFFFC0
  175. orr r0, r0, #0x3 /* AttrIndex=1, non-cacheable, enable region */
  176. mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
  177. mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
  178. /*---------------region 6 internal gic & peripheral---------------*/
  179. /* device memory attribute */
  180. ldr r0, =6 /* Region 6 */
  181. mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
  182. mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
  183. ldr r0, =0x22000000 /* Start address */
  184. orr r0, r0, #0x13 /* SH=2, AP=1, XN=1*/
  185. mcr p15, 4, r0, c6, c3, 0 /* Write HPRBAR */
  186. mcr p15, 0, r0, c6, c3, 0 /* Write PRBAR */
  187. ldr r0, =0x223FFFFF /* End address */
  188. sub r0, r0, #1
  189. and r0, r0, #0xFFFFFFC0
  190. orr r0, r0, #0x7 /* AttrIndex=3, device memory, enable region */
  191. mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
  192. mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
  193. /*---------------region 7 peripheral---------------*/
  194. /* device memory attribute */
  195. ldr r0, =7 /* Region 7 */
  196. mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
  197. mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
  198. ldr r0, =0x23000000 /* Start address */
  199. orr r0, r0, #0x13 /* SH=2, AP=1, XN=1*/
  200. mcr p15, 4, r0, c6, c3, 0 /* Write HPRBAR */
  201. mcr p15, 0, r0, c6, c3, 0 /* Write PRBAR */
  202. ldr r0, =0x2FFFFFFF /* End address */
  203. sub r0, r0, #1
  204. and r0, r0, #0xFFFFFFC0
  205. orr r0, r0, #0x7 /* AttrIndex=3, device memory, enable region */
  206. mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
  207. mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
  208. /*---------------region 8 CPUSYS------------------*/
  209. ldr r0, =8 /* Region 8 */
  210. mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
  211. mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
  212. ldr r0, =0x30000000 /* Start address */
  213. orr r0, r0, #0x13 /* SH=2, AP=1, XN=1*/
  214. mcr p15, 4, r0, c6, c3, 0 /* Write HPRBAR */
  215. mcr p15, 0, r0, c6, c3, 0 /* Write PRBAR */
  216. ldr r0, =0x3FFFFFFF /* End address */
  217. and r0, r0, #0xFFFFFFC0
  218. orr r0, r0, #0x7 /* AttrIndex=3, device memory, enable region */
  219. mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
  220. mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
  221. /*---------------region 9 DDR-------------------*/
  222. ldr r0, =9 /* Region 9 */
  223. mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
  224. mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
  225. ldr r0, =0x80000000 /* Start address */
  226. orr r0, r0, #0x2 /* SH=0, AP=1, XN=0*/
  227. mcr p15, 4, r0, c6, c3, 0 /* Write HPRBAR */
  228. mcr p15, 0, r0, c6, c3, 0 /* Write PRBAR */
  229. ldr r0, =0xFFFFFFFF /* End address */
  230. and r0, r0, #0xFFFFFFC0
  231. orr r0, r0, #0x3 /* AttrIndex=1, enable region */
  232. mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
  233. mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
  234. /*---------------region 10 xspi-------------------*/
  235. /* device memory attribute */
  236. ldr r0, =10 /* Region 10 */
  237. mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
  238. mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
  239. ldr r0, =0x18000000 /* Start address */
  240. orr r0, r0, #0x13 /* SH=2, AP=1, XN=1*/
  241. mcr p15, 4, r0, c6, c3, 0 /* Write HPRBAR */
  242. mcr p15, 0, r0, c6, c3, 0 /* Write PRBAR */
  243. ldr r0, =0x1FFFFFFF /* End address */
  244. and r0, r0, #0xFFFFFFC0
  245. orr r0, r0, #0x7 /* AttrIndex=3, device memory, enable region */
  246. mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
  247. mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
  248. /*---------------SET MAIR/HMAIR-------------------*/
  249. ldr r0, =0x44FF /* attr0(FF): normal memory, write-back non-transient */
  250. /* attr1(44): normal memory, non-cacheable */
  251. /* attr2~3(00): Device-nGnRnE memory */
  252. mcr p15, 4, r0, c10, c2, 0 /* Write HMAIR0 */
  253. mcr p15, 0, r0, c10, c2, 0 /* Write MAIR0 */
  254. ldr r0, =0x04 /* attr4~7(04/00): Device-nGnRnE memory */
  255. mcr p15, 4, r0, c10, c2, 1 /* Write HMAIR1 */
  256. mcr p15, 0, r0, c10, c2, 1 /* Write MAIR1 */
  257. mpu_enable:
  258. mrc p15, 4, r0, c1, c0, 0 /* Read HSCTLR */
  259. orr r0, r0, #0x1 /* Enable MPU */
  260. dsb
  261. mcr p15, 4, r0, c1, c0, 0 /* Write HSCTLR */
  262. isb
  263. mrc p15, 0, r0, c1, c0, 0 /* Read SCTLR */
  264. orr r0, r0, #0x1 /* Enable MPU */
  265. dsb
  266. mcr p15, 0, r0, c1, c0, 0 /* Write SCTLR */
  267. isb
  268. /* ARMv8-R cores are in EL2 (hypervisor mode) after reset, and we need
  269. to descend to EL1 (supervisor mode) or EL0 (user mode) */
  270. /* Init HVBAR (Hypervisor Vector Base Address Register) */
  271. ldr r0, =EL2_core_exceptions_table
  272. mcr p15, 4, r0, c12, c0, 0 /* Move to Coprocessor from ARM Register */
  273. /* Init VBAR (Vector Base Address Register) */
  274. ldr r0, =EL1_core_exceptions_table
  275. mcr p15, 0, r0, c12, c0, 0 /* Move to Coprocessor from ARM Register */
  276. init_mcu_stack:
  277. ldr r3, =__StackTop
  278. mov SP, r3
  279. bl init_bss
  280. /* Init ELR_hyp with EL1_Reset_Handler so eret can descend from EL2 to EL1. */
  281. ldr r0, =EL1_Reset_Handler
  282. msr ELR_hyp, r0
  283. mrs r0, SPSR_hyp
  284. and r0, r0, #~0x00FF /* r0 = r0 & FFFF FFE0. Clear SPSR_hyp bits [4:0] -> Execution state bit + Mode bits. */
  285. /* Return to EL1 system mode with interrupts masked until EL1 stack setup is done. */
  286. orr r0, r0, #0x1f
  287. bic r0, r0, #(0x1 << 5)
  288. msr SPSR_hyp, r0
  289. /* Configure the GIC CPU Interface */
  290. /* Disable group 0 interrupts */
  291. mov r0, #0x00
  292. mcr p15, 0, r0, c12, c12, 6 /* Write to ICC_IGRPEN0 */
  293. /* Enable group 1 interrupts */
  294. mov r0, #0x01
  295. mcr p15, 0, r0, c12, c12, 7 /* Write to ICC_IGRPEN1 */
  296. /* Set the interrupt priority mask to biggest value - 0x1F */
  297. /* Interrupts with all priorities are allowed. */
  298. mov r0, #0xF8 /* The priority bitfield is shifted with 3 bits - 0x1F becomes 0xF8 */
  299. mcr p15, 0, r0, c4, c6, 0 /* Write to ICC_PMR */
  300. /* Set the binary point for group 0 and group 1 interrupts */
  301. mov r0, #0
  302. mcr p15, 0, r0, c12, c8, 3 /* Write to ICC_BPR0 */
  303. mcr p15, 0, r0, c12, c12, 3 /* Write to ICC_BPR1 */
  304. /* Exception return - will jump to address pointed by ELR_hyp (main) */
  305. eret /* When executed in Hyp mode, ERET loads the PC from ELR_hyp and loads the CPSR from SPSR_hyp */
  306. .text
  307. .align 4
  308. .globl EL1_Reset_Handler
  309. .type EL1_Reset_Handler, %function
  310. EL1_Reset_Handler:
  311. /* Divide the non-USR mode stack area between the 5 non-USR modes */
  312. /* ABT,UND get 1/10 each. HYP, SVC,FIQ,IRQ get 1/5 each. */
  313. ldr r3, =__StackTop
  314. ldr r2, =__StackLimit
  315. sub r2, r3, r2 /* r2 : size in bytes */
  316. mov r4, #2
  317. udiv r1, r2, r4 /* r1 : size divided by 2 */
  318. and r1, r1, #~0x0f /* r1 size alligned to 16 bytes */
  319. /* Setup the stack for supervisor mode (entered from reset) */
  320. mrs r0, cpsr
  321. and r0, r0, #~0x00FF
  322. orr r0, r0, #0x0033
  323. msr cpsr_c, r0
  324. sub r3, r3, r1
  325. mov SP, r3 /* top of stack to SP_svc */
  326. ldr r3, =__StackTop_exc
  327. ldr r2, =__StackLimit_exc
  328. sub r2, r3, r2 /* r2 : size in bytes */
  329. mov r4, #4
  330. udiv r1, r2, r4 /* r1 : size divided by 4 */
  331. and r1, r1, #~0x0f /* r1 size alligned to 16 bytes */
  332. /* Go to FIQ mode and set stack (below the previous one) */
  333. mrs r0, cpsr
  334. and r0, r0, #~0x003F
  335. orr r0, r0, #0x0031
  336. msr cpsr_c, r0
  337. sub r3, r3, r1
  338. mov SP, r3
  339. /* Go to IRQ mode and set stack (below the previous one) */
  340. mrs r0, cpsr
  341. and r0, r0, #~0x003F
  342. orr r0, r0, #0x0032
  343. msr cpsr_c, r0
  344. sub r3, r3, r1
  345. mov SP, r3
  346. /* Go to ABORT mode and set stack (below the previous one) */
  347. mrs r0, cpsr
  348. and r0, r0, #~0x003F
  349. orr r0, r0, #0x0037
  350. msr cpsr_c, r0
  351. sub r3, r3, r1
  352. mov SP, r3
  353. /* Go to UNDEF mode and set stack (below the previous one) */
  354. mrs r0, cpsr
  355. and r0, r0, #~0x003F
  356. orr r0, r0, #0x003b
  357. msr cpsr_c, r0
  358. sub r3, r3, r1
  359. mov SP, r3
  360. /* Go to SYSTEM mode and set stack to the top of the reserved area */
  361. /* This is also the stack for user mode */
  362. mrs r0, cpsr
  363. and r0, r0, #~0x003F
  364. orr r0, r0, #0x003F
  365. msr cpsr_c, r0
  366. ldr r3, =__StackTop_exc
  367. mov SP, r3
  368. /* Enable IRQ and FIQ interrupts for the system/user mode */
  369. cpsie i /* Unmask interrupts (IRQ)*/
  370. cpsie f /* Unmask fast interrupts (FIQ)*/
  371. /* Go to supervisor mode */
  372. mrs r0, cpsr
  373. and r0, r0, #~0x00FF
  374. orr r0, r0, #0x0033
  375. msr cpsr_c, r0
  376. /* Jump to the entry() method */
  377. bl entry
  378. /* Should never get here */
  379. b .
  380. .text
  381. .align 4
  382. .globl init_bss
  383. .type init_bss, %function
  384. init_bss:
  385. ldr r1, =__bss_start
  386. ldr r2, =__bss_end
  387. mov r0, #0
  388. .clear_bss_loop:
  389. cmp r1, r2
  390. bcs .init_done
  391. str r0, [r1], #4
  392. b .clear_bss_loop
  393. .init_done:
  394. bx lr