start_gcc.S 8.3 KB
Newer Older
1
/*
2
 * Copyright (c) 2006-2018, RT-Thread Development Team
3
 *
4
 * SPDX-License-Identifier: Apache-2.0
5 6 7 8
 *
 * Change Logs:
 * Date           Author       Notes
 * 2011-01-13     weety      first version
9
 * 2015-04-15     ArdaFu     Split from AT91SAM9260 BSP
A
ardafu 已提交
10
 * 2015-04-21     ArdaFu     Remove remap code. Using mmu to map vector table
wuyangyong's avatar
wuyangyong 已提交
11
 * 2015-06-04     aozima     Align stack address to 8 byte.
12
 */
13 14 15

#include "rt_low_level_init.h"

16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
#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

46
#define NOINT           0xC0
47

48
@;----------------------- Stack and Heap Definitions ---------------------------
49 50 51
    .section .nobss, "w"

    .space UND_STK_SIZE
wuyangyong's avatar
wuyangyong 已提交
52
    .align 3
53 54 55 56
    .global UND_STACK_START
UND_STACK_START:

    .space ABT_STK_SIZE
wuyangyong's avatar
wuyangyong 已提交
57
    .align 3
58 59 60 61
    .global ABT_STACK_START
ABT_STACK_START:

    .space FIQ_STK_SIZE
wuyangyong's avatar
wuyangyong 已提交
62
    .align 3
63 64 65
    .global FIQ_STACK_START
FIQ_STACK_START:

A
ardafu 已提交
66
    .space IRQ_STK_SIZE
wuyangyong's avatar
wuyangyong 已提交
67
    .align 3
A
ardafu 已提交
68 69 70
    .global IRQ_STACK_START
IRQ_STACK_START:

71
    .skip SYS_STK_SIZE
wuyangyong's avatar
wuyangyong 已提交
72
    .align 3
73 74 75
    .global SYS_STACK_START
SYS_STACK_START:

A
ardafu 已提交
76
    .space SVC_STK_SIZE
wuyangyong's avatar
wuyangyong 已提交
77
    .align 3
A
ardafu 已提交
78 79
    .global SVC_STACK_START
SVC_STACK_START:
80

81
@;--------------Jump vector table-----------------------------------------------
82 83 84
    .section .init, "ax"
    .arm

85 86
    .global start
start:
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
    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
A
ardafu 已提交
124 125 126
    MSR     CPSR_cxsf, R0
    
    @; Set CO-Processor
127
    @; little-end锛宒isbale I/D Cache MMU, vector table is 0x00000000
A
ardafu 已提交
128 129 130 131
    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
132 133

    @; Call low level init function,
A
ardafu 已提交
134 135
    @; disable and clear all IRQs, Init MMU, Init interrupt controller, etc.
    LDR     SP, =SVC_STACK_START
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
    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:
192

193
    @; Enter the C code
194
    LDR     R0, =rtthread_startup
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
    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
280 281
    STMFD   SP, {R0-R2}             @; Save R0-R2
    SUB     R1,  SP, #4*3           @; Save old task's SP to R1
282 283
    SUB     R2,  LR, #4             @; Save old task's PC to R2

284 285
    MRS     R0,  SPSR               @; Get CPSR of interrupt thread

286 287 288
    MSR     CPSR_c, #MODE_SVC|NOINT @; Switch to SVC mode and no interrupt

    STMFD   SP!, {R2}               @; Push old task's PC
289 290 291 292
    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
293 294 295 296 297 298 299 300 301 302 303 304

    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

305
    LDMFD   SP!, {R0-R12,LR,PC}^    @; pop new task's R0-R12,LR & PC SPSR 2 CPSR