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) |