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 * 2008-12-11 XuXinming first version 9*10465441SEvalZero * 2011-03-17 Bernard update to 0.4.x 10*10465441SEvalZero */ 11*10465441SEvalZero 12*10465441SEvalZero#define WDMOD (0xE0000000 + 0x00) 13*10465441SEvalZero#define VICIntEnClr (0xFFFFF000 + 0x014) 14*10465441SEvalZero#define VICVectAddr (0xFFFFF000 + 0xF00) 15*10465441SEvalZero#define VICIntSelect (0xFFFFF000 + 0x00C) 16*10465441SEvalZero#define PLLCFG (0xE01FC000 + 0x084) 17*10465441SEvalZero#define PLLCON (0xE01FC000 + 0x080) 18*10465441SEvalZero#define PLLFEED (0xE01FC000 + 0x08C) 19*10465441SEvalZero#define PLLSTAT (0xE01FC000 + 0x088) 20*10465441SEvalZero#define CCLKCFG (0xE01FC000 + 0x104) 21*10465441SEvalZero#define MEMMAP (0xE01FC000 + 0x040) 22*10465441SEvalZero#define SCS (0xE01FC000 + 0x1A0) 23*10465441SEvalZero#define CLKSRCSEL (0xE01FC000 + 0x10C) 24*10465441SEvalZero#define MAMCR (0xE01FC000 + 0x000) 25*10465441SEvalZero#define MAMTIM (0xE01FC000 + 0x004) 26*10465441SEvalZero 27*10465441SEvalZero/* stack memory */ 28*10465441SEvalZero.section .bss.noinit 29*10465441SEvalZero.equ IRQ_STACK_SIZE, 0x00000200 30*10465441SEvalZero.equ FIQ_STACK_SIZE, 0x00000100 31*10465441SEvalZero.equ UDF_STACK_SIZE, 0x00000004 32*10465441SEvalZero.equ ABT_STACK_SIZE, 0x00000004 33*10465441SEvalZero.equ SVC_STACK_SIZE, 0x00000200 34*10465441SEvalZero 35*10465441SEvalZero.space IRQ_STACK_SIZE 36*10465441SEvalZeroIRQ_STACK: 37*10465441SEvalZero 38*10465441SEvalZero.space FIQ_STACK_SIZE 39*10465441SEvalZeroFIQ_STACK: 40*10465441SEvalZero 41*10465441SEvalZero.space UDF_STACK_SIZE 42*10465441SEvalZeroUDF_STACK: 43*10465441SEvalZero 44*10465441SEvalZero.space ABT_STACK_SIZE 45*10465441SEvalZeroABT_STACK: 46*10465441SEvalZero 47*10465441SEvalZero.space SVC_STACK_SIZE 48*10465441SEvalZeroSVC_STACK: 49*10465441SEvalZero 50*10465441SEvalZero.section .init, "ax" 51*10465441SEvalZero.code 32 52*10465441SEvalZero.globl _start 53*10465441SEvalZero_start: 54*10465441SEvalZero b reset 55*10465441SEvalZero ldr pc, _vector_undef 56*10465441SEvalZero ldr pc, _vector_swi 57*10465441SEvalZero ldr pc, _vector_pabt 58*10465441SEvalZero ldr pc, _vector_dabt 59*10465441SEvalZero ldr pc, _vector_resv 60*10465441SEvalZero ldr pc, _vector_irq 61*10465441SEvalZero ldr pc, _vector_fiq 62*10465441SEvalZero 63*10465441SEvalZero_vector_undef: .word vector_undef 64*10465441SEvalZero_vector_swi: .word vector_swi 65*10465441SEvalZero_vector_pabt: .word vector_pabt 66*10465441SEvalZero_vector_dabt: .word vector_dabt 67*10465441SEvalZero_vector_resv: .word vector_resv 68*10465441SEvalZero_vector_irq: .word vector_irq 69*10465441SEvalZero_vector_fiq: .word vector_fiq 70*10465441SEvalZero 71*10465441SEvalZero.balignl 16,0xdeadbeef 72*10465441SEvalZero 73*10465441SEvalZero/* 74*10465441SEvalZero * rtthread kernel start and end 75*10465441SEvalZero * which are defined in linker script 76*10465441SEvalZero */ 77*10465441SEvalZero.globl _rtthread_start 78*10465441SEvalZero_rtthread_start: 79*10465441SEvalZero .word _start 80*10465441SEvalZero 81*10465441SEvalZero.globl _rtthread_end 82*10465441SEvalZero_rtthread_end: 83*10465441SEvalZero .word _end 84*10465441SEvalZero 85*10465441SEvalZero/* 86*10465441SEvalZero * rtthread bss start and end which are defined in linker script 87*10465441SEvalZero */ 88*10465441SEvalZero.globl _bss_start 89*10465441SEvalZero_bss_start: 90*10465441SEvalZero .word __bss_start 91*10465441SEvalZero 92*10465441SEvalZero.globl _bss_end 93*10465441SEvalZero_bss_end: 94*10465441SEvalZero .word __bss_end 95*10465441SEvalZero 96*10465441SEvalZero.text 97*10465441SEvalZero.code 32 98*10465441SEvalZero 99*10465441SEvalZero/* the system entry */ 100*10465441SEvalZeroreset: 101*10465441SEvalZero /* enter svc mode */ 102*10465441SEvalZero msr cpsr_c, #SVCMODE|NOINT 103*10465441SEvalZero 104*10465441SEvalZero /*watch dog disable */ 105*10465441SEvalZero ldr r0,=WDMOD 106*10465441SEvalZero ldr r1,=0x0 107*10465441SEvalZero str r1,[r0] 108*10465441SEvalZero 109*10465441SEvalZero /* all interrupt disable */ 110*10465441SEvalZero ldr r0,=VICIntEnClr 111*10465441SEvalZero ldr r1,=0xffffffff 112*10465441SEvalZero str r1,[r0] 113*10465441SEvalZero 114*10465441SEvalZero ldr r1, =VICVectAddr 115*10465441SEvalZero ldr r0, =0x00 116*10465441SEvalZero str r0, [r1] 117*10465441SEvalZero 118*10465441SEvalZero ldr r1, =VICIntSelect 119*10465441SEvalZero ldr r0, =0x00 120*10465441SEvalZero str r0, [r1] 121*10465441SEvalZero 122*10465441SEvalZero /* setup stack */ 123*10465441SEvalZero bl stack_setup 124*10465441SEvalZero 125*10465441SEvalZero /* copy .data to SRAM */ 126*10465441SEvalZero ldr r1, =_sidata /* .data start in image */ 127*10465441SEvalZero ldr r2, =_edata /* .data end in image */ 128*10465441SEvalZero ldr r3, =_sdata /* sram data start */ 129*10465441SEvalZerodata_loop: 130*10465441SEvalZero ldr r0, [r1, #0] 131*10465441SEvalZero str r0, [r3] 132*10465441SEvalZero 133*10465441SEvalZero add r1, r1, #4 134*10465441SEvalZero add r3, r3, #4 135*10465441SEvalZero 136*10465441SEvalZero cmp r3, r2 /* check if data to clear */ 137*10465441SEvalZero blo data_loop /* loop until done */ 138*10465441SEvalZero 139*10465441SEvalZero /* clear .bss */ 140*10465441SEvalZero mov r0,#0 /* get a zero */ 141*10465441SEvalZero ldr r1,=__bss_start /* bss start */ 142*10465441SEvalZero ldr r2,=__bss_end /* bss end */ 143*10465441SEvalZero 144*10465441SEvalZerobss_loop: 145*10465441SEvalZero cmp r1,r2 /* check if data to clear */ 146*10465441SEvalZero strlo r0,[r1],#4 /* clear 4 bytes */ 147*10465441SEvalZero blo bss_loop /* loop until done */ 148*10465441SEvalZero 149*10465441SEvalZero /* call C++ constructors of global objects */ 150*10465441SEvalZero ldr r0, =__ctors_start__ 151*10465441SEvalZero ldr r1, =__ctors_end__ 152*10465441SEvalZero 153*10465441SEvalZeroctor_loop: 154*10465441SEvalZero cmp r0, r1 155*10465441SEvalZero beq ctor_end 156*10465441SEvalZero ldr r2, [r0], #4 157*10465441SEvalZero stmfd sp!, {r0-r1} 158*10465441SEvalZero mov lr, pc 159*10465441SEvalZero bx r2 160*10465441SEvalZero ldmfd sp!, {r0-r1} 161*10465441SEvalZero b ctor_loop 162*10465441SEvalZeroctor_end: 163*10465441SEvalZero 164*10465441SEvalZero /* start RT-Thread Kernel */ 165*10465441SEvalZero ldr pc, _rtthread_startup 166*10465441SEvalZero 167*10465441SEvalZero_rtthread_startup: 168*10465441SEvalZero .word rtthread_startup 169*10465441SEvalZero 170*10465441SEvalZero .equ USERMODE, 0x10 171*10465441SEvalZero .equ FIQMODE, 0x11 172*10465441SEvalZero .equ IRQMODE, 0x12 173*10465441SEvalZero .equ SVCMODE, 0x13 174*10465441SEvalZero .equ ABORTMODE, 0x17 175*10465441SEvalZero .equ UNDEFMODE, 0x1b 176*10465441SEvalZero .equ MODEMASK, 0x1f 177*10465441SEvalZero .equ NOINT, 0xc0 178*10465441SEvalZero 179*10465441SEvalZero/* exception handlers */ 180*10465441SEvalZerovector_undef: bl rt_hw_trap_udef 181*10465441SEvalZerovector_swi: bl rt_hw_trap_swi 182*10465441SEvalZerovector_pabt: bl rt_hw_trap_pabt 183*10465441SEvalZerovector_dabt: bl rt_hw_trap_dabt 184*10465441SEvalZerovector_resv: bl rt_hw_trap_resv 185*10465441SEvalZero 186*10465441SEvalZero.globl rt_interrupt_enter 187*10465441SEvalZero.globl rt_interrupt_leave 188*10465441SEvalZero.globl rt_thread_switch_interrupt_flag 189*10465441SEvalZero.globl rt_interrupt_from_thread 190*10465441SEvalZero.globl rt_interrupt_to_thread 191*10465441SEvalZerovector_irq: 192*10465441SEvalZero stmfd sp!, {r0-r12,lr} 193*10465441SEvalZero bl rt_interrupt_enter 194*10465441SEvalZero bl rt_hw_trap_irq 195*10465441SEvalZero bl rt_interrupt_leave 196*10465441SEvalZero 197*10465441SEvalZero /* if rt_thread_switch_interrupt_flag set, 198*10465441SEvalZero * jump to _interrupt_thread_switch and don't return 199*10465441SEvalZero */ 200*10465441SEvalZero ldr r0, =rt_thread_switch_interrupt_flag 201*10465441SEvalZero ldr r1, [r0] 202*10465441SEvalZero cmp r1, #1 203*10465441SEvalZero beq _interrupt_thread_switch 204*10465441SEvalZero 205*10465441SEvalZero ldmfd sp!, {r0-r12,lr} 206*10465441SEvalZero subs pc, lr, #4 207*10465441SEvalZero 208*10465441SEvalZero .align 5 209*10465441SEvalZerovector_fiq: 210*10465441SEvalZero stmfd sp!,{r0-r7,lr} 211*10465441SEvalZero bl rt_hw_trap_fiq 212*10465441SEvalZero ldmfd sp!,{r0-r7,lr} 213*10465441SEvalZero subs pc,lr,#4 214*10465441SEvalZero 215*10465441SEvalZero_interrupt_thread_switch: 216*10465441SEvalZero mov r1, #0 /* clear rt_thread_switch_interrupt_flag */ 217*10465441SEvalZero str r1, [r0] 218*10465441SEvalZero 219*10465441SEvalZero ldmfd sp!, {r0-r12,lr} /* reload saved registers */ 220*10465441SEvalZero stmfd sp!, {r0-r3} /* save r0-r3 */ 221*10465441SEvalZero mov r1, sp 222*10465441SEvalZero add sp, sp, #16 /* restore sp */ 223*10465441SEvalZero sub r2, lr, #4 /* save old task's pc to r2 */ 224*10465441SEvalZero 225*10465441SEvalZero mrs r3, spsr /* disable interrupt */ 226*10465441SEvalZero orr r0, r3, #NOINT 227*10465441SEvalZero msr spsr_c, r0 228*10465441SEvalZero 229*10465441SEvalZero ldr r0, =.+8 /* switch to interrupted task's stack */ 230*10465441SEvalZero movs pc, r0 231*10465441SEvalZero 232*10465441SEvalZero stmfd sp!, {r2} /* push old task's pc */ 233*10465441SEvalZero stmfd sp!, {r4-r12,lr} /* push old task's lr,r12-r4 */ 234*10465441SEvalZero mov r4, r1 /* Special optimised code below */ 235*10465441SEvalZero mov r5, r3 236*10465441SEvalZero ldmfd r4!, {r0-r3} 237*10465441SEvalZero stmfd sp!, {r0-r3} /* push old task's r3-r0 */ 238*10465441SEvalZero stmfd sp!, {r5} /* push old task's psr */ 239*10465441SEvalZero mrs r4, spsr 240*10465441SEvalZero stmfd sp!, {r4} /* push old task's spsr */ 241*10465441SEvalZero 242*10465441SEvalZero ldr r4, =rt_interrupt_from_thread 243*10465441SEvalZero ldr r5, [r4] 244*10465441SEvalZero str sp, [r5] /* store sp in preempted tasks's TCB */ 245*10465441SEvalZero 246*10465441SEvalZero ldr r6, =rt_interrupt_to_thread 247*10465441SEvalZero ldr r6, [r6] 248*10465441SEvalZero ldr sp, [r6] /* get new task's stack pointer */ 249*10465441SEvalZero 250*10465441SEvalZero ldmfd sp!, {r4} /* pop new task's spsr */ 251*10465441SEvalZero msr SPSR_cxsf, r4 252*10465441SEvalZero ldmfd sp!, {r4} /* pop new task's psr */ 253*10465441SEvalZero msr CPSR_cxsf, r4 254*10465441SEvalZero 255*10465441SEvalZero ldmfd sp!, {r0-r12,lr,pc} /* pop new task's r0-r12,lr & pc */ 256*10465441SEvalZero 257*10465441SEvalZerostack_setup: 258*10465441SEvalZero mrs r0, cpsr 259*10465441SEvalZero bic r0, r0, #MODEMASK 260*10465441SEvalZero orr r1, r0, #UNDEFMODE|NOINT 261*10465441SEvalZero msr cpsr_cxsf, r1 /* undef mode */ 262*10465441SEvalZero ldr sp, =UDF_STACK 263*10465441SEvalZero 264*10465441SEvalZero orr r1,r0,#ABORTMODE|NOINT 265*10465441SEvalZero msr cpsr_cxsf,r1 /* abort mode */ 266*10465441SEvalZero ldr sp, =ABT_STACK 267*10465441SEvalZero 268*10465441SEvalZero orr r1,r0,#IRQMODE|NOINT 269*10465441SEvalZero msr cpsr_cxsf,r1 /* IRQ mode */ 270*10465441SEvalZero ldr sp, =IRQ_STACK 271*10465441SEvalZero 272*10465441SEvalZero orr r1,r0,#FIQMODE|NOINT 273*10465441SEvalZero msr cpsr_cxsf,r1 /* FIQ mode */ 274*10465441SEvalZero ldr sp, =FIQ_STACK 275*10465441SEvalZero 276*10465441SEvalZero bic r0,r0,#MODEMASK 277*10465441SEvalZero orr r1,r0,#SVCMODE|NOINT 278*10465441SEvalZero msr cpsr_cxsf,r1 /* SVC mode */ 279*10465441SEvalZero ldr sp, =SVC_STACK 280*10465441SEvalZero 281*10465441SEvalZero /* USER mode is not initialized. */ 282*10465441SEvalZero mov pc,lr /* The LR register may be not valid for the mode changes.*/ 283