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