/* * File : start.S * This file is part of RT-Thread RTOS * COPYRIGHT (C) 2006 - 2013, RT-Thread Development Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Change Logs: * Date Author Notes * 2013-07-13 Peng Fan First implementation */ #define CONFIG_STACKSIZE 1024 #define S_FRAME_SIZE 132 #define S_OLD_R0 132 #define S_PSR 128 #define S_PC 124 #define S_LR 120 #define S_SP 116 #define S_IP 112 #define S_FP 108 #define S_R26 104 #define S_R25 100 #define S_R24 96 #define S_R23 92 #define S_R22 88 #define S_R21 84 #define S_R20 80 #define S_R19 76 #define S_R18 72 #define S_R17 68 #define S_R16 64 #define S_R15 60 #define S_R14 56 #define S_R13 52 #define S_R12 48 #define S_R11 44 #define S_R10 40 #define S_R9 36 #define S_R8 32 #define S_R7 28 #define S_R6 24 #define S_R5 20 #define S_R4 16 #define S_R3 12 #define S_R2 8 #define S_R1 4 #define S_R0 0 .equ USERMODE, 0x10 .equ REALMODE, 0x11 .equ IRQMODE, 0x12 .equ PRIVMODE, 0x13 .equ TRAPMODE, 0x17 .equ EXTNMODE, 0x1b .equ MODEMASK, 0x1f .equ NOINT, 0xc0 /* ************************************************************************* * * Jump vector table * ************************************************************************* */ .section .init, "ax" .code 32 .globl _start _start: b reset ldw pc, _extend_handle ldw pc, _swi_handle ldw pc, _iabort_handle ldw pc, _dabort_handle ldw pc, _reserve_handle ldw pc, _IRQ_handle ldw pc, _FIQ_handle _extend_handle: .word extend_handle _swi_handle: .word swi_handle _iabort_handle: .word iabort_handle _dabort_handle: .word dabort_handle _reserve_handle: .word reserve_handle _IRQ_handle: .word IRQ_handle _FIQ_handle: .word FIQ_handle .balignl 16,0xdeadbeef /* ************************************************************************* * * Startup Code (reset vector) * relocate armboot to ram * setup stack * jump to second stage * ************************************************************************* */ .global _TEXT_BASE _TEXT_BASE: .word TEXT_BASE .globl _rtthread_start _rtthread_start: .word _start .globl _rtthread_end _rtthread_end: .word _end .globl _bss_start _bss_start: .word __bss_start @ load end address .globl _bss_end _bss_end: .word __bss_end .globl IRQ_STACK_START IRQ_STACK_START: .word _irq_stack_start + 1024 .globl FIQ_STACK_START FIQ_STACK_START: .word _fiq_stack_start +1024 .globl UNDEFINED_STACK_START UNDEFINED_STACK_START: .word _undefined_stack_start + CONFIG_STACKSIZE .globl ABORT_STACK_START ABORT_STACK_START: .word _abort_stack_start + CONFIG_STACKSIZE .globl _STACK_START _STACK_START: .word _priv_stack_start + 4096 .equ SEP6200_VIC_BASE, 0xb0000000 .equ SEP6200_SYSCTL_BASE, 0xb0008000 /* ----------------------------------entry------------------------------*/ reset: /* set the cpu to PRIV mode and disable cpu interrupt */ mov r0, asr andn r0, r0, #0xff or r0, r0, #PRIVMODE|NOINT mov.a asr, r0 /* mask all IRQs by clearing all bits in the INTMRs */ ldw r1, =SEP6200_VIC_BASE ldw r0, =0xffffffff stw r0, [r1+], #0x20 /*interrupt enable clear*/ stw r0, [r1+], #0x24 /*remap ddr to 0x00000000 address*/ ldw r1, =SEP6200_SYSCTL_BASE ldw r0, [r1+] ldw r2, =0x80000000 or r0, r0, r2 stw r2, [r1+] /* set interrupt vector */ /*do nothing here for vector*/ /* setup stack */ b.l stack_setup /* copy the vector code to address 0 */ ldw r12, =0x100 ldw r0, = 0x40000000 ldw r1, = 0x00000000 copy_vetor: ldw r2, [r0] stw r2, [r1] add r0, r0, #4 add r1, r1, #4 sub r12, r12, #4 cmpsub.a r12, #0 bne copy_vetor /* clear .bss */ ldw r0, _bss_start /* bss start */ ldw r1, _bss_end /* bss end */ mov r2,#0 /* get a zero */ bss_loop: stw r2, [r0] @ clear loop... add r0, r0, #4 cmpsub.a r0, r1 bel bss_loop /* call C++ constructors of global objects */ ldw r0, =__ctors_start__ ldw r1, =__ctors_end__ ctor_loop: cmpsub.a r0, r1 beq ctor_end ldw.w r2, [r0]+, #4 stm.w (r0, r1), [sp-] add lr, pc, #4 mov pc, r2 ldm.w (r0, r1), [sp]+ b ctor_loop ctor_end: /*enable interrupt*/ mov r0, asr andn r1, r0, #NOINT mov.a asr, r1 /* start RT-Thread Kernel */ ldw pc, _rtthread_startup _rtthread_startup: .word rtthread_startup /* ************************************************************************* * * Interrupt handling * ************************************************************************* */ /* exception handlers */ /*Just simple implementation here */ .align 5 extend_handle: b rt_hw_trap_extn swi_handle: b rt_hw_trap_swi iabort_handle: b rt_hw_trap_pabt dabort_handle: b rt_hw_trap_dabt reserve_handle: b rt_hw_trap_resv .globl rt_interrupt_enter .globl rt_interrupt_leave .globl rt_thread_switch_interrupt_flag .globl rt_interrupt_from_thread .globl rt_interrupt_to_thread IRQ_handle: stm.w (lr), [sp-] stm.w (r16 - r28), [sp-] stm.w (r0 - r15), [sp-] b.l rt_interrupt_enter b.l rt_hw_trap_irq b.l rt_interrupt_leave /* if rt_thread_switch_interrupt_flag set, jump to _interrupt_thread_switch and don't return */ ldw r0, =rt_thread_switch_interrupt_flag ldw r1, [r0+] cmpsub.a r1, #1 beq _interrupt_thread_switch ldm.w (r0 - r15), [sp]+ ldm.w (r16 - r28), [sp]+ ldm.w (lr), [sp]+ mov.a pc, lr .align 5 FIQ_handle: b rt_hw_trap_fiq _interrupt_thread_switch: mov r1, #0 /* clear rt_thread_switch_interrupt_flag*/ stw r1, [r0+] /*reload register*/ ldm.w (r0 - r15), [sp]+ ldm.w (r16 - r28), [sp]+ ldm.w (lr), [sp]+ stm.w (r0 - r3), [sp-] /*save r0-r3*/ mov r1, sp add sp, sp, #16 /* restore sp */ mov r2, lr /* save old task's pc to r2 */ mov r3, bsr mov r0, #0xd3 /*I:F:0:PRIV*/ mov.a asr, r0 stm.w (r2), [sp-] /* push old task's pc */ /* push old task's registers */ stm.w (lr), [sp-] stm.w (r16 - r28), [sp-] stm.w (r4 - r15), [sp-] mov r4, r1 /* Special optimised code below */ mov r5, r3 ldm.w (r0 - r3), [r4]+ stm.w (r0 - r3), [sp-] /*push old task's r3-r0*/ stm.w (r5), [sp-] /* push old task's asr */ mov r4, bsr stm.w (r4), [sp-] /* push old task's bsr*/ ldw r4, =rt_interrupt_from_thread ldw r5, [r4+] stw sp, [r5+] /* store sp in preempted tasks's TCB*/ ldw r6, =rt_interrupt_to_thread ldw r6, [r6+] ldw sp, [r6+] /* get new task's stack pointer */ ldm.w (r4), [sp]+ /* pop new task's spsr */ mov.a bsr, r4 ldm.w (r4), [sp]+ /* pop new task's psr */ mov.a asr, r4 /* pop new task's r0-r28,lr & pc */ ldm.w (r0 - r15), [sp]+ ldm.w (r16 - r28), [sp]+ ldm.w (lr), [sp]+ ldm.w (pc), [sp]+ stack_setup: /*irq*/ mov ip, lr mov r0, asr andn r0, r0, #0x1f or r0, r0, #IRQMODE|NOINT mov.a asr, r0 /*IRQMODE*/ ldw r0, =IRQ_STACK_START ldw sp, [r0+] /*ldw sp, IRQ_STACK_START*/ /*priv*/ mov r0, asr andn r0, r0, #0x1f or r0, r0, #PRIVMODE|NOINT mov.a asr, r0 /*PRIVMODE*/ ldw r0, =_STACK_START ldw sp, [r0+] /*ldw sp, _STACK_START*/ mov lr, ip /*fiq and other mode is not implemented in code here*/ mov pc, lr /*lr may not be valid for the mode changes*/ /*/*}*/