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
 | 
