1*10465441SEvalZero/* 2*10465441SEvalZero * Copyright (c) 2006-2018, RT-Thread Development Team 3*10465441SEvalZero * 4*10465441SEvalZero * SPDX-License-Identifier: Apache-2.0 5*10465441SEvalZero * 6*10465441SEvalZero * Change Logs: 7*10465441SEvalZero * Date Author Notes 8*10465441SEvalZero * 2011-01-13 weety first version 9*10465441SEvalZero * 2015-04-15 ArdaFu Split from AT91SAM9260 BSP 10*10465441SEvalZero * 2015-04-21 ArdaFu Remove remap code. Using mmu to map vector table 11*10465441SEvalZero * 2015-06-04 aozima Align stack address to 8 byte. 12*10465441SEvalZero */ 13*10465441SEvalZero 14*10465441SEvalZero#include "rt_low_level_init.h" 15*10465441SEvalZero 16*10465441SEvalZero#define S_FRAME_SIZE (18*4) //72 17*10465441SEvalZero 18*10465441SEvalZero@#define S_SPSR (17*4) //SPSR 19*10465441SEvalZero@#define S_CPSR (16*4) //CPSR 20*10465441SEvalZero#define S_PC (15*4) //R15 21*10465441SEvalZero@#define S_LR (14*4) //R14 22*10465441SEvalZero@#define S_SP (13*4) //R13 23*10465441SEvalZero 24*10465441SEvalZero@#define S_IP (12*4) //R12 25*10465441SEvalZero@#define S_FP (11*4) //R11 26*10465441SEvalZero@#define S_R10 (10*4) 27*10465441SEvalZero@#define S_R9 (9*4) 28*10465441SEvalZero@#define S_R8 (8*4) 29*10465441SEvalZero@#define S_R7 (7*4) 30*10465441SEvalZero@#define S_R6 (6*4) 31*10465441SEvalZero@#define S_R5 (5*4) 32*10465441SEvalZero@#define S_R4 (4*4) 33*10465441SEvalZero@#define S_R3 (3*4) 34*10465441SEvalZero@#define S_R2 (2*4) 35*10465441SEvalZero@#define S_R1 (1*4) 36*10465441SEvalZero@#define S_R0 (0*4) 37*10465441SEvalZero 38*10465441SEvalZero#define MODE_SYS 0x1F 39*10465441SEvalZero#define MODE_FIQ 0x11 40*10465441SEvalZero#define MODE_IRQ 0x12 41*10465441SEvalZero#define MODE_SVC 0x13 42*10465441SEvalZero#define MODE_ABT 0x17 43*10465441SEvalZero#define MODE_UND 0x1B 44*10465441SEvalZero#define MODEMASK 0x1F 45*10465441SEvalZero 46*10465441SEvalZero#define NOINT 0xC0 47*10465441SEvalZero 48*10465441SEvalZero@;----------------------- Stack and Heap Definitions --------------------------- 49*10465441SEvalZero .section .nobss, "w" 50*10465441SEvalZero 51*10465441SEvalZero .space UND_STK_SIZE 52*10465441SEvalZero .align 3 53*10465441SEvalZero .global UND_STACK_START 54*10465441SEvalZeroUND_STACK_START: 55*10465441SEvalZero 56*10465441SEvalZero .space ABT_STK_SIZE 57*10465441SEvalZero .align 3 58*10465441SEvalZero .global ABT_STACK_START 59*10465441SEvalZeroABT_STACK_START: 60*10465441SEvalZero 61*10465441SEvalZero .space FIQ_STK_SIZE 62*10465441SEvalZero .align 3 63*10465441SEvalZero .global FIQ_STACK_START 64*10465441SEvalZeroFIQ_STACK_START: 65*10465441SEvalZero 66*10465441SEvalZero .space IRQ_STK_SIZE 67*10465441SEvalZero .align 3 68*10465441SEvalZero .global IRQ_STACK_START 69*10465441SEvalZeroIRQ_STACK_START: 70*10465441SEvalZero 71*10465441SEvalZero .skip SYS_STK_SIZE 72*10465441SEvalZero .align 3 73*10465441SEvalZero .global SYS_STACK_START 74*10465441SEvalZeroSYS_STACK_START: 75*10465441SEvalZero 76*10465441SEvalZero .space SVC_STK_SIZE 77*10465441SEvalZero .align 3 78*10465441SEvalZero .global SVC_STACK_START 79*10465441SEvalZeroSVC_STACK_START: 80*10465441SEvalZero 81*10465441SEvalZero@;--------------Jump vector table----------------------------------------------- 82*10465441SEvalZero .section .init, "ax" 83*10465441SEvalZero .arm 84*10465441SEvalZero 85*10465441SEvalZero .global start 86*10465441SEvalZerostart: 87*10465441SEvalZero LDR PC, vector_reset 88*10465441SEvalZero LDR PC, vector_undef 89*10465441SEvalZero LDR PC, vector_swi 90*10465441SEvalZero LDR PC, vector_pabt 91*10465441SEvalZero LDR PC, vector_dabt 92*10465441SEvalZero LDR PC, vector_resv 93*10465441SEvalZero LDR PC, vector_irq 94*10465441SEvalZero LDR PC, vector_fiq 95*10465441SEvalZero 96*10465441SEvalZerovector_reset: 97*10465441SEvalZero .word Reset_Handler 98*10465441SEvalZerovector_undef: 99*10465441SEvalZero .word Undef_Handler 100*10465441SEvalZerovector_swi: 101*10465441SEvalZero .word SWI_Handler 102*10465441SEvalZerovector_pabt: 103*10465441SEvalZero .word PAbt_Handler 104*10465441SEvalZerovector_dabt: 105*10465441SEvalZero .word DAbt_Handler 106*10465441SEvalZerovector_resv: 107*10465441SEvalZero .word Resv_Handler 108*10465441SEvalZerovector_irq: 109*10465441SEvalZero .word IRQ_Handler 110*10465441SEvalZerovector_fiq: 111*10465441SEvalZero .word FIQ_Handler 112*10465441SEvalZero 113*10465441SEvalZero .balignl 16,0xdeadbeef 114*10465441SEvalZero 115*10465441SEvalZero@;----------------- Reset Handler --------------------------------------------- 116*10465441SEvalZero .global rt_low_level_init 117*10465441SEvalZero .global main 118*10465441SEvalZero .global Reset_Handler 119*10465441SEvalZeroReset_Handler: 120*10465441SEvalZero @; Set the cpu to SVC32 mode 121*10465441SEvalZero MRS R0, CPSR 122*10465441SEvalZero BIC R0, R0, #MODEMASK 123*10465441SEvalZero ORR R0, R0, #MODE_SVC|NOINT 124*10465441SEvalZero MSR CPSR_cxsf, R0 125*10465441SEvalZero 126*10465441SEvalZero @; Set CO-Processor 127*10465441SEvalZero @; little-end锛宒isbale I/D Cache MMU, vector table is 0x00000000 128*10465441SEvalZero MRC P15, 0, R0, C1, C0, 0 @; Read CP15 129*10465441SEvalZero LDR R1, =0x00003085 @; set clear bits 130*10465441SEvalZero BIC R0, R0, R1 131*10465441SEvalZero MCR P15, 0, R0, C1, C0, 0 @; Write CP15 132*10465441SEvalZero 133*10465441SEvalZero @; Call low level init function, 134*10465441SEvalZero @; disable and clear all IRQs, Init MMU, Init interrupt controller, etc. 135*10465441SEvalZero LDR SP, =SVC_STACK_START 136*10465441SEvalZero LDR R0, =rt_low_level_init 137*10465441SEvalZero BLX R0 138*10465441SEvalZero 139*10465441SEvalZeroSetup_Stack: 140*10465441SEvalZero @; Setup Stack for each mode 141*10465441SEvalZero MRS R0, CPSR 142*10465441SEvalZero BIC R0, R0, #MODEMASK 143*10465441SEvalZero 144*10465441SEvalZero ORR R1, R0, #MODE_UND|NOINT 145*10465441SEvalZero MSR CPSR_cxsf, R1 @; Undef mode 146*10465441SEvalZero LDR SP, =UND_STACK_START 147*10465441SEvalZero 148*10465441SEvalZero ORR R1, R0, #MODE_ABT|NOINT 149*10465441SEvalZero MSR CPSR_cxsf, R1 @; Abort mode 150*10465441SEvalZero LDR SP, =ABT_STACK_START 151*10465441SEvalZero 152*10465441SEvalZero ORR R1, R0, #MODE_IRQ|NOINT 153*10465441SEvalZero MSR CPSR_cxsf, R1 @; IRQ mode 154*10465441SEvalZero LDR SP, =IRQ_STACK_START 155*10465441SEvalZero 156*10465441SEvalZero ORR R1, R0, #MODE_FIQ|NOINT 157*10465441SEvalZero MSR CPSR_cxsf, R1 @; FIQ mode 158*10465441SEvalZero LDR SP, =FIQ_STACK_START 159*10465441SEvalZero 160*10465441SEvalZero ORR R1, R0, #MODE_SYS|NOINT 161*10465441SEvalZero MSR CPSR_cxsf,R1 @; SYS/User mode 162*10465441SEvalZero LDR SP, =SYS_STACK_START 163*10465441SEvalZero 164*10465441SEvalZero ORR R1, R0, #MODE_SVC|NOINT 165*10465441SEvalZero MSR CPSR_cxsf, R1 @; SVC mode 166*10465441SEvalZero LDR SP, =SVC_STACK_START 167*10465441SEvalZero 168*10465441SEvalZero @; clear .bss 169*10465441SEvalZero MOV R0, #0 @; get a zero 170*10465441SEvalZero LDR R1, =__bss_start__ @; bss start 171*10465441SEvalZero LDR R2, =__bss_end__ @; bss end 172*10465441SEvalZero 173*10465441SEvalZerobss_clear_loop: 174*10465441SEvalZero CMP R1, R2 @; check if data to clear 175*10465441SEvalZero STRLO R0, [R1], #4 @; clear 4 bytes 176*10465441SEvalZero BLO bss_clear_loop @; loop until done 177*10465441SEvalZero 178*10465441SEvalZero @; call C++ constructors of global objects 179*10465441SEvalZero LDR R0, =__ctors_start__ 180*10465441SEvalZero LDR R1, =__ctors_end__ 181*10465441SEvalZero 182*10465441SEvalZeroctor_loop: 183*10465441SEvalZero CMP R0, R1 184*10465441SEvalZero BEQ ctor_end 185*10465441SEvalZero LDR R2, [R0], #4 186*10465441SEvalZero STMFD SP!, {R0-R1} 187*10465441SEvalZero MOV LR, PC 188*10465441SEvalZero BX R2 189*10465441SEvalZero LDMFD SP!, {R0-R1} 190*10465441SEvalZero B ctor_loop 191*10465441SEvalZeroctor_end: 192*10465441SEvalZero 193*10465441SEvalZero @; Enter the C code 194*10465441SEvalZero LDR R0, =rtthread_startup 195*10465441SEvalZero BLX R0 196*10465441SEvalZero 197*10465441SEvalZero@;----------------- Exception Handler ----------------------------------------- 198*10465441SEvalZero .global rt_hw_trap_udef 199*10465441SEvalZero .global rt_hw_trap_swi 200*10465441SEvalZero .global rt_hw_trap_pabt 201*10465441SEvalZero .global rt_hw_trap_dabt 202*10465441SEvalZero .global rt_hw_trap_resv 203*10465441SEvalZero .global rt_hw_trap_irq 204*10465441SEvalZero .global rt_hw_trap_fiq 205*10465441SEvalZero 206*10465441SEvalZero .global rt_interrupt_enter 207*10465441SEvalZero .global rt_interrupt_leave 208*10465441SEvalZero .global rt_thread_switch_interrupt_flag 209*10465441SEvalZero .global rt_interrupt_from_thread 210*10465441SEvalZero .global rt_interrupt_to_thread 211*10465441SEvalZero 212*10465441SEvalZero .align 5 213*10465441SEvalZeroUndef_Handler: 214*10465441SEvalZero SUB SP, SP, #S_FRAME_SIZE 215*10465441SEvalZero STMIA SP, {R0 - R12} @; Calling R0-R12 216*10465441SEvalZero ADD R8, SP, #S_PC 217*10465441SEvalZero STMDB R8, {SP, LR} @; Calling SP, LR 218*10465441SEvalZero STR LR, [R8, #0] @; Save calling PC 219*10465441SEvalZero MRS R6, SPSR 220*10465441SEvalZero STR R6, [R8, #4] @; Save CPSR 221*10465441SEvalZero STR R0, [R8, #8] @; Save SPSR 222*10465441SEvalZero MOV R0, SP 223*10465441SEvalZero BL rt_hw_trap_udef 224*10465441SEvalZero 225*10465441SEvalZero .align 5 226*10465441SEvalZeroSWI_Handler: 227*10465441SEvalZero BL rt_hw_trap_swi 228*10465441SEvalZero 229*10465441SEvalZero .align 5 230*10465441SEvalZeroPAbt_Handler: 231*10465441SEvalZero BL rt_hw_trap_pabt 232*10465441SEvalZero 233*10465441SEvalZero .align 5 234*10465441SEvalZeroDAbt_Handler: 235*10465441SEvalZero SUB SP, SP, #S_FRAME_SIZE 236*10465441SEvalZero STMIA SP, {R0 - R12} @; Calling R0-R12 237*10465441SEvalZero ADD R8, SP, #S_PC 238*10465441SEvalZero STMDB R8, {SP, LR} @; Calling SP, LR 239*10465441SEvalZero STR LR, [R8, #0] @; Save calling PC 240*10465441SEvalZero MRS R6, SPSR 241*10465441SEvalZero STR R6, [R8, #4] @; Save CPSR 242*10465441SEvalZero STR R0, [R8, #8] @; Save SPSR 243*10465441SEvalZero MOV R0, SP 244*10465441SEvalZero BL rt_hw_trap_dabt 245*10465441SEvalZero 246*10465441SEvalZero .align 5 247*10465441SEvalZeroResv_Handler: 248*10465441SEvalZero BL rt_hw_trap_resv 249*10465441SEvalZero 250*10465441SEvalZero .align 5 251*10465441SEvalZeroFIQ_Handler: 252*10465441SEvalZero STMFD SP!, {R0-R7,LR} 253*10465441SEvalZero BL rt_hw_trap_fiq 254*10465441SEvalZero LDMFD SP!, {R0-R7,LR} 255*10465441SEvalZero SUBS PC, LR, #4 256*10465441SEvalZero 257*10465441SEvalZero .align 5 258*10465441SEvalZeroIRQ_Handler: 259*10465441SEvalZero STMFD SP!, {R0-R12,LR} 260*10465441SEvalZero BL rt_interrupt_enter 261*10465441SEvalZero BL rt_hw_trap_irq 262*10465441SEvalZero BL rt_interrupt_leave 263*10465441SEvalZero 264*10465441SEvalZero @; If rt_thread_switch_interrupt_flag set, 265*10465441SEvalZero @; jump to rt_hw_context_switch_interrupt_do and don't return 266*10465441SEvalZero LDR R0, =rt_thread_switch_interrupt_flag 267*10465441SEvalZero LDR R1, [R0] 268*10465441SEvalZero CMP R1, #1 269*10465441SEvalZero BEQ rt_hw_context_switch_interrupt_do 270*10465441SEvalZero 271*10465441SEvalZero LDMFD SP!, {R0-R12,LR} 272*10465441SEvalZero SUBS PC, LR, #4 273*10465441SEvalZero 274*10465441SEvalZero@;------ void rt_hw_context_switch_interrupt_do(rt_base_t flag) ----------------- 275*10465441SEvalZerort_hw_context_switch_interrupt_do: 276*10465441SEvalZero MOV R1, #0 @; Clear flag 277*10465441SEvalZero STR R1, [R0] @; Save to flag variable 278*10465441SEvalZero 279*10465441SEvalZero LDMFD SP!, {R0-R12,LR} @; Reload saved registers 280*10465441SEvalZero STMFD SP, {R0-R2} @; Save R0-R2 281*10465441SEvalZero SUB R1, SP, #4*3 @; Save old task's SP to R1 282*10465441SEvalZero SUB R2, LR, #4 @; Save old task's PC to R2 283*10465441SEvalZero 284*10465441SEvalZero MRS R0, SPSR @; Get CPSR of interrupt thread 285*10465441SEvalZero 286*10465441SEvalZero MSR CPSR_c, #MODE_SVC|NOINT @; Switch to SVC mode and no interrupt 287*10465441SEvalZero 288*10465441SEvalZero STMFD SP!, {R2} @; Push old task's PC 289*10465441SEvalZero STMFD SP!, {R3-R12,LR} @; Push old task's LR,R12-R3 290*10465441SEvalZero LDMFD R1, {R1-R3} 291*10465441SEvalZero STMFD SP!, {R1-R3} @; Push old task's R2-R0 292*10465441SEvalZero STMFD SP!, {R0} @; Push old task's CPSR 293*10465441SEvalZero 294*10465441SEvalZero LDR R4, =rt_interrupt_from_thread 295*10465441SEvalZero LDR R5, [R4] @; R5 = stack ptr in old tasks's TCB 296*10465441SEvalZero STR SP, [R5] @; Store SP in preempted tasks's TCB 297*10465441SEvalZero 298*10465441SEvalZero LDR R6, =rt_interrupt_to_thread 299*10465441SEvalZero LDR R6, [R6] @; R6 = stack ptr in new tasks's TCB 300*10465441SEvalZero LDR SP, [R6] @; Get new task's stack pointer 301*10465441SEvalZero 302*10465441SEvalZero LDMFD SP!, {R4} @; Pop new task's SPSR 303*10465441SEvalZero MSR SPSR_cxsf, R4 304*10465441SEvalZero 305*10465441SEvalZero LDMFD SP!, {R0-R12,LR,PC}^ @; pop new task's R0-R12,LR & PC SPSR 2 CPSR 306