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Äê9ÔÂ7ÈÕ     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
 | 
						|
 | 
						|
;/*********************************************************************************************************
 | 
						|
;  Èë¿Ú
 | 
						|
;*********************************************************************************************************/
 | 
						|
	.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
 | 
						|
 | 
						|
 | 
						|
;/*********************************************************************************************************
 | 
						|
;  Òì³£ÏòÁ¿±í
 | 
						|
;*********************************************************************************************************/
 | 
						|
    /* 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)
 |