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