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