1/* 2 * Copyright (c) 2006-2018, RT-Thread Development Team 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Change Logs: 7 * Date Author Notes 8 * 2006-03-13 Bernard first version 9 * 2006-10-05 Alsor.Z for s3c2440 initialize 10 * 2008-01-29 Yi.Qiu for QEMU emulator 11 */ 12 13#define CONFIG_STACKSIZE 512 14#define S_FRAME_SIZE 72 15 16#define S_OLD_R0 68 17#define S_PSR 64 18#define S_PC 60 19#define S_LR 56 20#define S_SP 52 21 22#define S_IP 48 23#define S_FP 44 24#define S_R10 40 25#define S_R9 36 26#define S_R8 32 27#define S_R7 28 28#define S_R6 24 29#define S_R5 20 30#define S_R4 16 31#define S_R3 12 32#define S_R2 8 33#define S_R1 4 34#define S_R0 0 35 36.equ USERMODE, 0x10 37.equ FIQMODE, 0x11 38.equ IRQMODE, 0x12 39.equ SVCMODE, 0x13 40.equ ABORTMODE, 0x17 41.equ UNDEFMODE, 0x1b 42.equ MODEMASK, 0x1f 43.equ NOINT, 0xc0 44 45.equ RAM_BASE, 0x00000000 /*Start address of RAM */ 46.equ ROM_BASE, 0x30000000 /*Start address of Flash */ 47 48.equ MPLLCON, 0x4c000004 /*Mpll control register */ 49.equ M_MDIV, 0x20 50.equ M_PDIV, 0x4 51.equ M_SDIV, 0x2 52 53.equ INTMSK, 0x4a000008 54.equ INTSUBMSK, 0x4a00001c 55.equ WTCON, 0x53000000 56.equ LOCKTIME, 0x4c000000 57.equ CLKDIVN, 0x4c000014 /*Clock divider control */ 58.equ GPHCON, 0x56000070 /*Port H control */ 59.equ GPHUP, 0x56000078 /*Pull-up control H */ 60.equ BWSCON, 0x48000000 /*Bus width & wait status */ 61.equ BANKCON0, 0x48000004 /*Boot ROM control */ 62.equ BANKCON1, 0x48000008 /*BANK1 control */ 63.equ BANKCON2, 0x4800000c /*BANK2 cControl */ 64.equ BANKCON3, 0x48000010 /*BANK3 control */ 65.equ BANKCON4, 0x48000014 /*BANK4 control */ 66.equ BANKCON5, 0x48000018 /*BANK5 control */ 67.equ BANKCON6, 0x4800001c /*BANK6 control */ 68.equ BANKCON7, 0x48000020 /*BANK7 control */ 69.equ REFRESH, 0x48000024 /*DRAM/SDRAM efresh */ 70.equ BANKSIZE, 0x48000028 /*Flexible Bank Size */ 71.equ MRSRB6, 0x4800002c /*Mode egister set for SDRAM*/ 72.equ MRSRB7, 0x48000030 /*Mode egister set for SDRAM*/ 73 74/* 75 ************************************************************************* 76 * 77 * Jump vector table 78 * 79 ************************************************************************* 80 */ 81 82.section .init, "ax" 83.code 32 84 85.globl _start 86_start: 87 b reset 88 ldr pc, _vector_undef 89 ldr pc, _vector_swi 90 ldr pc, _vector_pabt 91 ldr pc, _vector_dabt 92 ldr pc, _vector_resv 93 ldr pc, _vector_irq 94 ldr pc, _vector_fiq 95 96_vector_undef: .word vector_undef 97_vector_swi: .word vector_swi 98_vector_pabt: .word vector_pabt 99_vector_dabt: .word vector_dabt 100_vector_resv: .word vector_resv 101_vector_irq: .word vector_irq 102_vector_fiq: .word vector_fiq 103 104.balignl 16,0xdeadbeef 105 106/* 107 ************************************************************************* 108 * 109 * Startup Code (reset vector) 110 * relocate armboot to ram 111 * setup stack 112 * jump to second stage 113 * 114 ************************************************************************* 115 */ 116 117_TEXT_BASE: 118 .word TEXT_BASE 119 120/* 121 * rtthread kernel start and end 122 * which are defined in linker script 123 */ 124.globl _rtthread_start 125_rtthread_start: 126 .word _start 127 128.globl _rtthread_end 129_rtthread_end: 130 .word _end 131 132/* 133 * rtthread bss start and end which are defined in linker script 134 */ 135.globl _bss_start 136_bss_start: 137 .word __bss_start 138 139.globl _bss_end 140_bss_end: 141 .word __bss_end 142 143/* IRQ stack memory (calculated at run-time) */ 144.globl IRQ_STACK_START 145IRQ_STACK_START: 146 .word _irq_stack_start + 1024 147 148.globl FIQ_STACK_START 149FIQ_STACK_START: 150 .word _fiq_stack_start + 1024 151 152.globl UNDEFINED_STACK_START 153UNDEFINED_STACK_START: 154 .word _undefined_stack_start + CONFIG_STACKSIZE 155 156.globl ABORT_STACK_START 157ABORT_STACK_START: 158 .word _abort_stack_start + CONFIG_STACKSIZE 159 160.globl _STACK_START 161_STACK_START: 162 .word _svc_stack_start + 4096 163 164/* ----------------------------------entry------------------------------*/ 165reset: 166 167 /* set the cpu to SVC32 mode */ 168 mrs r0,cpsr 169 bic r0,r0,#MODEMASK 170 orr r0,r0,#SVCMODE 171 msr cpsr,r0 172 173 /* watch dog disable */ 174 ldr r0,=WTCON 175 ldr r1,=0x0 176 str r1,[r0] 177 178 /* mask all IRQs by clearing all bits in the INTMRs */ 179 ldr r1, =INTMSK 180 ldr r0, =0xffffffff 181 str r0, [r1] 182 ldr r1, =INTSUBMSK 183 ldr r0, =0x7fff /*all sub interrupt disable */ 184 str r0, [r1] 185 186 /* set interrupt vector */ 187 ldr r0, _load_address 188 mov r1, #0x0 /* target address */ 189 add r2, r0, #0x20 /* size, 32bytes */ 190 191copy_loop: 192 ldmia r0!, {r3-r10} /* copy from source address [r0] */ 193 stmia r1!, {r3-r10} /* copy to target address [r1] */ 194 cmp r0, r2 /* until source end addreee [r2] */ 195 ble copy_loop 196 197 /* setup stack */ 198 bl stack_setup 199 200 /* clear .bss */ 201 mov r0,#0 /* get a zero */ 202 ldr r1,=__bss_start /* bss start */ 203 ldr r2,=__bss_end /* bss end */ 204 205bss_loop: 206 cmp r1,r2 /* check if data to clear */ 207 strlo r0,[r1],#4 /* clear 4 bytes */ 208 blo bss_loop /* loop until done */ 209 210 /* call C++ constructors of global objects */ 211 ldr r0, =__ctors_start__ 212 ldr r1, =__ctors_end__ 213 214ctor_loop: 215 cmp r0, r1 216 beq ctor_end 217 ldr r2, [r0], #4 218 stmfd sp!, {r0-r1} 219 mov lr, pc 220 bx r2 221 ldmfd sp!, {r0-r1} 222 b ctor_loop 223 224ctor_end: 225 226 /* start RT-Thread Kernel */ 227 ldr pc, _rtthread_startup 228 229_rtthread_startup: 230 .word rtthread_startup 231#if defined (__FLASH_BUILD__) 232_load_address: 233 .word ROM_BASE + _TEXT_BASE 234#else 235_load_address: 236 .word RAM_BASE + _TEXT_BASE 237#endif 238 239/* 240 ************************************************************************* 241 * 242 * Interrupt handling 243 * 244 ************************************************************************* 245 */ 246 247/* exception handlers */ 248 .align 5 249vector_undef: 250 sub sp, sp, #S_FRAME_SIZE 251 stmia sp, {r0 - r12} /* Calling r0-r12 */ 252 add r8, sp, #S_PC 253 stmdb r8, {sp, lr}^ /* Calling SP, LR */ 254 str lr, [r8, #0] /* Save calling PC */ 255 mrs r6, spsr 256 str r6, [r8, #4] /* Save CPSR */ 257 str r0, [r8, #8] /* Save OLD_R0 */ 258 mov r0, sp 259 260 bl rt_hw_trap_udef 261 262 .align 5 263vector_swi: 264 bl rt_hw_trap_swi 265 266 .align 5 267vector_pabt: 268 bl rt_hw_trap_pabt 269 270 .align 5 271vector_dabt: 272 sub sp, sp, #S_FRAME_SIZE 273 stmia sp, {r0 - r12} /* Calling r0-r12 */ 274 add r8, sp, #S_PC 275 stmdb r8, {sp, lr}^ /* Calling SP, LR */ 276 str lr, [r8, #0] /* Save calling PC */ 277 mrs r6, spsr 278 str r6, [r8, #4] /* Save CPSR */ 279 str r0, [r8, #8] /* Save OLD_R0 */ 280 mov r0, sp 281 282 bl rt_hw_trap_dabt 283 284 .align 5 285vector_resv: 286 bl rt_hw_trap_resv 287 288.globl rt_interrupt_enter 289.globl rt_interrupt_leave 290.globl rt_thread_switch_interrupt_flag 291.globl rt_interrupt_from_thread 292.globl rt_interrupt_to_thread 293vector_irq: 294 stmfd sp!, {r0-r12,lr} 295 bl rt_interrupt_enter 296 bl rt_hw_trap_irq 297 bl rt_interrupt_leave 298 299 /* if rt_thread_switch_interrupt_flag set, jump to _interrupt_thread_switch and don't return */ 300 ldr r0, =rt_thread_switch_interrupt_flag 301 ldr r1, [r0] 302 cmp r1, #1 303 beq _interrupt_thread_switch 304 305 ldmfd sp!, {r0-r12,lr} 306 subs pc, lr, #4 307 308 .align 5 309vector_fiq: 310 stmfd sp!,{r0-r7,lr} 311 bl rt_hw_trap_fiq 312 ldmfd sp!,{r0-r7,lr} 313 subs pc,lr,#4 314 315_interrupt_thread_switch: 316 mov r1, #0 /* clear rt_thread_switch_interrupt_flag*/ 317 str r1, [r0] 318 319 ldmfd sp!, {r0-r12,lr} /* reload saved registers */ 320 stmfd sp!, {r0-r3} /* save r0-r3 */ 321 mov r1, sp 322 add sp, sp, #16 /* restore sp */ 323 sub r2, lr, #4 /* save old task's pc to r2 */ 324 325 mrs r3, spsr /* disable interrupt */ 326 orr r0, r3, #NOINT 327 msr spsr_c, r0 328 329 ldr r0, =.+8 /* switch to interrupted task's stack*/ 330 movs pc, r0 331 332 stmfd sp!, {r2} /* push old task's pc */ 333 stmfd sp!, {r4-r12,lr} /* push old task's lr,r12-r4 */ 334 mov r4, r1 /* Special optimised code below */ 335 mov r5, r3 336 ldmfd r4!, {r0-r3} 337 stmfd sp!, {r0-r3} /* push old task's r3-r0 */ 338 stmfd sp!, {r5} /* push old task's psr */ 339 mrs r4, spsr 340 stmfd sp!, {r4} /* push old task's spsr */ 341 342 ldr r4, =rt_interrupt_from_thread 343 ldr r5, [r4] 344 str sp, [r5] /* store sp in preempted tasks's TCB*/ 345 346 ldr r6, =rt_interrupt_to_thread 347 ldr r6, [r6] 348 ldr sp, [r6] /* get new task's stack pointer */ 349 350 ldmfd sp!, {r4} /* pop new task's spsr */ 351 msr SPSR_cxsf, r4 352 ldmfd sp!, {r4} /* pop new task's psr */ 353 msr CPSR_cxsf, r4 354 355 ldmfd sp!, {r0-r12,lr,pc} /* pop new task's r0-r12,lr & pc */ 356 357stack_setup: 358 mrs r0, cpsr 359 bic r0, r0, #MODEMASK 360 orr r1, r0, #UNDEFMODE|NOINT 361 msr cpsr_cxsf, r1 /* undef mode */ 362 ldr sp, UNDEFINED_STACK_START 363 364 orr r1,r0,#ABORTMODE|NOINT 365 msr cpsr_cxsf,r1 /* abort mode */ 366 ldr sp, ABORT_STACK_START 367 368 orr r1,r0,#IRQMODE|NOINT 369 msr cpsr_cxsf,r1 /* IRQ mode */ 370 ldr sp, IRQ_STACK_START 371 372 orr r1,r0,#FIQMODE|NOINT 373 msr cpsr_cxsf,r1 /* FIQ mode */ 374 ldr sp, FIQ_STACK_START 375 376 bic r0,r0,#MODEMASK 377 orr r1,r0,#SVCMODE|NOINT 378 msr cpsr_cxsf,r1 /* SVC mode */ 379 380 ldr sp, _STACK_START 381 382 /* USER mode is not initialized. */ 383 mov pc,lr /* The LR register may be not valid for the mode changes.*/ 384 385/*/*}*/ 386 387