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