rt-thread-official/libcpu/unicore32/sep6200/start_gcc.S

364 lines
8.0 KiB
ArmAsm

/*
* 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*/
/*/*}*/