start_gcc.S 9.0 KB
Newer Older
1
/*
2
 * File      : start_gcc.S
3
 * This file is part of RT-Thread RTOS
4
 * COPYRIGHT (C) 2006 - 2015, RT-Thread Development Team
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Change Logs:
 * Date           Author       Notes
 * 2011-01-13     weety      first version
23
 * 2015-04-15     ArdaFu     Split from AT91SAM9260 BSP
24
 */
25
 
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
#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

.include  "rt_low_level_gcc.inc"

59
@;----------------------- Stack and Heap Definitions ---------------------------
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
    .section .nobss, "w"

    .space UND_STK_SIZE
    .global UND_STACK_START
UND_STACK_START:

    .space SVC_STK_SIZE
    .align 2
    .global SVC_STACK_START
SVC_STACK_START:

    .space ABT_STK_SIZE
    .align 2
    .global ABT_STACK_START
ABT_STACK_START:

    .space IRQ_STK_SIZE
    .align 2
    .global IRQ_STACK_START
IRQ_STACK_START:

    .space FIQ_STK_SIZE
    .align 2
    .global FIQ_STACK_START
FIQ_STACK_START:

    .skip SYS_STK_SIZE
    .align 2
    .global SYS_STACK_START
SYS_STACK_START:


92
@;--------------Jump vector table-----------------------------------------------
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 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
    .section .init, "ax"
    .arm

    .global entry
entry:
    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, R0
    LDR     SP, =SVC_STACK_START

    @; Call low level init function,
    @; disable and clear all IRQs and remap internal ram to 0x00000000.
    LDR     R0, =rt_low_level_init
    BLX     R0

    @; Copy Exception Vectors to Internal RAM
    LDR     R8, =entry              @; Source
145
    LDR     R9, =VECTOR_TABLE_START @; Destination
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 192 193 194 195 196 197 198 199 200 201 202 203 204 205
    CMP     R8, R9
    BEQ     Setup_Stack
    LDMIA   R8!, {R0-R7}            @; Load Vectors
    STMIA   R9!, {R0-R7}            @; Store Vectors
    LDMIA   R8!, {R0-R7}            @; Load Handler Addresses
    STMIA   R9!, {R0-R7}            @; Store Handler Addresses

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:
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 280 281 282 283 284 285 286 287 288 289 290 291 292 293
    @; Enter the C code
    LDR     R0, =main
    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
294 295
    STMFD   SP, {R0-R2}             @; Save R0-R2
    SUB     R1,  SP, #4*3           @; Save old task's SP to R1
296 297
    SUB     R2,  LR, #4             @; Save old task's PC to R2

298 299
    MRS     R0,  SPSR               @; Get CPSR of interrupt thread

300 301 302
    MSR     CPSR_c, #MODE_SVC|NOINT @; Switch to SVC mode and no interrupt

    STMFD   SP!, {R2}               @; Push old task's PC
303 304 305 306
    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
307 308 309 310 311 312 313 314 315 316 317 318

    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

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