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 * 2013-07-05 Bernard the first version 9*10465441SEvalZero */ 10*10465441SEvalZero 11*10465441SEvalZero.equ Mode_USR, 0x10 12*10465441SEvalZero.equ Mode_FIQ, 0x11 13*10465441SEvalZero.equ Mode_IRQ, 0x12 14*10465441SEvalZero.equ Mode_SVC, 0x13 15*10465441SEvalZero.equ Mode_ABT, 0x17 16*10465441SEvalZero.equ Mode_UND, 0x1B 17*10465441SEvalZero.equ Mode_SYS, 0x1F 18*10465441SEvalZero 19*10465441SEvalZero.equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled 20*10465441SEvalZero.equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled 21*10465441SEvalZero 22*10465441SEvalZero.equ UND_Stack_Size, 0x00000200 23*10465441SEvalZero.equ SVC_Stack_Size, 0x00000100 24*10465441SEvalZero.equ ABT_Stack_Size, 0x00000000 25*10465441SEvalZero.equ FIQ_Stack_Size, 0x00000000 26*10465441SEvalZero.equ IRQ_Stack_Size, 0x00000100 27*10465441SEvalZero.equ USR_Stack_Size, 0x00000100 28*10465441SEvalZero 29*10465441SEvalZero#define ISR_Stack_Size (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \ 30*10465441SEvalZero FIQ_Stack_Size + IRQ_Stack_Size) 31*10465441SEvalZero 32*10465441SEvalZero/* stack */ 33*10465441SEvalZero.globl stack_start 34*10465441SEvalZero.globl stack_top 35*10465441SEvalZero 36*10465441SEvalZerostack_start: 37*10465441SEvalZero.rept ISR_Stack_Size 38*10465441SEvalZero.long 0 39*10465441SEvalZero.endr 40*10465441SEvalZerostack_top: 41*10465441SEvalZero 42*10465441SEvalZero/* reset entry */ 43*10465441SEvalZero.globl _reset 44*10465441SEvalZero_reset: 45*10465441SEvalZero /* set the cpu to SVC32 mode and disable interrupt */ 46*10465441SEvalZero mrs r0, cpsr 47*10465441SEvalZero bic r0, r0, #0x1f 48*10465441SEvalZero orr r0, r0, #0x13 49*10465441SEvalZero msr cpsr_c, r0 50*10465441SEvalZero 51*10465441SEvalZero /* setup stack */ 52*10465441SEvalZero bl stack_setup 53*10465441SEvalZero 54*10465441SEvalZero /* clear .bss */ 55*10465441SEvalZero mov r0,#0 /* get a zero */ 56*10465441SEvalZero ldr r1,=__bss_start /* bss start */ 57*10465441SEvalZero ldr r2,=__bss_end /* bss end */ 58*10465441SEvalZero 59*10465441SEvalZerobss_loop: 60*10465441SEvalZero cmp r1,r2 /* check if data to clear */ 61*10465441SEvalZero strlo r0,[r1],#4 /* clear 4 bytes */ 62*10465441SEvalZero blo bss_loop /* loop until done */ 63*10465441SEvalZero 64*10465441SEvalZero /* call C++ constructors of global objects */ 65*10465441SEvalZero ldr r0, =__ctors_start__ 66*10465441SEvalZero ldr r1, =__ctors_end__ 67*10465441SEvalZero 68*10465441SEvalZeroctor_loop: 69*10465441SEvalZero cmp r0, r1 70*10465441SEvalZero beq ctor_end 71*10465441SEvalZero ldr r2, [r0], #4 72*10465441SEvalZero stmfd sp!, {r0-r1} 73*10465441SEvalZero mov lr, pc 74*10465441SEvalZero bx r2 75*10465441SEvalZero ldmfd sp!, {r0-r1} 76*10465441SEvalZero b ctor_loop 77*10465441SEvalZeroctor_end: 78*10465441SEvalZero 79*10465441SEvalZero /* start RT-Thread Kernel */ 80*10465441SEvalZero ldr pc, _rtthread_startup 81*10465441SEvalZero_rtthread_startup: 82*10465441SEvalZero .word rtthread_startup 83*10465441SEvalZero 84*10465441SEvalZerostack_setup: 85*10465441SEvalZero ldr r0, =stack_top 86*10465441SEvalZero 87*10465441SEvalZero @ Enter Undefined Instruction Mode and set its Stack Pointer 88*10465441SEvalZero msr cpsr_c, #Mode_UND|I_Bit|F_Bit 89*10465441SEvalZero mov sp, r0 90*10465441SEvalZero sub r0, r0, #UND_Stack_Size 91*10465441SEvalZero 92*10465441SEvalZero @ Enter Abort Mode and set its Stack Pointer 93*10465441SEvalZero msr cpsr_c, #Mode_ABT|I_Bit|F_Bit 94*10465441SEvalZero mov sp, r0 95*10465441SEvalZero sub r0, r0, #ABT_Stack_Size 96*10465441SEvalZero 97*10465441SEvalZero @ Enter FIQ Mode and set its Stack Pointer 98*10465441SEvalZero msr cpsr_c, #Mode_FIQ|I_Bit|F_Bit 99*10465441SEvalZero mov sp, r0 100*10465441SEvalZero sub r0, r0, #FIQ_Stack_Size 101*10465441SEvalZero 102*10465441SEvalZero @ Enter IRQ Mode and set its Stack Pointer 103*10465441SEvalZero msr cpsr_c, #Mode_IRQ|I_Bit|F_Bit 104*10465441SEvalZero mov sp, r0 105*10465441SEvalZero sub r0, r0, #IRQ_Stack_Size 106*10465441SEvalZero 107*10465441SEvalZero @ Enter Supervisor Mode and set its Stack Pointer 108*10465441SEvalZero msr cpsr_c, #Mode_SVC|I_Bit|F_Bit 109*10465441SEvalZero mov sp, r0 110*10465441SEvalZero sub r0, r0, #SVC_Stack_Size 111*10465441SEvalZero 112*10465441SEvalZero @ Enter User Mode and set its Stack Pointer 113*10465441SEvalZero mov sp, r0 114*10465441SEvalZero sub sl, sp, #USR_Stack_Size 115*10465441SEvalZero bx lr 116*10465441SEvalZero 117*10465441SEvalZero/* exception handlers: undef, swi, padt, dabt, resv, irq, fiq */ 118*10465441SEvalZero .align 5 119*10465441SEvalZero.globl vector_undef 120*10465441SEvalZerovector_undef: 121*10465441SEvalZero sub sp, sp, #72 122*10465441SEvalZero stmia sp, {r0 - r12} @/* Calling r0-r12 */ 123*10465441SEvalZero add r8, sp, #60 124*10465441SEvalZero 125*10465441SEvalZero mrs r1, cpsr 126*10465441SEvalZero mrs r2, spsr 127*10465441SEvalZero orr r2,r2, #I_Bit|F_Bit 128*10465441SEvalZero msr cpsr_c, r2 129*10465441SEvalZero mov r0, r0 130*10465441SEvalZero stmdb r8, {sp, lr} @/* Calling SP, LR */ 131*10465441SEvalZero msr cpsr_c, r1 @/* return to Undefined Instruction mode */ 132*10465441SEvalZero 133*10465441SEvalZero str lr, [r8, #0] @/* Save calling PC */ 134*10465441SEvalZero mrs r6, spsr 135*10465441SEvalZero str r6, [r8, #4] @/* Save CPSR */ 136*10465441SEvalZero str r0, [r8, #8] @/* Save OLD_R0 */ 137*10465441SEvalZero mov r0, sp 138*10465441SEvalZero 139*10465441SEvalZero bl rt_hw_trap_udef 140*10465441SEvalZero 141*10465441SEvalZero ldmia sp, {r0 - r12} @/* Calling r0 - r2 */ 142*10465441SEvalZero mov r0, r0 143*10465441SEvalZero ldr lr, [sp, #60] @/* Get PC */ 144*10465441SEvalZero add sp, sp, #72 145*10465441SEvalZero movs pc, lr @/* return & move spsr_svc into cpsr */ 146*10465441SEvalZero 147*10465441SEvalZero .align 5 148*10465441SEvalZero.globl vector_swi 149*10465441SEvalZerovector_swi: 150*10465441SEvalZero bl rt_hw_trap_swi 151*10465441SEvalZero 152*10465441SEvalZero .align 5 153*10465441SEvalZero.globl vector_pabt 154*10465441SEvalZerovector_pabt: 155*10465441SEvalZero bl rt_hw_trap_pabt 156*10465441SEvalZero 157*10465441SEvalZero .align 5 158*10465441SEvalZero.globl vector_dabt 159*10465441SEvalZerovector_dabt: 160*10465441SEvalZero sub sp, sp, #72 161*10465441SEvalZero stmia sp, {r0 - r12} @/* Calling r0-r12 */ 162*10465441SEvalZero add r8, sp, #60 163*10465441SEvalZero stmdb r8, {sp, lr} @/* Calling SP, LR */ 164*10465441SEvalZero str lr, [r8, #0] @/* Save calling PC */ 165*10465441SEvalZero mrs r6, spsr 166*10465441SEvalZero str r6, [r8, #4] @/* Save CPSR */ 167*10465441SEvalZero str r0, [r8, #8] @/* Save OLD_R0 */ 168*10465441SEvalZero mov r0, sp 169*10465441SEvalZero 170*10465441SEvalZero bl rt_hw_trap_dabt 171*10465441SEvalZero 172*10465441SEvalZero ldmia sp, {r0 - r12} @/* Calling r0 - r2 */ 173*10465441SEvalZero mov r0, r0 174*10465441SEvalZero ldr lr, [sp, #60] @/* Get PC */ 175*10465441SEvalZero add sp, sp, #72 176*10465441SEvalZero movs pc, lr @/* return & move spsr_svc into cpsr */ 177*10465441SEvalZero 178*10465441SEvalZero .align 5 179*10465441SEvalZero.globl vector_resv 180*10465441SEvalZerovector_resv: 181*10465441SEvalZero b . 182*10465441SEvalZero 183*10465441SEvalZero .align 5 184*10465441SEvalZero.globl vector_fiq 185*10465441SEvalZerovector_fiq: 186*10465441SEvalZero stmfd sp!,{r0-r7,lr} 187*10465441SEvalZero bl rt_hw_trap_fiq 188*10465441SEvalZero ldmfd sp!,{r0-r7,lr} 189*10465441SEvalZero subs pc,lr,#4 190*10465441SEvalZero 191*10465441SEvalZero.globl rt_interrupt_enter 192*10465441SEvalZero.globl rt_interrupt_leave 193*10465441SEvalZero.globl rt_thread_switch_interrupt_flag 194*10465441SEvalZero.globl rt_interrupt_from_thread 195*10465441SEvalZero.globl rt_interrupt_to_thread 196*10465441SEvalZero 197*10465441SEvalZero.globl rt_current_thread 198*10465441SEvalZero.globl vmm_thread 199*10465441SEvalZero.globl vmm_virq_check 200*10465441SEvalZero 201*10465441SEvalZero.globl vector_irq 202*10465441SEvalZerovector_irq: 203*10465441SEvalZero stmfd sp!, {r0-r12,lr} 204*10465441SEvalZero 205*10465441SEvalZero bl rt_interrupt_enter 206*10465441SEvalZero bl rt_hw_trap_irq 207*10465441SEvalZero bl rt_interrupt_leave 208*10465441SEvalZero 209*10465441SEvalZero @ if rt_thread_switch_interrupt_flag set, jump to 210*10465441SEvalZero @ rt_hw_context_switch_interrupt_do and don't return 211*10465441SEvalZero ldr r0, =rt_thread_switch_interrupt_flag 212*10465441SEvalZero ldr r1, [r0] 213*10465441SEvalZero cmp r1, #1 214*10465441SEvalZero beq rt_hw_context_switch_interrupt_do 215*10465441SEvalZero 216*10465441SEvalZero ldmfd sp!, {r0-r12,lr} 217*10465441SEvalZero subs pc, lr, #4 218*10465441SEvalZero 219*10465441SEvalZerort_hw_context_switch_interrupt_do: 220*10465441SEvalZero mov r1, #0 @ clear flag 221*10465441SEvalZero str r1, [r0] 222*10465441SEvalZero 223*10465441SEvalZero ldmfd sp!, {r0-r12,lr}@ reload saved registers 224*10465441SEvalZero stmfd sp, {r0-r2} @ save r0-r2 225*10465441SEvalZero 226*10465441SEvalZero mrs r0, spsr @ get cpsr of interrupt thread 227*10465441SEvalZero 228*10465441SEvalZero sub r1, sp, #4*3 229*10465441SEvalZero sub r2, lr, #4 @ save old task's pc to r2 230*10465441SEvalZero 231*10465441SEvalZero @ switch to SVC mode with no interrupt 232*10465441SEvalZero msr cpsr_c, #I_Bit|F_Bit|Mode_SVC 233*10465441SEvalZero 234*10465441SEvalZero stmfd sp!, {r2} @ push old task's pc 235*10465441SEvalZero stmfd sp!, {r3-r12,lr}@ push old task's lr,r12-r4 236*10465441SEvalZero ldmfd r1, {r1-r3} @ restore r0-r2 of the interrupt thread 237*10465441SEvalZero stmfd sp!, {r1-r3} @ push old task's r0-r2 238*10465441SEvalZero stmfd sp!, {r0} @ push old task's cpsr 239*10465441SEvalZero 240*10465441SEvalZero ldr r4, =rt_interrupt_from_thread 241*10465441SEvalZero ldr r5, [r4] 242*10465441SEvalZero str sp, [r5] @ store sp in preempted tasks's TCB 243*10465441SEvalZero 244*10465441SEvalZero ldr r6, =rt_interrupt_to_thread 245*10465441SEvalZero ldr r6, [r6] 246*10465441SEvalZero ldr sp, [r6] @ get new task's stack pointer 247*10465441SEvalZero 248*10465441SEvalZero ldmfd sp!, {r4} @ pop new task's cpsr to spsr 249*10465441SEvalZero msr spsr_cxsf, r4 250*10465441SEvalZero 251*10465441SEvalZero ldmfd sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr 252