1*10465441SEvalZero/* 2*10465441SEvalZero * File : start.S 3*10465441SEvalZero * This file is part of RT-Thread RTOS 4*10465441SEvalZero * COPYRIGHT (C) 2006 - 2013, RT-Thread Development Team 5*10465441SEvalZero * 6*10465441SEvalZero * This program is free software; you can redistribute it and/or modify 7*10465441SEvalZero * it under the terms of the GNU General Public License as published by 8*10465441SEvalZero * the Free Software Foundation; either version 2 of the License, or 9*10465441SEvalZero * (at your option) any later version. 10*10465441SEvalZero * 11*10465441SEvalZero * This program is distributed in the hope that it will be useful, 12*10465441SEvalZero * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*10465441SEvalZero * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*10465441SEvalZero * GNU General Public License for more details. 15*10465441SEvalZero * 16*10465441SEvalZero * You should have received a copy of the GNU General Public License along 17*10465441SEvalZero * with this program; if not, write to the Free Software Foundation, Inc., 18*10465441SEvalZero * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19*10465441SEvalZero * 20*10465441SEvalZero * Change Logs: 21*10465441SEvalZero * Date Author Notes 22*10465441SEvalZero * 2013-07-13 Peng Fan First implementation 23*10465441SEvalZero */ 24*10465441SEvalZero 25*10465441SEvalZero 26*10465441SEvalZero#define CONFIG_STACKSIZE 1024 27*10465441SEvalZero#define S_FRAME_SIZE 132 28*10465441SEvalZero 29*10465441SEvalZero#define S_OLD_R0 132 30*10465441SEvalZero#define S_PSR 128 31*10465441SEvalZero#define S_PC 124 32*10465441SEvalZero#define S_LR 120 33*10465441SEvalZero#define S_SP 116 34*10465441SEvalZero 35*10465441SEvalZero#define S_IP 112 36*10465441SEvalZero#define S_FP 108 37*10465441SEvalZero#define S_R26 104 38*10465441SEvalZero#define S_R25 100 39*10465441SEvalZero#define S_R24 96 40*10465441SEvalZero#define S_R23 92 41*10465441SEvalZero#define S_R22 88 42*10465441SEvalZero#define S_R21 84 43*10465441SEvalZero#define S_R20 80 44*10465441SEvalZero#define S_R19 76 45*10465441SEvalZero#define S_R18 72 46*10465441SEvalZero#define S_R17 68 47*10465441SEvalZero#define S_R16 64 48*10465441SEvalZero#define S_R15 60 49*10465441SEvalZero#define S_R14 56 50*10465441SEvalZero#define S_R13 52 51*10465441SEvalZero#define S_R12 48 52*10465441SEvalZero#define S_R11 44 53*10465441SEvalZero#define S_R10 40 54*10465441SEvalZero#define S_R9 36 55*10465441SEvalZero#define S_R8 32 56*10465441SEvalZero#define S_R7 28 57*10465441SEvalZero#define S_R6 24 58*10465441SEvalZero#define S_R5 20 59*10465441SEvalZero#define S_R4 16 60*10465441SEvalZero#define S_R3 12 61*10465441SEvalZero#define S_R2 8 62*10465441SEvalZero#define S_R1 4 63*10465441SEvalZero#define S_R0 0 64*10465441SEvalZero 65*10465441SEvalZero.equ USERMODE, 0x10 66*10465441SEvalZero.equ REALMODE, 0x11 67*10465441SEvalZero.equ IRQMODE, 0x12 68*10465441SEvalZero.equ PRIVMODE, 0x13 69*10465441SEvalZero.equ TRAPMODE, 0x17 70*10465441SEvalZero.equ EXTNMODE, 0x1b 71*10465441SEvalZero.equ MODEMASK, 0x1f 72*10465441SEvalZero.equ NOINT, 0xc0 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.globl _start 85*10465441SEvalZero_start: 86*10465441SEvalZero b reset 87*10465441SEvalZero ldw pc, _extend_handle 88*10465441SEvalZero ldw pc, _swi_handle 89*10465441SEvalZero ldw pc, _iabort_handle 90*10465441SEvalZero ldw pc, _dabort_handle 91*10465441SEvalZero ldw pc, _reserve_handle 92*10465441SEvalZero ldw pc, _IRQ_handle 93*10465441SEvalZero ldw pc, _FIQ_handle 94*10465441SEvalZero 95*10465441SEvalZero_extend_handle: .word extend_handle 96*10465441SEvalZero_swi_handle: .word swi_handle 97*10465441SEvalZero_iabort_handle: .word iabort_handle 98*10465441SEvalZero_dabort_handle: .word dabort_handle 99*10465441SEvalZero_reserve_handle: .word reserve_handle 100*10465441SEvalZero_IRQ_handle: .word IRQ_handle 101*10465441SEvalZero_FIQ_handle: .word FIQ_handle 102*10465441SEvalZero .balignl 16,0xdeadbeef 103*10465441SEvalZero 104*10465441SEvalZero/* 105*10465441SEvalZero ************************************************************************* 106*10465441SEvalZero * 107*10465441SEvalZero * Startup Code (reset vector) 108*10465441SEvalZero * relocate armboot to ram 109*10465441SEvalZero * setup stack 110*10465441SEvalZero * jump to second stage 111*10465441SEvalZero * 112*10465441SEvalZero ************************************************************************* 113*10465441SEvalZero */ 114*10465441SEvalZero.global _TEXT_BASE 115*10465441SEvalZero_TEXT_BASE: 116*10465441SEvalZero .word TEXT_BASE 117*10465441SEvalZero 118*10465441SEvalZero.globl _rtthread_start 119*10465441SEvalZero_rtthread_start: 120*10465441SEvalZero .word _start 121*10465441SEvalZero 122*10465441SEvalZero.globl _rtthread_end 123*10465441SEvalZero_rtthread_end: 124*10465441SEvalZero .word _end 125*10465441SEvalZero 126*10465441SEvalZero.globl _bss_start 127*10465441SEvalZero_bss_start: 128*10465441SEvalZero .word __bss_start @ load end address 129*10465441SEvalZero 130*10465441SEvalZero.globl _bss_end 131*10465441SEvalZero_bss_end: 132*10465441SEvalZero .word __bss_end 133*10465441SEvalZero 134*10465441SEvalZero.globl IRQ_STACK_START 135*10465441SEvalZeroIRQ_STACK_START: 136*10465441SEvalZero .word _irq_stack_start + 1024 137*10465441SEvalZero 138*10465441SEvalZero.globl FIQ_STACK_START 139*10465441SEvalZeroFIQ_STACK_START: 140*10465441SEvalZero .word _fiq_stack_start +1024 141*10465441SEvalZero 142*10465441SEvalZero.globl UNDEFINED_STACK_START 143*10465441SEvalZeroUNDEFINED_STACK_START: 144*10465441SEvalZero .word _undefined_stack_start + CONFIG_STACKSIZE 145*10465441SEvalZero 146*10465441SEvalZero.globl ABORT_STACK_START 147*10465441SEvalZeroABORT_STACK_START: 148*10465441SEvalZero .word _abort_stack_start + CONFIG_STACKSIZE 149*10465441SEvalZero 150*10465441SEvalZero.globl _STACK_START 151*10465441SEvalZero_STACK_START: 152*10465441SEvalZero .word _priv_stack_start + 4096 153*10465441SEvalZero 154*10465441SEvalZero.equ SEP6200_VIC_BASE, 0xb0000000 155*10465441SEvalZero.equ SEP6200_SYSCTL_BASE, 0xb0008000 156*10465441SEvalZero/* ----------------------------------entry------------------------------*/ 157*10465441SEvalZeroreset: 158*10465441SEvalZero /* set the cpu to PRIV mode and disable cpu interrupt */ 159*10465441SEvalZero mov r0, asr 160*10465441SEvalZero andn r0, r0, #0xff 161*10465441SEvalZero or r0, r0, #PRIVMODE|NOINT 162*10465441SEvalZero mov.a asr, r0 163*10465441SEvalZero 164*10465441SEvalZero /* mask all IRQs by clearing all bits in the INTMRs */ 165*10465441SEvalZero ldw r1, =SEP6200_VIC_BASE 166*10465441SEvalZero ldw r0, =0xffffffff 167*10465441SEvalZero stw r0, [r1+], #0x20 /*interrupt enable clear*/ 168*10465441SEvalZero stw r0, [r1+], #0x24 169*10465441SEvalZero 170*10465441SEvalZero 171*10465441SEvalZero /*remap ddr to 0x00000000 address*/ 172*10465441SEvalZero ldw r1, =SEP6200_SYSCTL_BASE 173*10465441SEvalZero ldw r0, [r1+] 174*10465441SEvalZero ldw r2, =0x80000000 175*10465441SEvalZero or r0, r0, r2 176*10465441SEvalZero stw r2, [r1+] 177*10465441SEvalZero 178*10465441SEvalZero /* set interrupt vector */ 179*10465441SEvalZero /*do nothing here for vector*/ 180*10465441SEvalZero 181*10465441SEvalZero /* setup stack */ 182*10465441SEvalZero b.l stack_setup 183*10465441SEvalZero 184*10465441SEvalZero /* copy the vector code to address 0 */ 185*10465441SEvalZero ldw r12, =0x100 186*10465441SEvalZero ldw r0, = 0x40000000 187*10465441SEvalZero ldw r1, = 0x00000000 188*10465441SEvalZerocopy_vetor: 189*10465441SEvalZero ldw r2, [r0] 190*10465441SEvalZero stw r2, [r1] 191*10465441SEvalZero add r0, r0, #4 192*10465441SEvalZero add r1, r1, #4 193*10465441SEvalZero sub r12, r12, #4 194*10465441SEvalZero cmpsub.a r12, #0 195*10465441SEvalZero bne copy_vetor 196*10465441SEvalZero 197*10465441SEvalZero /* clear .bss */ 198*10465441SEvalZero ldw r0, _bss_start /* bss start */ 199*10465441SEvalZero ldw r1, _bss_end /* bss end */ 200*10465441SEvalZero mov r2,#0 /* get a zero */ 201*10465441SEvalZero 202*10465441SEvalZero 203*10465441SEvalZerobss_loop: 204*10465441SEvalZero stw r2, [r0] @ clear loop... 205*10465441SEvalZero add r0, r0, #4 206*10465441SEvalZero cmpsub.a r0, r1 207*10465441SEvalZero bel bss_loop 208*10465441SEvalZero 209*10465441SEvalZero /* call C++ constructors of global objects */ 210*10465441SEvalZero ldw r0, =__ctors_start__ 211*10465441SEvalZero ldw r1, =__ctors_end__ 212*10465441SEvalZero 213*10465441SEvalZeroctor_loop: 214*10465441SEvalZero cmpsub.a r0, r1 215*10465441SEvalZero beq ctor_end 216*10465441SEvalZero ldw.w r2, [r0]+, #4 217*10465441SEvalZero stm.w (r0, r1), [sp-] 218*10465441SEvalZero add lr, pc, #4 219*10465441SEvalZero mov pc, r2 220*10465441SEvalZero ldm.w (r0, r1), [sp]+ 221*10465441SEvalZero b ctor_loop 222*10465441SEvalZeroctor_end: 223*10465441SEvalZero 224*10465441SEvalZero /*enable interrupt*/ 225*10465441SEvalZero mov r0, asr 226*10465441SEvalZero andn r1, r0, #NOINT 227*10465441SEvalZero mov.a asr, r1 228*10465441SEvalZero 229*10465441SEvalZero /* start RT-Thread Kernel */ 230*10465441SEvalZero ldw pc, _rtthread_startup 231*10465441SEvalZero 232*10465441SEvalZero_rtthread_startup: 233*10465441SEvalZero .word rtthread_startup 234*10465441SEvalZero 235*10465441SEvalZero/* 236*10465441SEvalZero ************************************************************************* 237*10465441SEvalZero * 238*10465441SEvalZero * Interrupt handling 239*10465441SEvalZero * 240*10465441SEvalZero ************************************************************************* 241*10465441SEvalZero */ 242*10465441SEvalZero 243*10465441SEvalZero/* exception handlers */ 244*10465441SEvalZero/*Just simple implementation here */ 245*10465441SEvalZero .align 5 246*10465441SEvalZeroextend_handle: 247*10465441SEvalZero b rt_hw_trap_extn 248*10465441SEvalZeroswi_handle: 249*10465441SEvalZero b rt_hw_trap_swi 250*10465441SEvalZeroiabort_handle: 251*10465441SEvalZero b rt_hw_trap_pabt 252*10465441SEvalZerodabort_handle: 253*10465441SEvalZero b rt_hw_trap_dabt 254*10465441SEvalZeroreserve_handle: 255*10465441SEvalZero b rt_hw_trap_resv 256*10465441SEvalZero 257*10465441SEvalZero.globl rt_interrupt_enter 258*10465441SEvalZero.globl rt_interrupt_leave 259*10465441SEvalZero.globl rt_thread_switch_interrupt_flag 260*10465441SEvalZero.globl rt_interrupt_from_thread 261*10465441SEvalZero.globl rt_interrupt_to_thread 262*10465441SEvalZeroIRQ_handle: 263*10465441SEvalZero 264*10465441SEvalZero stm.w (lr), [sp-] 265*10465441SEvalZero stm.w (r16 - r28), [sp-] 266*10465441SEvalZero stm.w (r0 - r15), [sp-] 267*10465441SEvalZero 268*10465441SEvalZero b.l rt_interrupt_enter 269*10465441SEvalZero b.l rt_hw_trap_irq 270*10465441SEvalZero b.l rt_interrupt_leave 271*10465441SEvalZero 272*10465441SEvalZero /* if rt_thread_switch_interrupt_flag set, jump to _interrupt_thread_switch and don't return */ 273*10465441SEvalZero ldw r0, =rt_thread_switch_interrupt_flag 274*10465441SEvalZero ldw r1, [r0+] 275*10465441SEvalZero cmpsub.a r1, #1 276*10465441SEvalZero beq _interrupt_thread_switch 277*10465441SEvalZero 278*10465441SEvalZero ldm.w (r0 - r15), [sp]+ 279*10465441SEvalZero ldm.w (r16 - r28), [sp]+ 280*10465441SEvalZero ldm.w (lr), [sp]+ 281*10465441SEvalZero mov.a pc, lr 282*10465441SEvalZero 283*10465441SEvalZero .align 5 284*10465441SEvalZeroFIQ_handle: 285*10465441SEvalZero b rt_hw_trap_fiq 286*10465441SEvalZero 287*10465441SEvalZero_interrupt_thread_switch: 288*10465441SEvalZero 289*10465441SEvalZero mov r1, #0 /* clear rt_thread_switch_interrupt_flag*/ 290*10465441SEvalZero stw r1, [r0+] 291*10465441SEvalZero 292*10465441SEvalZero /*reload register*/ 293*10465441SEvalZero ldm.w (r0 - r15), [sp]+ 294*10465441SEvalZero ldm.w (r16 - r28), [sp]+ 295*10465441SEvalZero ldm.w (lr), [sp]+ 296*10465441SEvalZero 297*10465441SEvalZero stm.w (r0 - r3), [sp-] /*save r0-r3*/ 298*10465441SEvalZero 299*10465441SEvalZero mov r1, sp 300*10465441SEvalZero add sp, sp, #16 /* restore sp */ 301*10465441SEvalZero mov r2, lr /* save old task's pc to r2 */ 302*10465441SEvalZero 303*10465441SEvalZero mov r3, bsr 304*10465441SEvalZero mov r0, #0xd3 /*I:F:0:PRIV*/ 305*10465441SEvalZero mov.a asr, r0 306*10465441SEvalZero 307*10465441SEvalZero stm.w (r2), [sp-] /* push old task's pc */ 308*10465441SEvalZero 309*10465441SEvalZero /* push old task's registers */ 310*10465441SEvalZero stm.w (lr), [sp-] 311*10465441SEvalZero stm.w (r16 - r28), [sp-] 312*10465441SEvalZero stm.w (r4 - r15), [sp-] 313*10465441SEvalZero mov r4, r1 /* Special optimised code below */ 314*10465441SEvalZero mov r5, r3 315*10465441SEvalZero ldm.w (r0 - r3), [r4]+ 316*10465441SEvalZero stm.w (r0 - r3), [sp-] /*push old task's r3-r0*/ 317*10465441SEvalZero stm.w (r5), [sp-] /* push old task's asr */ 318*10465441SEvalZero mov r4, bsr 319*10465441SEvalZero stm.w (r4), [sp-] /* push old task's bsr*/ 320*10465441SEvalZero 321*10465441SEvalZero ldw r4, =rt_interrupt_from_thread 322*10465441SEvalZero ldw r5, [r4+] 323*10465441SEvalZero stw sp, [r5+] /* store sp in preempted tasks's TCB*/ 324*10465441SEvalZero 325*10465441SEvalZero ldw r6, =rt_interrupt_to_thread 326*10465441SEvalZero ldw r6, [r6+] 327*10465441SEvalZero ldw sp, [r6+] /* get new task's stack pointer */ 328*10465441SEvalZero 329*10465441SEvalZero ldm.w (r4), [sp]+ /* pop new task's spsr */ 330*10465441SEvalZero mov.a bsr, r4 331*10465441SEvalZero ldm.w (r4), [sp]+ /* pop new task's psr */ 332*10465441SEvalZero mov.a asr, r4 333*10465441SEvalZero 334*10465441SEvalZero /* pop new task's r0-r28,lr & pc */ 335*10465441SEvalZero 336*10465441SEvalZero ldm.w (r0 - r15), [sp]+ 337*10465441SEvalZero ldm.w (r16 - r28), [sp]+ 338*10465441SEvalZero ldm.w (lr), [sp]+ 339*10465441SEvalZero ldm.w (pc), [sp]+ 340*10465441SEvalZero 341*10465441SEvalZerostack_setup: 342*10465441SEvalZero /*irq*/ 343*10465441SEvalZero mov ip, lr 344*10465441SEvalZero mov r0, asr 345*10465441SEvalZero andn r0, r0, #0x1f 346*10465441SEvalZero or r0, r0, #IRQMODE|NOINT 347*10465441SEvalZero mov.a asr, r0 /*IRQMODE*/ 348*10465441SEvalZero ldw r0, =IRQ_STACK_START 349*10465441SEvalZero ldw sp, [r0+] 350*10465441SEvalZero /*ldw sp, IRQ_STACK_START*/ 351*10465441SEvalZero 352*10465441SEvalZero /*priv*/ 353*10465441SEvalZero mov r0, asr 354*10465441SEvalZero andn r0, r0, #0x1f 355*10465441SEvalZero or r0, r0, #PRIVMODE|NOINT 356*10465441SEvalZero mov.a asr, r0 /*PRIVMODE*/ 357*10465441SEvalZero ldw r0, =_STACK_START 358*10465441SEvalZero ldw sp, [r0+] 359*10465441SEvalZero /*ldw sp, _STACK_START*/ 360*10465441SEvalZero mov lr, ip 361*10465441SEvalZero /*fiq and other mode is not implemented in code here*/ 362*10465441SEvalZero mov pc, lr /*lr may not be valid for the mode changes*/ 363*10465441SEvalZero/*/*}*/ 364