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