329 lines
7.1 KiB
ArmAsm
329 lines
7.1 KiB
ArmAsm
|
/*
|
|||
|
* File : startup.S
|
|||
|
* This file is part of RT-Thread RTOS
|
|||
|
* COPYRIGHT (C) 2008 - 2012, 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
|
|||
|
* 2016<EFBFBD><EFBFBD>9<EFBFBD><EFBFBD>7<EFBFBD><EFBFBD> Urey the first version
|
|||
|
*/
|
|||
|
|
|||
|
#ifndef __ASSEMBLY__
|
|||
|
# define __ASSEMBLY__
|
|||
|
#endif
|
|||
|
|
|||
|
#include "../common/mips.h"
|
|||
|
|
|||
|
#define IRQ_STACK_SIZE 0x2000
|
|||
|
#define EXC_STACK_SIZE 0x2000
|
|||
|
|
|||
|
|
|||
|
.section ".bss"
|
|||
|
ALIGN(4)
|
|||
|
irq_stack_low:
|
|||
|
.space IRQ_STACK_SIZE
|
|||
|
irq_stack_top:
|
|||
|
.space 8
|
|||
|
|
|||
|
ALIGN(4)
|
|||
|
exc_stack_low:
|
|||
|
.space EXC_STACK_SIZE
|
|||
|
exc_stack_top:
|
|||
|
.space 8
|
|||
|
|
|||
|
#define SYSTEM_STACK 0x80003fe8
|
|||
|
|
|||
|
;/*********************************************************************************************************
|
|||
|
; <20><><EFBFBD><EFBFBD>
|
|||
|
;*********************************************************************************************************/
|
|||
|
.global rtthread_startup
|
|||
|
.global mips_vfp32_init
|
|||
|
|
|||
|
.global _start
|
|||
|
.section ".start", "ax"
|
|||
|
.set noreorder
|
|||
|
_start:
|
|||
|
.set noreorder
|
|||
|
la ra, _start
|
|||
|
|
|||
|
li t1, 0x00800000
|
|||
|
mtc0 t1, CP0_CAUSE
|
|||
|
|
|||
|
/* init cp0 registers. */
|
|||
|
li t0, 0x1000FC00 /* BEV = 0 and mask all interrupt */
|
|||
|
mtc0 t0, CP0_STATUS
|
|||
|
|
|||
|
#ifdef __mips_hard_float
|
|||
|
jal mips_vfp32_init
|
|||
|
nop
|
|||
|
#endif
|
|||
|
|
|||
|
/* setup stack pointer */
|
|||
|
li sp, SYSTEM_STACK
|
|||
|
la gp, _gp
|
|||
|
|
|||
|
_cache_init:
|
|||
|
/* init caches, assumes a 4way * 128set * 32byte I/D cache */
|
|||
|
mtc0 zero, CP0_TAGLO /* TAGLO reg */
|
|||
|
mtc0 zero, CP0_TAGHI /* TAGHI reg */
|
|||
|
li t0, 3 /* enable cache for kseg0 accesses */
|
|||
|
mtc0 t0, CP0_CONFIG /* CONFIG reg */
|
|||
|
la t0, 0x80000000 /* an idx op should use an unmappable address */
|
|||
|
ori t1, t0, 0x4000 /* 16kB cache */
|
|||
|
|
|||
|
_cache_loop:
|
|||
|
cache 0x8, 0(t0) /* index store icache tag */
|
|||
|
cache 0x9, 0(t0) /* index store dcache tag */
|
|||
|
bne t0, t1, _cache_loop
|
|||
|
addiu t0, t0, 0x20 /* 32 bytes per cache line */
|
|||
|
nop
|
|||
|
|
|||
|
/* invalidate BTB */
|
|||
|
mfc0 t0, CP0_CONFIG
|
|||
|
nop
|
|||
|
ori t0, 2
|
|||
|
mtc0 t0, CP0_CONFIG
|
|||
|
nop
|
|||
|
|
|||
|
|
|||
|
/* jump to RT-Thread RTOS */
|
|||
|
jal rtthread_startup
|
|||
|
nop
|
|||
|
|
|||
|
/* restart, never die */
|
|||
|
j _start
|
|||
|
nop
|
|||
|
.set reorder
|
|||
|
|
|||
|
|
|||
|
;/*********************************************************************************************************
|
|||
|
; <20>쳣<EFBFBD><ECB3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
;*********************************************************************************************************/
|
|||
|
/* 0x0 - TLB refill handler */
|
|||
|
.section .vectors.1, "ax", %progbits
|
|||
|
j mips_tlb_refill_entry
|
|||
|
nop
|
|||
|
|
|||
|
/* 0x100 - Cache error handler */
|
|||
|
.section .vectors.2, "ax", %progbits
|
|||
|
j mips_cache_error_entry
|
|||
|
nop
|
|||
|
|
|||
|
/* 0x180 - Exception/Interrupt handler */
|
|||
|
.section .vectors.3, "ax", %progbits
|
|||
|
j mips_exception_entry
|
|||
|
nop
|
|||
|
|
|||
|
/* 0x200 - Special Exception Interrupt handler (when IV is set in CP0_CAUSE) */
|
|||
|
.section .vectors.4, "ax", %progbits
|
|||
|
j mips_interrupt_entry
|
|||
|
nop
|
|||
|
.section .vectors, "ax", %progbits
|
|||
|
|
|||
|
.global mips_exception_handler
|
|||
|
// .global mips_syscall
|
|||
|
LEAF(mips_exception_entry)
|
|||
|
.set push
|
|||
|
.set noat
|
|||
|
.set noreorder
|
|||
|
.set volatile
|
|||
|
|
|||
|
mfc0 k0, C0_CAUSE
|
|||
|
andi k0, k0, 0x7c
|
|||
|
beq zero, k0, except_do_intr
|
|||
|
nop
|
|||
|
|
|||
|
andi k0,(0x08 << 2)
|
|||
|
beq zero,k0,except_do
|
|||
|
nop
|
|||
|
except_do_intr:
|
|||
|
la k0,mips_interrupt_entry
|
|||
|
jr k0
|
|||
|
nop
|
|||
|
except_do_syscall:
|
|||
|
// la k0,mips_syscall
|
|||
|
// jr k0
|
|||
|
nop
|
|||
|
except_do:
|
|||
|
//save sp
|
|||
|
move k0,sp
|
|||
|
//la sp, exc_stack_top
|
|||
|
subu sp, sp, CONTEXT_SIZE
|
|||
|
//save context
|
|||
|
sw $0, (4*0)(sp);
|
|||
|
sw $1, (4*1)(sp);
|
|||
|
sw $2, (4*2)(sp);
|
|||
|
sw $3, (4*3)(sp);
|
|||
|
sw $4, (4*4)(sp);
|
|||
|
sw $5, (4*5)(sp);
|
|||
|
sw $6, (4*6)(sp);
|
|||
|
sw $7, (4*7)(sp);
|
|||
|
sw $8, (4*8)(sp);
|
|||
|
sw $9, (4*9)(sp);
|
|||
|
sw $10, (4*10)(sp);
|
|||
|
sw $11, (4*11)(sp);
|
|||
|
sw $12, (4*12)(sp);
|
|||
|
sw $13, (4*13)(sp);
|
|||
|
sw $14, (4*14)(sp);
|
|||
|
sw $15, (4*15)(sp);
|
|||
|
sw $16, (4*16)(sp);
|
|||
|
sw $17, (4*17)(sp);
|
|||
|
sw $18, (4*18)(sp);
|
|||
|
sw $19, (4*19)(sp);
|
|||
|
sw $20, (4*20)(sp);
|
|||
|
sw $21, (4*21)(sp);
|
|||
|
sw $22, (4*22)(sp);
|
|||
|
sw $23, (4*23)(sp);
|
|||
|
sw $24, (4*24)(sp);
|
|||
|
sw $25, (4*25)(sp);
|
|||
|
sw $26, (4*26)(sp);
|
|||
|
sw $27, (4*27)(sp);
|
|||
|
sw $28, (4*28)(sp);
|
|||
|
sw k0, (4*29)(sp); //old sp
|
|||
|
sw $30, (4*30)(sp);
|
|||
|
sw $31, (4*31)(sp);
|
|||
|
|
|||
|
/* STATUS CAUSE EPC.... */
|
|||
|
mfc0 $2, CP0_STATUS
|
|||
|
sw $2, STK_OFFSET_SR(sp)
|
|||
|
|
|||
|
mfc0 $2, CP0_CAUSE
|
|||
|
sw $2, STK_OFFSET_CAUSE(sp)
|
|||
|
|
|||
|
mfc0 $2, CP0_BADVADDR
|
|||
|
sw $2, STK_OFFSET_BADVADDR(sp)
|
|||
|
|
|||
|
MFC0 $2, CP0_EPC
|
|||
|
sw $2, STK_OFFSET_EPC(sp)
|
|||
|
|
|||
|
mfhi $2
|
|||
|
sw $2, STK_OFFSET_HI(sp)
|
|||
|
|
|||
|
mflo $2
|
|||
|
sw $2, STK_OFFSET_LO(sp)
|
|||
|
|
|||
|
move a0, sp
|
|||
|
la k0, mips_exception_handler
|
|||
|
j k0
|
|||
|
nop
|
|||
|
|
|||
|
//
|
|||
|
|
|||
|
.set pop
|
|||
|
END(mips_exception_entry)
|
|||
|
|
|||
|
.global mips_tlb_refill_handler
|
|||
|
LEAF(mips_tlb_refill_entry)
|
|||
|
.set push
|
|||
|
.set noat
|
|||
|
.set noreorder
|
|||
|
.set volatile
|
|||
|
|
|||
|
la k0,mips_tlb_refill_handler
|
|||
|
jr k0
|
|||
|
|
|||
|
nop
|
|||
|
eret
|
|||
|
nop
|
|||
|
|
|||
|
.set pop
|
|||
|
END(mips_tlb_refill_entry)
|
|||
|
|
|||
|
.global mips_cache_error_handler
|
|||
|
LEAF(mips_cache_error_entry)
|
|||
|
.set push
|
|||
|
.set noat
|
|||
|
.set noreorder
|
|||
|
.set volatile
|
|||
|
|
|||
|
la k0,mips_cache_error_handler
|
|||
|
jr k0
|
|||
|
nop
|
|||
|
eret
|
|||
|
nop
|
|||
|
|
|||
|
.set pop
|
|||
|
END(mips_cache_error_entry)
|
|||
|
|
|||
|
|
|||
|
|
|||
|
.global rt_interrupt_dispatch
|
|||
|
.global rt_interrupt_enter
|
|||
|
.global rt_interrupt_leave
|
|||
|
LEAF(mips_interrupt_entry)
|
|||
|
.set push
|
|||
|
.set noat
|
|||
|
.set noreorder
|
|||
|
.set volatile
|
|||
|
|
|||
|
//mfc0 k0,CP0_EPC
|
|||
|
SAVE_CONTEXT
|
|||
|
|
|||
|
mfc0 t0, CP0_CAUSE
|
|||
|
mfc0 t1, CP0_STATUS
|
|||
|
and t0, t1
|
|||
|
|
|||
|
andi t0, 0xff00
|
|||
|
beqz t0, spurious_interrupt
|
|||
|
nop
|
|||
|
|
|||
|
/* let k0 keep the current context sp */
|
|||
|
move k0, sp
|
|||
|
|
|||
|
/* switch to kernel stack */
|
|||
|
la sp, irq_stack_top
|
|||
|
jal rt_interrupt_enter
|
|||
|
nop
|
|||
|
jal rt_interrupt_dispatch
|
|||
|
nop
|
|||
|
jal rt_interrupt_leave
|
|||
|
nop
|
|||
|
|
|||
|
/* switch sp back to thread's context */
|
|||
|
move sp, k0
|
|||
|
|
|||
|
/*
|
|||
|
* if rt_thread_switch_interrupt_flag set, jump to
|
|||
|
* rt_hw_context_switch_interrupt_do and don't return
|
|||
|
*/
|
|||
|
la k0, rt_thread_switch_interrupt_flag
|
|||
|
lw k1, 0(k0)
|
|||
|
beqz k1, spurious_interrupt
|
|||
|
nop
|
|||
|
sw zero, 0(k0) /* clear flag */
|
|||
|
nop
|
|||
|
|
|||
|
/*
|
|||
|
* switch to the new thread
|
|||
|
*/
|
|||
|
la k0, rt_interrupt_from_thread
|
|||
|
lw k1, 0(k0)
|
|||
|
nop
|
|||
|
sw sp, 0(k1) /* store sp in preempted tasks's TCB */
|
|||
|
|
|||
|
la k0, rt_interrupt_to_thread
|
|||
|
lw k1, 0(k0)
|
|||
|
nop
|
|||
|
lw sp, 0(k1) /* get new task's stack pointer */
|
|||
|
j spurious_interrupt
|
|||
|
nop
|
|||
|
spurious_interrupt:
|
|||
|
RESTORE_CONTEXT
|
|||
|
|
|||
|
.set pop
|
|||
|
END(mips_interrupt_entry)
|