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, 0x00000000 23*10465441SEvalZero.equ SVC_Stack_Size, 0x00000100 24*10465441SEvalZero.equ ABT_Stack_Size, 0x00000000 25*10465441SEvalZero.equ RT_FIQ_STACK_PGSZ, 0x00000000 26*10465441SEvalZero.equ RT_IRQ_STACK_PGSZ, 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 RT_FIQ_STACK_PGSZ + RT_IRQ_STACK_PGSZ) 31*10465441SEvalZero 32*10465441SEvalZero.section .data.share.isr 33*10465441SEvalZero/* stack */ 34*10465441SEvalZero.globl stack_start 35*10465441SEvalZero.globl stack_top 36*10465441SEvalZero 37*10465441SEvalZerostack_start: 38*10465441SEvalZero.rept ISR_Stack_Size 39*10465441SEvalZero.byte 0 40*10465441SEvalZero.endr 41*10465441SEvalZerostack_top: 42*10465441SEvalZero 43*10465441SEvalZero.text 44*10465441SEvalZero/* reset entry */ 45*10465441SEvalZero.globl _reset 46*10465441SEvalZero_reset: 47*10465441SEvalZero bl rt_cpu_mmu_disable 48*10465441SEvalZero /* set the cpu to SVC32 mode and disable interrupt */ 49*10465441SEvalZero mrs r0, cpsr 50*10465441SEvalZero bic r0, r0, #0x1f 51*10465441SEvalZero orr r0, r0, #0x13 52*10465441SEvalZero msr cpsr_c, r0 53*10465441SEvalZero 54*10465441SEvalZero /* setup stack */ 55*10465441SEvalZero bl stack_setup 56*10465441SEvalZero 57*10465441SEvalZero /* clear .bss */ 58*10465441SEvalZero mov r0,#0 /* get a zero */ 59*10465441SEvalZero ldr r1,=__bss_start /* bss start */ 60*10465441SEvalZero ldr r2,=__bss_end /* bss end */ 61*10465441SEvalZero 62*10465441SEvalZerobss_loop: 63*10465441SEvalZero cmp r1,r2 /* check if data to clear */ 64*10465441SEvalZero strlo r0,[r1],#4 /* clear 4 bytes */ 65*10465441SEvalZero blo bss_loop /* loop until done */ 66*10465441SEvalZero 67*10465441SEvalZero /* call C++ constructors of global objects */ 68*10465441SEvalZero ldr r0, =__ctors_start__ 69*10465441SEvalZero ldr r1, =__ctors_end__ 70*10465441SEvalZero 71*10465441SEvalZeroctor_loop: 72*10465441SEvalZero cmp r0, r1 73*10465441SEvalZero beq ctor_end 74*10465441SEvalZero ldr r2, [r0], #4 75*10465441SEvalZero stmfd sp!, {r0-r1} 76*10465441SEvalZero mov lr, pc 77*10465441SEvalZero bx r2 78*10465441SEvalZero ldmfd sp!, {r0-r1} 79*10465441SEvalZero b ctor_loop 80*10465441SEvalZeroctor_end: 81*10465441SEvalZero 82*10465441SEvalZero /* start RT-Thread Kernel */ 83*10465441SEvalZero ldr pc, _rtthread_startup 84*10465441SEvalZero_rtthread_startup: 85*10465441SEvalZero .word rtthread_startup 86*10465441SEvalZero 87*10465441SEvalZerostack_setup: 88*10465441SEvalZero ldr r0, =stack_top 89*10465441SEvalZero 90*10465441SEvalZero @ Set the startup stack for svc 91*10465441SEvalZero mov sp, r0 92*10465441SEvalZero 93*10465441SEvalZero @ Enter Undefined Instruction Mode and set its Stack Pointer 94*10465441SEvalZero msr cpsr_c, #Mode_UND|I_Bit|F_Bit 95*10465441SEvalZero mov sp, r0 96*10465441SEvalZero sub r0, r0, #UND_Stack_Size 97*10465441SEvalZero 98*10465441SEvalZero @ Enter Abort Mode and set its Stack Pointer 99*10465441SEvalZero msr cpsr_c, #Mode_ABT|I_Bit|F_Bit 100*10465441SEvalZero mov sp, r0 101*10465441SEvalZero sub r0, r0, #ABT_Stack_Size 102*10465441SEvalZero 103*10465441SEvalZero @ Enter FIQ Mode and set its Stack Pointer 104*10465441SEvalZero msr cpsr_c, #Mode_FIQ|I_Bit|F_Bit 105*10465441SEvalZero mov sp, r0 106*10465441SEvalZero sub r0, r0, #RT_FIQ_STACK_PGSZ 107*10465441SEvalZero 108*10465441SEvalZero @ Enter IRQ Mode and set its Stack Pointer 109*10465441SEvalZero msr cpsr_c, #Mode_IRQ|I_Bit|F_Bit 110*10465441SEvalZero mov sp, r0 111*10465441SEvalZero sub r0, r0, #RT_IRQ_STACK_PGSZ 112*10465441SEvalZero 113*10465441SEvalZero /* come back to SVC mode */ 114*10465441SEvalZero msr cpsr_c, #Mode_SVC|I_Bit|F_Bit 115*10465441SEvalZero bx lr 116*10465441SEvalZero 117*10465441SEvalZero/* exception handlers: undef, swi, padt, dabt, resv, irq, fiq */ 118*10465441SEvalZero.section .text.isr, "ax" 119*10465441SEvalZero .align 5 120*10465441SEvalZero.globl vector_fiq 121*10465441SEvalZerovector_fiq: 122*10465441SEvalZero stmfd sp!,{r0-r7,lr} 123*10465441SEvalZero bl rt_hw_trap_fiq 124*10465441SEvalZero ldmfd sp!,{r0-r7,lr} 125*10465441SEvalZero subs pc, lr, #4 126*10465441SEvalZero 127*10465441SEvalZero.globl rt_interrupt_enter 128*10465441SEvalZero.globl rt_interrupt_leave 129*10465441SEvalZero.globl rt_thread_switch_interrupt_flag 130*10465441SEvalZero.globl rt_interrupt_from_thread 131*10465441SEvalZero.globl rt_interrupt_to_thread 132*10465441SEvalZero 133*10465441SEvalZero.globl rt_current_thread 134*10465441SEvalZero.globl vmm_thread 135*10465441SEvalZero.globl vmm_virq_check 136*10465441SEvalZero 137*10465441SEvalZero .align 5 138*10465441SEvalZero.globl vector_irq 139*10465441SEvalZerovector_irq: 140*10465441SEvalZero stmfd sp!, {r0-r12,lr} 141*10465441SEvalZero 142*10465441SEvalZero bl rt_interrupt_enter 143*10465441SEvalZero bl rt_hw_trap_irq 144*10465441SEvalZero bl rt_interrupt_leave 145*10465441SEvalZero 146*10465441SEvalZero @ if rt_thread_switch_interrupt_flag set, jump to 147*10465441SEvalZero @ rt_hw_context_switch_interrupt_do and don't return 148*10465441SEvalZero ldr r0, =rt_thread_switch_interrupt_flag 149*10465441SEvalZero ldr r1, [r0] 150*10465441SEvalZero cmp r1, #1 151*10465441SEvalZero beq rt_hw_context_switch_interrupt_do 152*10465441SEvalZero 153*10465441SEvalZero ldmfd sp!, {r0-r12,lr} 154*10465441SEvalZero subs pc, lr, #4 155*10465441SEvalZero 156*10465441SEvalZerort_hw_context_switch_interrupt_do: 157*10465441SEvalZero mov r1, #0 @ clear flag 158*10465441SEvalZero str r1, [r0] 159*10465441SEvalZero 160*10465441SEvalZero mov r1, sp @ r1 point to {r0-r3} in stack 161*10465441SEvalZero add sp, sp, #4*4 162*10465441SEvalZero ldmfd sp!, {r4-r12,lr}@ reload saved registers 163*10465441SEvalZero mrs r0, spsr @ get cpsr of interrupt thread 164*10465441SEvalZero sub r2, lr, #4 @ save old task's pc to r2 165*10465441SEvalZero 166*10465441SEvalZero @ Switch to SVC mode with no interrupt. If the usr mode guest is 167*10465441SEvalZero @ interrupted, this will just switch to the stack of kernel space. 168*10465441SEvalZero @ save the registers in kernel space won't trigger data abort. 169*10465441SEvalZero msr cpsr_c, #I_Bit|F_Bit|Mode_SVC 170*10465441SEvalZero 171*10465441SEvalZero stmfd sp!, {r2} @ push old task's pc 172*10465441SEvalZero stmfd sp!, {r4-r12,lr}@ push old task's lr,r12-r4 173*10465441SEvalZero ldmfd r1, {r1-r4} @ restore r0-r3 of the interrupt thread 174*10465441SEvalZero stmfd sp!, {r1-r4} @ push old task's r0-r3 175*10465441SEvalZero stmfd sp!, {r0} @ push old task's cpsr 176*10465441SEvalZero 177*10465441SEvalZero ldr r4, =rt_interrupt_from_thread 178*10465441SEvalZero ldr r5, [r4] 179*10465441SEvalZero str sp, [r5] @ store sp in preempted tasks's TCB 180*10465441SEvalZero 181*10465441SEvalZero ldr r6, =rt_interrupt_to_thread 182*10465441SEvalZero ldr r6, [r6] 183*10465441SEvalZero ldr sp, [r6] @ get new task's stack pointer 184*10465441SEvalZero 185*10465441SEvalZero ldmfd sp!, {r4} @ pop new task's cpsr to spsr 186*10465441SEvalZero msr spsr_cxsf, r4 187*10465441SEvalZero 188*10465441SEvalZero ldmfd sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr 189*10465441SEvalZero 190*10465441SEvalZero.macro push_svc_reg 191*10465441SEvalZero sub sp, sp, #17 * 4 @/* Sizeof(struct rt_hw_exp_stack) */ 192*10465441SEvalZero stmia sp, {r0 - r12} @/* Calling r0-r12 */ 193*10465441SEvalZero mov r0, sp 194*10465441SEvalZero mrs r6, spsr @/* Save CPSR */ 195*10465441SEvalZero str lr, [r0, #15*4] @/* Push PC */ 196*10465441SEvalZero str r6, [r0, #16*4] @/* Push CPSR */ 197*10465441SEvalZero cps #Mode_SVC 198*10465441SEvalZero str sp, [r0, #13*4] @/* Save calling SP */ 199*10465441SEvalZero str lr, [r0, #14*4] @/* Save calling PC */ 200*10465441SEvalZero.endm 201*10465441SEvalZero 202*10465441SEvalZero .align 5 203*10465441SEvalZero .globl vector_swi 204*10465441SEvalZerovector_swi: 205*10465441SEvalZero push_svc_reg 206*10465441SEvalZero bl rt_hw_trap_swi 207*10465441SEvalZero b . 208*10465441SEvalZero 209*10465441SEvalZero .align 5 210*10465441SEvalZero .globl vector_undef 211*10465441SEvalZerovector_undef: 212*10465441SEvalZero push_svc_reg 213*10465441SEvalZero bl rt_hw_trap_undef 214*10465441SEvalZero b . 215*10465441SEvalZero 216*10465441SEvalZero .align 5 217*10465441SEvalZero .globl vector_pabt 218*10465441SEvalZerovector_pabt: 219*10465441SEvalZero push_svc_reg 220*10465441SEvalZero bl rt_hw_trap_pabt 221*10465441SEvalZero b . 222*10465441SEvalZero 223*10465441SEvalZero .align 5 224*10465441SEvalZero .globl vector_dabt 225*10465441SEvalZerovector_dabt: 226*10465441SEvalZero push_svc_reg 227*10465441SEvalZero bl rt_hw_trap_dabt 228*10465441SEvalZero b . 229*10465441SEvalZero 230*10465441SEvalZero .align 5 231*10465441SEvalZero .globl vector_resv 232*10465441SEvalZerovector_resv: 233*10465441SEvalZero push_svc_reg 234*10465441SEvalZero bl rt_hw_trap_resv 235*10465441SEvalZero b . 236