123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- /*
- * Copyright (c) 2006-2018, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2011-01-13 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.
- */
- #include "rt_low_level_init.h"
- #define S_FRAME_SIZE (18*4) //72
- @#define S_SPSR (17*4) //SPSR
- @#define S_CPSR (16*4) //CPSR
- #define S_PC (15*4) //R15
- @#define S_LR (14*4) //R14
- @#define S_SP (13*4) //R13
- @#define S_IP (12*4) //R12
- @#define S_FP (11*4) //R11
- @#define S_R10 (10*4)
- @#define S_R9 (9*4)
- @#define S_R8 (8*4)
- @#define S_R7 (7*4)
- @#define S_R6 (6*4)
- @#define S_R5 (5*4)
- @#define S_R4 (4*4)
- @#define S_R3 (3*4)
- @#define S_R2 (2*4)
- @#define S_R1 (1*4)
- @#define S_R0 (0*4)
- #define MODE_SYS 0x1F
- #define MODE_FIQ 0x11
- #define MODE_IRQ 0x12
- #define MODE_SVC 0x13
- #define MODE_ABT 0x17
- #define MODE_UND 0x1B
- #define MODEMASK 0x1F
- #define NOINT 0xC0
- @;----------------------- Stack and Heap Definitions ---------------------------
- .section .nobss, "w"
- .space UND_STK_SIZE
- .align 3
- .global UND_STACK_START
- UND_STACK_START:
- .space ABT_STK_SIZE
- .align 3
- .global ABT_STACK_START
- ABT_STACK_START:
- .space FIQ_STK_SIZE
- .align 3
- .global FIQ_STACK_START
- FIQ_STACK_START:
- .space IRQ_STK_SIZE
- .align 3
- .global IRQ_STACK_START
- IRQ_STACK_START:
- .skip SYS_STK_SIZE
- .align 3
- .global SYS_STACK_START
- SYS_STACK_START:
- .space SVC_STK_SIZE
- .align 3
- .global SVC_STACK_START
- SVC_STACK_START:
- @;--------------Jump vector table-----------------------------------------------
- .section .init, "ax"
- .arm
- .global start
- start:
- 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:
- .word Reset_Handler
- vector_undef:
- .word Undef_Handler
- vector_swi:
- .word SWI_Handler
- vector_pabt:
- .word PAbt_Handler
- vector_dabt:
- .word DAbt_Handler
- vector_resv:
- .word Resv_Handler
- vector_irq:
- .word IRQ_Handler
- vector_fiq:
- .word FIQ_Handler
- .balignl 16,0xdeadbeef
- @;----------------- Reset Handler ---------------------------------------------
- .global rt_low_level_init
- .global main
- .global Reset_Handler
- Reset_Handler:
- @; Set the cpu to SVC32 mode
- MRS R0, CPSR
- BIC R0, R0, #MODEMASK
- ORR R0, R0, #MODE_SVC|NOINT
- MSR CPSR_cxsf, R0
-
- @; Set CO-Processor
- @; little-end锛宒isbale 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|NOINT
- MSR CPSR_cxsf, R1 @; Undef mode
- LDR SP, =UND_STACK_START
- ORR R1, R0, #MODE_ABT|NOINT
- MSR CPSR_cxsf, R1 @; Abort mode
- LDR SP, =ABT_STACK_START
- ORR R1, R0, #MODE_IRQ|NOINT
- MSR CPSR_cxsf, R1 @; IRQ mode
- LDR SP, =IRQ_STACK_START
- ORR R1, R0, #MODE_FIQ|NOINT
- MSR CPSR_cxsf, R1 @; FIQ mode
- LDR SP, =FIQ_STACK_START
- ORR R1, R0, #MODE_SYS|NOINT
- MSR CPSR_cxsf,R1 @; SYS/User mode
- LDR SP, =SYS_STACK_START
- ORR R1, R0, #MODE_SVC|NOINT
- MSR CPSR_cxsf, R1 @; SVC mode
- LDR SP, =SVC_STACK_START
- @; clear .bss
- MOV R0, #0 @; get a zero
- LDR R1, =__bss_start__ @; bss start
- LDR R2, =__bss_end__ @; bss end
- bss_clear_loop:
- CMP R1, R2 @; check if data to clear
- STRLO R0, [R1], #4 @; clear 4 bytes
- BLO bss_clear_loop @; loop until done
- @; call C++ constructors of global objects
- LDR R0, =__ctors_start__
- LDR R1, =__ctors_end__
- ctor_loop:
- CMP R0, R1
- BEQ ctor_end
- LDR R2, [R0], #4
- STMFD SP!, {R0-R1}
- MOV LR, PC
- BX R2
- LDMFD SP!, {R0-R1}
- B ctor_loop
- ctor_end:
- @; Enter the C code
- LDR R0, =rtthread_startup
- BLX R0
- @;----------------- Exception Handler -----------------------------------------
- .global rt_hw_trap_udef
- .global rt_hw_trap_swi
- .global rt_hw_trap_pabt
- .global rt_hw_trap_dabt
- .global rt_hw_trap_resv
- .global rt_hw_trap_irq
- .global rt_hw_trap_fiq
- .global rt_interrupt_enter
- .global rt_interrupt_leave
- .global rt_thread_switch_interrupt_flag
- .global rt_interrupt_from_thread
- .global rt_interrupt_to_thread
-
- .align 5
- Undef_Handler:
- 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
-
- .align 5
- SWI_Handler:
- BL rt_hw_trap_swi
-
- .align 5
- PAbt_Handler:
- BL rt_hw_trap_pabt
- .align 5
- DAbt_Handler:
- 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
- .align 5
- Resv_Handler:
- BL rt_hw_trap_resv
- .align 5
- FIQ_Handler:
- STMFD SP!, {R0-R7,LR}
- BL rt_hw_trap_fiq
- LDMFD SP!, {R0-R7,LR}
- SUBS PC, LR, #4
- .align 5
- IRQ_Handler:
- 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
- @;------ void rt_hw_context_switch_interrupt_do(rt_base_t flag) -----------------
- rt_hw_context_switch_interrupt_do:
- 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|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 2 CPSR
|