start_iar.s 10.1 KB
Newer Older
山河's avatar
山河 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 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 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 124 125 126 127 128 129 130 131 132 133 134 135 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 192 193 194 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 280 281 282 283 284 285 286 287 288 289 290 291 292
/*
 * File      : start_iar.s
 * This file is part of RT-Thread RTOS
 * COPYRIGHT (C) 2015, RT-Thread Development Team
 *
 *  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
 * 2015-04-06     zchong      the first version 
 */

        MODULE  ?cstartup
        
        ; --------------------
; Mode, correspords to bits 0-5 in CPSR

MODE_MSK DEFINE 0x1F            ; Bit mask for mode bits in CPSR
I_Bit    DEFINE 0x80            ; when I bit is set, IRQ is disabled
F_Bit    DEFINE 0x40            ; when F bit is set, FIQ is disabled

USR_MODE DEFINE 0x10            ; User mode
FIQ_MODE DEFINE 0x11            ; Fast Interrupt Request mode
IRQ_MODE DEFINE 0x12            ; Interrupt Request mode
SVC_MODE DEFINE 0x13            ; Supervisor mode
ABT_MODE DEFINE 0x17            ; Abort mode
UND_MODE DEFINE 0x1B            ; Undefined Instruction mode
SYS_MODE DEFINE 0x1F            ; System mode

        
        ;; Forward declaration of sections.
        SECTION IRQ_STACK:DATA:NOROOT(3)
        SECTION FIQ_STACK:DATA:NOROOT(3)
        SECTION SVC_STACK:DATA:NOROOT(3)
        SECTION ABT_STACK:DATA:NOROOT(3)
        SECTION UND_STACK:DATA:NOROOT(3)
        SECTION CSTACK:DATA:NOROOT(3)
        SECTION .text:CODE
        
        
        SECTION .intvec:CODE:NOROOT(5)

        PUBLIC  __vector
        PUBLIC  __iar_program_start


__iar_init$$done:               ; The vector table is not needed
                                ; until after copy initialization is done

__vector:                       ; Make this a DATA label, so that stack usage
                                ; analysis doesn't consider it an uncalled fun
        ARM

        ; All default exception handlers (except reset) are
        ; defined as weak symbol definitions.
        ; If a handler is defined by the application it will take precedence.
        LDR     PC,Reset_Addr           ; Reset
        LDR     PC,Undefined_Addr       ; Undefined instructions
        LDR     PC,SWI_Addr             ; Software interrupt (SWI/SVC)
        LDR     PC,Prefetch_Addr        ; Prefetch abort
        LDR     PC,Abort_Addr           ; Data abort
        DCD     0                       ; RESERVED
        LDR     PC,IRQ_Addr             ; IRQ
        LDR     PC,FIQ_Addr             ; FIQ

        DATA

Reset_Addr:     DCD   __iar_program_start
Undefined_Addr: DCD   Undefined_Handler
SWI_Addr:       DCD   SWI_Handler
Prefetch_Addr:  DCD   Prefetch_Handler
Abort_Addr:     DCD   Abort_Handler
IRQ_Addr:       DCD   IRQ_Handler
FIQ_Addr:       DCD   FIQ_Handler


; --------------------------------------------------
; ?cstartup -- low-level system initialization code.
;
; After a reset execution starts here, the mode is ARM, supervisor
; with interrupts disabled.
;

        SECTION .text:CODE:NOROOT(2)

        EXTERN  rt_hw_trap_udef
        EXTERN  rt_hw_trap_swi
        EXTERN  rt_hw_trap_pabt
        EXTERN  rt_hw_trap_dabt
        EXTERN  rt_hw_trap_fiq
        EXTERN  rt_hw_trap_irq
        EXTERN  rt_interrupt_enter
        EXTERN  rt_interrupt_leave
        EXTERN  rt_thread_switch_interrupt_flag
        EXTERN  rt_interrupt_from_thread
        EXTERN  rt_interrupt_to_thread
        EXTERN  rt_current_thread
        EXTERN  vmm_thread
        EXTERN  vmm_virq_check
        
        EXTERN  __cmain
        REQUIRE __vector
        EXTWEAK __iar_init_core
        EXTWEAK __iar_init_vfp


        ARM

__iar_program_start:
?cstartup:

;
; Add initialization needed before setup of stackpointers here.
;

;
; Initialize the stack pointers.
; The pattern below can be used for any of the exception stacks:
; FIQ, IRQ, SVC, ABT, UND, SYS.
; The USR mode uses the same stack as SYS.
; The stack segments must be defined in the linker command file,
; and be declared above.
;

        MRS     r0, cpsr                ; Original PSR value

        ;; Set up the interrupt stack pointer.
        BIC     r0, r0, #MODE_MSK       ; Clear the mode bits
        ORR     r0, r0, #IRQ_MODE       ; Set IRQ mode bits
        MSR     cpsr_c, r0              ; Change the mode
        LDR     sp, =SFE(IRQ_STACK)     ; End of IRQ_STACK
        BIC     sp,sp,#0x7              ; Make sure SP is 8 aligned

        ;; Set up the fast interrupt stack pointer.
        BIC     r0, r0, #MODE_MSK       ; Clear the mode bits
        ORR     r0, r0, #FIQ_MODE       ; Set FIR mode bits
        MSR     cpsr_c, r0              ; Change the mode
        LDR     sp, =SFE(FIQ_STACK)     ; End of FIQ_STACK
        BIC     sp,sp,#0x7              ; Make sure SP is 8 aligned
        
        BIC     r0,r0,#MODE_MSK         ; Clear the mode bits
        ORR     r0,r0,#ABT_MODE         ; Set Abort mode bits
        MSR     cpsr_c,r0               ; Change the mode
        LDR     sp,=SFE(ABT_STACK)      ; End of ABT_STACK
        BIC     sp,sp,#0x7              ; Make sure SP is 8 aligned

        BIC     r0,r0,#MODE_MSK         ; Clear the mode bits
        ORR     r0,r0,#UND_MODE         ; Set Undefined mode bits
        MSR     cpsr_c,r0               ; Change the mode
        LDR     sp,=SFE(UND_STACK)      ; End of UND_STACK
        BIC     sp,sp,#0x7              ; Make sure SP is 8 aligned

        ;; Set up the normal stack pointer.
        BIC     r0 ,r0, #MODE_MSK       ; Clear the mode bits
        ORR     r0 ,r0, #SVC_MODE       ; Set System mode bits
        MSR     cpsr_c, r0              ; Change the mode
        LDR     sp, =SFE(SVC_STACK)     ; End of SVC_STACK
        BIC     sp,sp,#0x7              ; Make sure SP is 8 aligned

        ;; Turn on core features assumed to be enabled.
        BL      __iar_init_core

        ;; Initialize VFP (if needed).
        BL      __iar_init_vfp


        ;; Continue to __cmain for C-level initialization.
        B       __cmain

      
Undefined_Handler:
        SUB     sp, sp, #72
        STMIA   sp, {r0 - r12}          ;/* Calling r0-r12                  */
        ADD     r8, sp, #60

        MRS     r1, cpsr
        MRS     r2, spsr
        ORR     r2,r2, #I_Bit | F_Bit
        MSR     cpsr_c, r2
        MOV     r0, r0
        STMDB   r8, {sp, lr}            ;/* Calling SP, LR                  */
        MSR     cpsr_c, r1              ;/* return to Undefined Instruction mode  */

        STR     lr, [r8, #0]            ;/* Save calling PC                 */
        MRS     r6, spsr
        STR     r6, [r8, #4]            ;/* Save CPSR                       */
        STR     r0, [r8, #8]            ;/* Save OLD_R0                     */
        MOV     r0, sp

        BL      rt_hw_trap_udef

        LDMIA    sp, {r0 - r12}         ;/* Calling r0 - r2  */
        MOV      r0, r0
        LDR      lr, [sp, #60]          ;/* Get PC   */
        ADD      sp, sp, #72
        MOVS     pc, lr                 ;/* return & move spsr_svc into cpsr */

SWI_Handler:
        BL      rt_hw_trap_swi

Prefetch_Handler:
        BL      rt_hw_trap_pabt

Abort_Handler:
        SUB     sp, sp, #72
        STMIA   sp, {r0 - r12}          ;/* Calling r0-r12                  */
        ADD     r8, sp, #60
        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 OLD_R0                     */
        MOV     r0, sp

        BL      rt_hw_trap_dabt

        LDMIA    sp, {r0 - r12}         ;/* Calling r0 - r2  */
        MOV      r0, r0
        LDR      lr, [sp, #60]          ;/* Get PC   */
        ADD      sp, sp, #72
        MOVS     pc, lr                 ;/* return & move spsr_svc into cpsr */
         
FIQ_Handler:
        STMFD   sp!,{r0-r7,lr}
        BL      rt_hw_trap_fiq
        LDMFD   sp!,{r0-r7,lr}
        SUBS    pc,lr,#4

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

rt_hw_context_switch_interrupt_do:
        MOV     r1,  #0         ; clear flag
        STR     r1,  [r0]

        LDMFD   sp!, {r0-r12,lr}; reload saved registers
        STMFD   sp,  {r0-r2}    ; save r0-r2

        MRS     r0,  spsr       ; get cpsr of interrupt thread

        SUB     r1,  sp, #4*3
        SUB     r2,  lr, #4     ; save old task's pc to r2

        ; switch to SVC mode with no interrupt
        MSR     cpsr_c, #I_Bit | F_Bit | SVC_MODE

        STMFD   sp!, {r2}       ; push old task's pc
        STMFD   sp!, {r3-r12,lr}; push old task's lr,r12-r4
        LDMFD   r1,  {r1-r3}    ; restore r0-r2 of the interrupt thread
        STMFD   sp!, {r1-r3}    ; push old task's r0-r2
        STMFD   sp!, {r0}       ; push old task's cpsr

        LDR     r4,  =rt_interrupt_from_thread
        LDR     r5,  [r4]
        STR     sp,  [r5]       ; store sp in preempted tasks's TCB

        LDR     r6,  =rt_interrupt_to_thread
        LDR     r6,  [r6]
        LDR     sp,  [r6]       ; get new task's stack pointer

        LDMFD   sp!, {r4}       ; pop new task's cpsr to spsr
        MSR     spsr_cxsf, r4

        LDMFD   sp!, {r0-r12,lr,pc}^ ; pop new task's r0-r12,lr & pc, copy spsr to cpsr
    
     END