302 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
		
		
			
		
	
	
			302 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
|   | ;/*
 | |||
|  | ; * Copyright (c) 2006-2018, RT-Thread Development Team
 | |||
|  | ; *
 | |||
|  | ; * SPDX-License-Identifier: Apache-2.0
 | |||
|  | ; *
 | |||
|  | ; * Change Logs:
 | |||
|  | ; * Date           Author       Notes
 | |||
|  | ; * 2011-08-14     weety      first version
 | |||
|  | ; * 2015-04-15     ArdaFu     Split from AT91SAM9260 BSP
 | |||
|  | ; * 2015-04-21     ArdaFu     Remove remap code. Using mmu to map vector table
 | |||
|  | ; * 2015-06-04     aozima     Align stack address to 8 byte.
 | |||
|  | ; */
 | |||
|  | 
 | |||
|  | UND_STK_SIZE EQU 512 | |||
|  | SVC_STK_SIZE EQU 4096 | |||
|  | ABT_STK_SIZE EQU 512 | |||
|  | IRQ_STK_SIZE EQU 1024 | |||
|  | FIQ_STK_SIZE EQU 1024 | |||
|  | SYS_STK_SIZE EQU 512 | |||
|  | Heap_Size    EQU 512 | |||
|  | 
 | |||
|  | S_FRAME_SIZE    EQU     (18*4)   ;72
 | |||
|  | S_PC            EQU     (15*4)   ;R15
 | |||
|  | 
 | |||
|  | MODE_USR        EQU     0X10 | |||
|  | MODE_FIQ        EQU     0X11 | |||
|  | MODE_IRQ        EQU     0X12 | |||
|  | MODE_SVC        EQU     0X13 | |||
|  | MODE_ABT        EQU     0X17 | |||
|  | MODE_UND        EQU     0X1B | |||
|  | MODE_SYS        EQU     0X1F | |||
|  | MODEMASK        EQU     0X1F | |||
|  | 
 | |||
|  | NOINT           EQU     0xC0 | |||
|  |      | |||
|  | ;----------------------- Stack and Heap Definitions ----------------------------
 | |||
|  |     AREA    STACK, NOINIT, READWRITE, ALIGN=3 | |||
|  | Stack_Mem | |||
|  | 
 | |||
|  |     SPACE   UND_STK_SIZE | |||
|  |     EXPORT UND_STACK_START | |||
|  | UND_STACK_START | |||
|  | 
 | |||
|  |     ALIGN 8 | |||
|  |     SPACE   ABT_STK_SIZE | |||
|  |     EXPORT ABT_STACK_START | |||
|  | ABT_STACK_START | |||
|  | 
 | |||
|  |     ALIGN 8 | |||
|  |     SPACE   FIQ_STK_SIZE | |||
|  |     EXPORT FIQ_STACK_START | |||
|  | FIQ_STACK_START | |||
|  | 
 | |||
|  |     ALIGN 8 | |||
|  |     SPACE   IRQ_STK_SIZE | |||
|  |     EXPORT IRQ_STACK_START | |||
|  | IRQ_STACK_START | |||
|  | 
 | |||
|  |     ALIGN 8 | |||
|  |     SPACE   SYS_STK_SIZE | |||
|  |     EXPORT SYS_STACK_START | |||
|  | SYS_STACK_START | |||
|  | 
 | |||
|  |     ALIGN 8 | |||
|  |     SPACE   SVC_STK_SIZE | |||
|  |     EXPORT SVC_STACK_START | |||
|  | SVC_STACK_START | |||
|  | Stack_Top | |||
|  | __initial_sp | |||
|  | 
 | |||
|  | __heap_base | |||
|  | Heap_Mem        SPACE   Heap_Size | |||
|  | __heap_limit | |||
|  | 
 | |||
|  |     PRESERVE8 | |||
|  | ;--------------Jump vector table------------------------------------------------
 | |||
|  |     EXPORT Entry_Point | |||
|  |     AREA    RESET, CODE, READONLY | |||
|  |     ARM | |||
|  | Entry_Point | |||
|  |     LDR     PC, vector_reset | |||
|  |     LDR     PC, vector_undef | |||
|  |     LDR     PC, vector_swi | |||
|  |     LDR     PC, vector_pabt | |||
|  |     LDR     PC, vector_dabt | |||
|  |     LDR     PC, vector_resv | |||
|  |     LDR     PC, vector_irq | |||
|  |     LDR     PC, vector_fiq | |||
|  | 
 | |||
|  | vector_reset | |||
|  |     DCD     Reset_Handler | |||
|  | vector_undef | |||
|  |     DCD     Undef_Handler | |||
|  | vector_swi | |||
|  |     DCD     SWI_Handler | |||
|  | vector_pabt | |||
|  |     DCD     PAbt_Handler | |||
|  | vector_dabt | |||
|  |     DCD     DAbt_Handler | |||
|  | vector_resv | |||
|  |     DCD     Resv_Handler | |||
|  | vector_irq | |||
|  |     DCD     IRQ_Handler | |||
|  | vector_fiq | |||
|  |     DCD     FIQ_Handler | |||
|  | 
 | |||
|  | ;----------------- Reset Handler -----------------------------------------------
 | |||
|  |     IMPORT rt_low_level_init | |||
|  |     IMPORT  __main | |||
|  |     EXPORT  Reset_Handler | |||
|  | Reset_Handler | |||
|  |     ; set the cpu to SVC32 mode
 | |||
|  |     MRS     R0,CPSR | |||
|  |     BIC     R0,R0,#MODEMASK | |||
|  |     ORR     R0,R0,#MODE_SVC:OR:NOINT | |||
|  |     MSR     CPSR_cxsf,R0 | |||
|  |      | |||
|  |     ; Set CO-Processor
 | |||
|  |     ; little-end,disbale I/D Cache MMU, vector table is 0x00000000
 | |||
|  |     MRC     p15, 0, R0, c1, c0, 0   ; Read CP15
 | |||
|  |     LDR     R1, =0x00003085         ; set clear bits
 | |||
|  |     BIC     R0, R0, R1 | |||
|  |     MCR     p15, 0, R0, c1, c0, 0   ; Write CP15
 | |||
|  | 
 | |||
|  |     ; Call low level init function,
 | |||
|  |     ; disable and clear all IRQs, Init MMU, Init interrupt controller, etc.
 | |||
|  |     LDR     SP, =SVC_STACK_START | |||
|  |     LDR     R0, =rt_low_level_init | |||
|  |     BLX     R0 | |||
|  | 
 | |||
|  | Setup_Stack | |||
|  |     ; Setup Stack for each mode
 | |||
|  |     MRS     R0, CPSR | |||
|  |     BIC     R0, R0, #MODEMASK | |||
|  | 
 | |||
|  |     ORR     R1, R0, #MODE_UND:OR:NOINT | |||
|  |     MSR     CPSR_cxsf, R1            ; Undef mode
 | |||
|  |     LDR     SP, =UND_STACK_START | |||
|  | 
 | |||
|  |     ORR     R1,R0,#MODE_ABT:OR:NOINT | |||
|  |     MSR     CPSR_cxsf,R1             ; Abort mode
 | |||
|  |     LDR     SP, =ABT_STACK_START | |||
|  | 
 | |||
|  |     ORR     R1,R0,#MODE_IRQ:OR:NOINT | |||
|  |     MSR     CPSR_cxsf,R1             ; IRQ mode
 | |||
|  |     LDR     SP, =IRQ_STACK_START | |||
|  | 
 | |||
|  |     ORR     R1,R0,#MODE_FIQ:OR:NOINT | |||
|  |     MSR     CPSR_cxsf,R1             ; FIQ mode
 | |||
|  |     LDR     SP, =FIQ_STACK_START | |||
|  | 
 | |||
|  |     ORR     R1,R0,#MODE_SYS:OR:NOINT | |||
|  |     MSR     CPSR_cxsf,R1             ; SYS/User mode
 | |||
|  |     LDR     SP, =SYS_STACK_START | |||
|  | 
 | |||
|  |     ORR     R1,R0,#MODE_SVC:OR:NOINT | |||
|  |     MSR     CPSR_cxsf,R1             ; SVC mode
 | |||
|  |     LDR     SP, =SVC_STACK_START | |||
|  | 
 | |||
|  |     ; Enter the C code
 | |||
|  |     LDR     R0, =__main | |||
|  |     BLX     R0 | |||
|  |      | |||
|  | ;----------------- Exception Handler -------------------------------------------
 | |||
|  |     IMPORT rt_hw_trap_udef | |||
|  |     IMPORT rt_hw_trap_swi | |||
|  |     IMPORT rt_hw_trap_pabt | |||
|  |     IMPORT rt_hw_trap_dabt | |||
|  |     IMPORT rt_hw_trap_resv | |||
|  |     IMPORT rt_hw_trap_irq | |||
|  |     IMPORT rt_hw_trap_fiq | |||
|  | 
 | |||
|  |     IMPORT rt_interrupt_enter | |||
|  |     IMPORT rt_interrupt_leave | |||
|  |     IMPORT rt_thread_switch_interrupt_flag | |||
|  |     IMPORT rt_interrupt_from_thread | |||
|  |     IMPORT rt_interrupt_to_thread | |||
|  | 
 | |||
|  | Undef_Handler PROC | |||
|  |     SUB     SP, SP, #S_FRAME_SIZE | |||
|  |     STMIA   SP, {R0 - R12}          ; Calling R0-R12
 | |||
|  |     ADD     R8, SP, #S_PC | |||
|  |     STMDB   R8, {SP, LR}            ; Calling SP, LR
 | |||
|  |     STR     LR, [R8, #0]            ; Save calling PC
 | |||
|  |     MRS     R6, SPSR | |||
|  |     STR     R6, [R8, #4]            ; Save CPSR
 | |||
|  |     STR     R0, [R8, #8]            ; Save SPSR
 | |||
|  |     MOV     R0, SP | |||
|  |     BL      rt_hw_trap_udef | |||
|  |     ENDP | |||
|  | 
 | |||
|  | SWI_Handler PROC | |||
|  |     BL      rt_hw_trap_swi | |||
|  |     ENDP | |||
|  | 
 | |||
|  | PAbt_Handler PROC | |||
|  |     BL      rt_hw_trap_pabt | |||
|  |     ENDP | |||
|  | 
 | |||
|  | DAbt_Handler PROC | |||
|  |     SUB     SP, SP, #S_FRAME_SIZE | |||
|  |     STMIA   SP, {R0 - R12}          ; Calling R0-R12
 | |||
|  |     ADD     R8, SP, #S_PC | |||
|  |     STMDB   R8, {SP, LR}            ; Calling SP, LR
 | |||
|  |     STR     LR, [R8, #0]            ; Save calling PC
 | |||
|  |     MRS     R6, SPSR | |||
|  |     STR     R6, [R8, #4]            ; Save CPSR
 | |||
|  |     STR     R0, [R8, #8]            ; Save SPSR
 | |||
|  |     MOV     R0, SP | |||
|  |     BL      rt_hw_trap_dabt | |||
|  |     ENDP | |||
|  | 
 | |||
|  | Resv_Handler PROC | |||
|  |     BL      rt_hw_trap_resv | |||
|  |     ENDP | |||
|  | 
 | |||
|  | FIQ_Handler PROC | |||
|  |     STMFD   SP!, {R0-R7,LR} | |||
|  |     BL      rt_hw_trap_fiq | |||
|  |     LDMFD   SP!, {R0-R7,LR} | |||
|  |     SUBS    PC, LR, #4 | |||
|  |     ENDP | |||
|  | 
 | |||
|  | IRQ_Handler PROC | |||
|  |     STMFD   SP!, {R0-R12,LR} | |||
|  |     BL      rt_interrupt_enter | |||
|  |     BL      rt_hw_trap_irq | |||
|  |     BL      rt_interrupt_leave | |||
|  | 
 | |||
|  |     ; If rt_thread_switch_interrupt_flag set,
 | |||
|  |     ; jump to rt_hw_context_switch_interrupt_do and don't return
 | |||
|  |     LDR     R0, =rt_thread_switch_interrupt_flag | |||
|  |     LDR     R1, [R0] | |||
|  |     CMP     R1, #1 | |||
|  |     BEQ     rt_hw_context_switch_interrupt_do | |||
|  | 
 | |||
|  |     LDMFD   SP!, {R0-R12,LR} | |||
|  |     SUBS    PC, LR, #4 | |||
|  |     ENDP | |||
|  | 
 | |||
|  | ;------ void rt_hw_context_switch_interrupt_do(rt_base_t flag) -----------------
 | |||
|  | rt_hw_context_switch_interrupt_do PROC | |||
|  |     MOV     R1,  #0                 ; Clear flag
 | |||
|  |     STR     R1,  [R0]               ; Save to flag variable
 | |||
|  | 
 | |||
|  |     LDMFD   SP!, {R0-R12,LR}        ; Reload saved registers
 | |||
|  |     STMFD   SP, {R0-R2}             ; Save R0-R2
 | |||
|  |     SUB     R1,  SP, #4*3           ; Save old task's SP to R1
 | |||
|  |     SUB     R2,  LR, #4             ; Save old task's PC to R2
 | |||
|  | 
 | |||
|  |     MRS     R0,  SPSR               ; Get CPSR of interrupt thread
 | |||
|  | 
 | |||
|  |     MSR     CPSR_c, #MODE_SVC:OR:NOINT  ; Switch to SVC mode and no interrupt | |||
|  | 
 | |||
|  |     STMFD   SP!, {R2}               ; Push old task's PC
 | |||
|  |     STMFD   SP!, {R3-R12,LR}        ; Push old task's LR,R12-R3
 | |||
|  |     LDMFD   R1, {R1-R3} | |||
|  |     STMFD   SP!, {R1-R3}            ; Push old task's R2-R0
 | |||
|  |     STMFD   SP!, {R0}               ; Push old task's CPSR
 | |||
|  | 
 | |||
|  |     LDR     R4,  =rt_interrupt_from_thread | |||
|  |     LDR     R5,  [R4]               ; R5 = stack ptr in old tasks's TCB
 | |||
|  |     STR     SP,  [R5]               ; Store SP in preempted tasks's TCB
 | |||
|  | 
 | |||
|  |     LDR     R6,  =rt_interrupt_to_thread | |||
|  |     LDR     R6,  [R6]               ; R6 = stack ptr in new tasks's TCB
 | |||
|  |     LDR     SP,  [R6]               ; Get new task's stack pointer
 | |||
|  | 
 | |||
|  |     LDMFD   SP!, {R4}               ; Pop new task's SPSR
 | |||
|  |     MSR     SPSR_cxsf, R4 | |||
|  | 
 | |||
|  |     LDMFD   SP!, {R0-R12,LR,PC}^    ; pop new task's R0-R12,LR & PC SPSR to CPSR
 | |||
|  |     ENDP | |||
|  | 
 | |||
|  | ;*******************************************************************************
 | |||
|  | ; User Stack and Heap initialization
 | |||
|  | ;*******************************************************************************
 | |||
|  |                  IF      :DEF:__MICROLIB | |||
|  |                  | |||
|  |                  EXPORT  __initial_sp | |||
|  |                  EXPORT  __heap_base | |||
|  |                  EXPORT  __heap_limit | |||
|  |                  | |||
|  |                  ELSE | |||
|  |                  | |||
|  |                  IMPORT  __use_two_region_memory | |||
|  |                  EXPORT  __user_initial_stackheap | |||
|  |                   | |||
|  | __user_initial_stackheap | |||
|  | 
 | |||
|  |                  LDR     R0, = Heap_Mem                         ; heap base
 | |||
|  |                  LDR     R1, = SVC_STACK_START                  ; stack base (top-address)
 | |||
|  |                  LDR     R2, = (Heap_Mem +  Heap_Size)          ; heap limit
 | |||
|  |                  LDR     R3, = (SVC_STACK_START - SVC_STK_SIZE) ; stack limit (low-address)
 | |||
|  |                  BX      LR | |||
|  | 
 | |||
|  |                  ALIGN | |||
|  | 
 | |||
|  |                  ENDIF | |||
|  | 
 | |||
|  |     END |