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 */ 9*10465441SEvalZero .extern main /* 引入外部C入口 */ 10*10465441SEvalZero 11*10465441SEvalZero .extern rt_interrupt_enter 12*10465441SEvalZero .extern rt_interrupt_leave 13*10465441SEvalZero .extern rt_thread_switch_interrupt_flag 14*10465441SEvalZero .extern rt_interrupt_from_thread 15*10465441SEvalZero .extern rt_interrupt_to_thread 16*10465441SEvalZero .extern rt_hw_trap_irq 17*10465441SEvalZero 18*10465441SEvalZero .global start 19*10465441SEvalZero .global endless_loop 20*10465441SEvalZero .global rt_hw_context_switch_interrupt_do 21*10465441SEvalZero 22*10465441SEvalZero /* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs */ 23*10465441SEvalZero .set MODE_USR, 0x10 /* User Mode */ 24*10465441SEvalZero .set MODE_FIQ, 0x11 /* FIQ Mode */ 25*10465441SEvalZero .set MODE_IRQ, 0x12 /* IRQ Mode */ 26*10465441SEvalZero .set MODE_SVC, 0x13 /* Supervisor Mode */ 27*10465441SEvalZero .set MODE_ABT, 0x17 /* Abort Mode */ 28*10465441SEvalZero .set MODE_UND, 0x1B /* Undefined Mode */ 29*10465441SEvalZero .set MODE_SYS, 0x1F /* System Mode */ 30*10465441SEvalZero 31*10465441SEvalZero .equ I_BIT, 0x80 /* when I bit is set, IRQ is disabled */ 32*10465441SEvalZero .equ F_BIT, 0x40 /* when F bit is set, FIQ is disabled */ 33*10465441SEvalZero .equ I_Bit, 0x80 /* when I bit is set, IRQ is disabled */ 34*10465441SEvalZero .equ F_Bit, 0x40 /* when F bit is set, FIQ is disabled */ 35*10465441SEvalZero 36*10465441SEvalZero /* VPBDIV definitions*/ 37*10465441SEvalZero .equ VPBDIV, 0xE01FC100 38*10465441SEvalZero .set VPBDIV_VALUE, 0x00000000 39*10465441SEvalZero 40*10465441SEvalZero /* Phase Locked Loop (PLL) definitions*/ 41*10465441SEvalZero .equ PLL_BASE, 0xE01FC080 /* PLL Base Address */ 42*10465441SEvalZero .equ PLLCON_OFS, 0x00 /* PLL Control Offset */ 43*10465441SEvalZero .equ PLLCFG_OFS, 0x04 /* PLL Configuration Offset */ 44*10465441SEvalZero .equ PLLSTAT_OFS, 0x08 /* PLL Status Offset */ 45*10465441SEvalZero .equ PLLFEED_OFS, 0x0C /* PLL Feed Offset */ 46*10465441SEvalZero .equ PLLCON_PLLE, (1<<0) /* PLL Enable */ 47*10465441SEvalZero .equ PLLCON_PLLC, (1<<1) /* PLL Connect */ 48*10465441SEvalZero .equ PLLCFG_MSEL, (0x1F<<0) /* PLL Multiplier */ 49*10465441SEvalZero .equ PLLCFG_PSEL, (0x03<<5) /* PLL Divider */ 50*10465441SEvalZero .equ PLLSTAT_PLOCK, (1<<10) /* PLL Lock Status */ 51*10465441SEvalZero .equ PLLCFG_Val, 0x00000024 /* <o1.0..4> MSEL: PLL Multiplier Selection,<o1.5..6> PSEL: PLL Divider Selection */ 52*10465441SEvalZero 53*10465441SEvalZero .equ MEMMAP, 0xE01FC040 /*Memory Mapping Control*/ 54*10465441SEvalZero 55*10465441SEvalZero 56*10465441SEvalZero /* Memory Accelerator Module (MAM) definitions*/ 57*10465441SEvalZero .equ MAM_BASE, 0xE01FC000 58*10465441SEvalZero .equ MAMCR_OFS, 0x00 59*10465441SEvalZero .equ MAMTIM_OFS, 0x04 60*10465441SEvalZero .equ MAMCR_Val, 0x00000002 61*10465441SEvalZero .equ MAMTIM_Val, 0x00000004 62*10465441SEvalZero 63*10465441SEvalZero .equ VICIntEnClr, 0xFFFFF014 64*10465441SEvalZero .equ VICIntSelect, 0xFFFFF00C 65*10465441SEvalZero/************* 目标配置结束 *************/ 66*10465441SEvalZero 67*10465441SEvalZero 68*10465441SEvalZero/* Setup the operating mode & stack.*/ 69*10465441SEvalZero/* --------------------------------- */ 70*10465441SEvalZero .global _reset 71*10465441SEvalZero_reset: 72*10465441SEvalZero .code 32 73*10465441SEvalZero .align 0 74*10465441SEvalZero 75*10465441SEvalZero/************************* PLL_SETUP **********************************/ 76*10465441SEvalZero ldr r0, =PLL_BASE 77*10465441SEvalZero mov r1, #0xAA 78*10465441SEvalZero mov r2, #0x55 79*10465441SEvalZero 80*10465441SEvalZero/* Configure and Enable PLL */ 81*10465441SEvalZero mov r3, #PLLCFG_Val 82*10465441SEvalZero str r3, [r0, #PLLCFG_OFS] 83*10465441SEvalZero mov r3, #PLLCON_PLLE 84*10465441SEvalZero str r3, [r0, #PLLCON_OFS] 85*10465441SEvalZero str r1, [r0, #PLLFEED_OFS] 86*10465441SEvalZero str r2, [r0, #PLLFEED_OFS] 87*10465441SEvalZero 88*10465441SEvalZero/* Wait until PLL Locked */ 89*10465441SEvalZeroPLL_Locked_loop: 90*10465441SEvalZero ldr r3, [r0, #PLLSTAT_OFS] 91*10465441SEvalZero ands r3, r3, #PLLSTAT_PLOCK 92*10465441SEvalZero beq PLL_Locked_loop 93*10465441SEvalZero 94*10465441SEvalZero/* Switch to PLL Clock */ 95*10465441SEvalZero mov r3, #(PLLCON_PLLE|PLLCON_PLLC) 96*10465441SEvalZero str r3, [r0, #PLLCON_OFS] 97*10465441SEvalZero str r1, [r0, #PLLFEED_OFS] 98*10465441SEvalZero str R2, [r0, #PLLFEED_OFS] 99*10465441SEvalZero/************************* PLL_SETUP **********************************/ 100*10465441SEvalZero 101*10465441SEvalZero/************************ Setup VPBDIV ********************************/ 102*10465441SEvalZero ldr r0, =VPBDIV 103*10465441SEvalZero ldr r1, =VPBDIV_VALUE 104*10465441SEvalZero str r1, [r0] 105*10465441SEvalZero/************************ Setup VPBDIV ********************************/ 106*10465441SEvalZero 107*10465441SEvalZero/************** Setup MAM **************/ 108*10465441SEvalZero ldr r0, =MAM_BASE 109*10465441SEvalZero mov r1, #MAMTIM_Val 110*10465441SEvalZero str r1, [r0, #MAMTIM_OFS] 111*10465441SEvalZero mov r1, #MAMCR_Val 112*10465441SEvalZero str r1, [r0, #MAMCR_OFS] 113*10465441SEvalZero/************** Setup MAM **************/ 114*10465441SEvalZero 115*10465441SEvalZero/************************ setup stack *********************************/ 116*10465441SEvalZero ldr r0, .undefined_stack_top 117*10465441SEvalZero sub r0, r0, #4 118*10465441SEvalZero msr CPSR_c, #MODE_UND|I_BIT|F_BIT /* Undefined Instruction Mode */ 119*10465441SEvalZero mov sp, r0 120*10465441SEvalZero 121*10465441SEvalZero ldr r0, .abort_stack_top 122*10465441SEvalZero sub r0, r0, #4 123*10465441SEvalZero msr CPSR_c, #MODE_ABT|I_BIT|F_BIT /* Abort Mode */ 124*10465441SEvalZero mov sp, r0 125*10465441SEvalZero 126*10465441SEvalZero ldr r0, .fiq_stack_top 127*10465441SEvalZero sub r0, r0, #4 128*10465441SEvalZero msr CPSR_c, #MODE_FIQ|I_BIT|F_BIT /* FIQ Mode */ 129*10465441SEvalZero mov sp, r0 130*10465441SEvalZero 131*10465441SEvalZero ldr r0, .irq_stack_top 132*10465441SEvalZero sub r0, r0, #4 133*10465441SEvalZero msr CPSR_c, #MODE_IRQ|I_BIT|F_BIT /* IRQ Mode */ 134*10465441SEvalZero mov sp, r0 135*10465441SEvalZero 136*10465441SEvalZero ldr r0, .svc_stack_top 137*10465441SEvalZero sub r0, r0, #4 138*10465441SEvalZero msr CPSR_c, #MODE_SVC|I_BIT|F_BIT /* Supervisor Mode */ 139*10465441SEvalZero mov sp, r0 140*10465441SEvalZero/************************ setup stack ********************************/ 141*10465441SEvalZero 142*10465441SEvalZero /* copy .data to SRAM */ 143*10465441SEvalZero ldr r1, =_sidata /* .data start in image */ 144*10465441SEvalZero ldr r2, =_edata /* .data end in image */ 145*10465441SEvalZero ldr r3, =_sdata /* sram data start */ 146*10465441SEvalZerodata_loop: 147*10465441SEvalZero ldr r0, [r1, #0] 148*10465441SEvalZero str r0, [r3] 149*10465441SEvalZero 150*10465441SEvalZero add r1, r1, #4 151*10465441SEvalZero add r3, r3, #4 152*10465441SEvalZero 153*10465441SEvalZero cmp r3, r2 /* check if data to clear */ 154*10465441SEvalZero blo data_loop /* loop until done */ 155*10465441SEvalZero 156*10465441SEvalZero /* clear .bss */ 157*10465441SEvalZero mov r0,#0 /* get a zero */ 158*10465441SEvalZero ldr r1,=__bss_start /* bss start */ 159*10465441SEvalZero ldr r2,=__bss_end /* bss end */ 160*10465441SEvalZero 161*10465441SEvalZerobss_loop: 162*10465441SEvalZero cmp r1,r2 /* check if data to clear */ 163*10465441SEvalZero strlo r0,[r1],#4 /* clear 4 bytes */ 164*10465441SEvalZero blo bss_loop /* loop until done */ 165*10465441SEvalZero 166*10465441SEvalZero 167*10465441SEvalZero /* call C++ constructors of global objects */ 168*10465441SEvalZero ldr r0, =__ctors_start__ 169*10465441SEvalZero ldr r1, =__ctors_end__ 170*10465441SEvalZero 171*10465441SEvalZeroctor_loop: 172*10465441SEvalZero cmp r0, r1 173*10465441SEvalZero beq ctor_end 174*10465441SEvalZero ldr r2, [r0], #4 175*10465441SEvalZero stmfd sp!, {r0-r1} 176*10465441SEvalZero mov lr, pc 177*10465441SEvalZero bx r2 178*10465441SEvalZero ldmfd sp!, {r0-r1} 179*10465441SEvalZero b ctor_loop 180*10465441SEvalZeroctor_end: 181*10465441SEvalZero 182*10465441SEvalZero /* enter C code */ 183*10465441SEvalZero bl main 184*10465441SEvalZero 185*10465441SEvalZero .align 0 186*10465441SEvalZero .undefined_stack_top: 187*10465441SEvalZero .word _undefined_stack_top 188*10465441SEvalZero .abort_stack_top: 189*10465441SEvalZero .word _abort_stack_top 190*10465441SEvalZero .fiq_stack_top: 191*10465441SEvalZero .word _fiq_stack_top 192*10465441SEvalZero .irq_stack_top: 193*10465441SEvalZero .word _irq_stack_top 194*10465441SEvalZero .svc_stack_top: 195*10465441SEvalZero .word _svc_stack_top 196*10465441SEvalZero/*********************** END Clear BSS ******************************/ 197*10465441SEvalZero 198*10465441SEvalZero.section .init,"ax" 199*10465441SEvalZero.code 32 200*10465441SEvalZero.align 0 201*10465441SEvalZero.globl _start 202*10465441SEvalZero_start: 203*10465441SEvalZero 204*10465441SEvalZero ldr pc, __start /* reset - _start */ 205*10465441SEvalZero ldr pc, _undf /* undefined - _undf */ 206*10465441SEvalZero ldr pc, _swi /* SWI - _swi */ 207*10465441SEvalZero ldr pc, _pabt /* program abort - _pabt */ 208*10465441SEvalZero ldr pc, _dabt /* data abort - _dabt */ 209*10465441SEvalZero .word 0xB8A06F58 /* reserved */ 210*10465441SEvalZero ldr pc, __IRQ_Handler /* IRQ - read the VIC */ 211*10465441SEvalZero ldr pc, _fiq /* FIQ - _fiq */ 212*10465441SEvalZero 213*10465441SEvalZero__start:.word _reset 214*10465441SEvalZero_undf: .word __undf /* undefined */ 215*10465441SEvalZero_swi: .word __swi /* SWI */ 216*10465441SEvalZero_pabt: .word __pabt /* program abort */ 217*10465441SEvalZero_dabt: .word __dabt /* data abort */ 218*10465441SEvalZerotemp1: .word 0 219*10465441SEvalZero__IRQ_Handler: .word IRQ_Handler 220*10465441SEvalZero_fiq: .word __fiq /* FIQ */ 221*10465441SEvalZero 222*10465441SEvalZero__undf: b . /* undefined */ 223*10465441SEvalZero__swi : b . 224*10465441SEvalZero__pabt: b . /* program abort */ 225*10465441SEvalZero__dabt: b . /* data abort */ 226*10465441SEvalZero__fiq : b . /* FIQ */ 227*10465441SEvalZero 228*10465441SEvalZero/* IRQ入口 */ 229*10465441SEvalZeroIRQ_Handler : 230*10465441SEvalZero stmfd sp!, {r0-r12,lr} /* 对R0 – R12,LR寄存器压栈 */ 231*10465441SEvalZero bl rt_interrupt_enter /* 通知RT-Thread进入中断模式 */ 232*10465441SEvalZero bl rt_hw_trap_irq /* 相应中断服务例程处理 */ 233*10465441SEvalZero bl rt_interrupt_leave /* ; 通知RT-Thread要离开中断模式 */ 234*10465441SEvalZero 235*10465441SEvalZero /* 如果设置了rt_thread_switch_interrupt_flag,进行中断中的线程上下文处理 */ 236*10465441SEvalZero ldr r0, =rt_thread_switch_interrupt_flag 237*10465441SEvalZero ldr r1, [r0] 238*10465441SEvalZero cmp r1, #1 239*10465441SEvalZero beq rt_hw_context_switch_interrupt_do /* 中断中切换发生 */ 240*10465441SEvalZero /* 如果跳转了,将不会回来 */ 241*10465441SEvalZero ldmfd sp!, {r0-r12,lr} /* 恢复栈 */ 242*10465441SEvalZero subs pc, lr, #4 /* 从IRQ中返回 */ 243*10465441SEvalZero 244*10465441SEvalZero/* 245*10465441SEvalZero* void rt_hw_context_switch_interrupt_do(rt_base_t flag) 246*10465441SEvalZero* 中断结束后的上下文切换 247*10465441SEvalZero*/ 248*10465441SEvalZerort_hw_context_switch_interrupt_do: 249*10465441SEvalZero mov r1, #0 /* clear flag */ 250*10465441SEvalZero /* 清楚中断中切换标志 */ 251*10465441SEvalZero str r1, [r0] /* */ 252*10465441SEvalZero 253*10465441SEvalZero ldmfd sp!, {r0-r12,lr}/* reload saved registers */ 254*10465441SEvalZero /* 先恢复被中断线程的上下文 */ 255*10465441SEvalZero stmfd sp!, {r0-r3} /* save r0-r3 */ 256*10465441SEvalZero /* 对R0 – R3压栈,因为后面会用到 */ 257*10465441SEvalZero mov r1, sp /* 把此处的栈值保存到R1 */ 258*10465441SEvalZero add sp, sp, #16 /* restore sp */ 259*10465441SEvalZero /* 恢复IRQ的栈,后面会跳出IRQ模式 */ 260*10465441SEvalZero sub r2, lr, #4 /* save old task's pc to r2 */ 261*10465441SEvalZero /* 保存切换出线程的PC到R2 */ 262*10465441SEvalZero 263*10465441SEvalZero mrs r3, spsr /* disable interrupt 保存中断前的CPSR到R3寄存器 */ 264*10465441SEvalZero /* 获得SPSR寄存器值 */ 265*10465441SEvalZero orr r0, r3, #I_BIT|F_BIT 266*10465441SEvalZero msr spsr_c, r0 /* 关闭SPSR中的IRQ/FIQ中断 */ 267*10465441SEvalZero 268*10465441SEvalZero ldr r0, =.+8 /* 把当前地址+8载入到R0寄存器中 switch to interrupted task's stack */ 269*10465441SEvalZero movs pc, r0 /* 退出IRQ模式,由于SPSR被设置成关中断模式 */ 270*10465441SEvalZero /* 所以从IRQ返回后,中断并没有打开 271*10465441SEvalZero ; R0寄存器中的位置实际就是下一条指令, 272*10465441SEvalZero ; 即PC继续往下走 273*10465441SEvalZero ; 此时 274*10465441SEvalZero ; 模式已经换成中断前的SVC模式, 275*10465441SEvalZero ; SP寄存器也是SVC模式下的栈寄存器 276*10465441SEvalZero ; R1保存IRQ模式下的栈指针 277*10465441SEvalZero ; R2保存切换出线程的PC 278*10465441SEvalZero ; R3保存切换出线程的CPSR */ 279*10465441SEvalZero stmfd sp!, {r2} /* push old task's pc */ 280*10465441SEvalZero /* 保存切换出任务的PC */ 281*10465441SEvalZero stmfd sp!, {r4-r12,lr}/* push old task's lr,r12-r4 */ 282*10465441SEvalZero /* 保存R4 – R12,LR寄存器 */ 283*10465441SEvalZero mov r4, r1 /* Special optimised code below */ 284*10465441SEvalZero /* R1保存有压栈R0 – R3处的栈位置 */ 285*10465441SEvalZero mov r5, r3 /* R3切换出线程的CPSR */ 286*10465441SEvalZero ldmfd r4!, {r0-r3} /* 恢复R0 – R3 */ 287*10465441SEvalZero stmfd sp!, {r0-r3} /* push old task's r3-r0 */ 288*10465441SEvalZero /* R0 – R3压栈到切换出线程 */ 289*10465441SEvalZero stmfd sp!, {r5} /* push old task's psr */ 290*10465441SEvalZero /* 切换出线程CPSR压栈 */ 291*10465441SEvalZero mrs r4, spsr 292*10465441SEvalZero stmfd sp!, {r4} /* push old task's spsr */ 293*10465441SEvalZero /* 切换出线程SPSR压栈 */ 294*10465441SEvalZero 295*10465441SEvalZero ldr r4, =rt_interrupt_from_thread 296*10465441SEvalZero ldr r5, [r4] 297*10465441SEvalZero str sp, [r5] /* store sp in preempted tasks's TCB */ 298*10465441SEvalZero /* 保存切换出线程的SP指针 */ 299*10465441SEvalZero 300*10465441SEvalZero ldr r6, =rt_interrupt_to_thread 301*10465441SEvalZero ldr r6, [r6] 302*10465441SEvalZero ldr sp, [r6] /* get new task's stack pointer */ 303*10465441SEvalZero /* 获得切换到线程的栈 */ 304*10465441SEvalZero 305*10465441SEvalZero ldmfd sp!, {r4} /* pop new task's spsr */ 306*10465441SEvalZero /* 恢复SPSR */ 307*10465441SEvalZero msr SPSR_cxsf, r4 308*10465441SEvalZero ldmfd sp!, {r4} /* pop new task's psr */ 309*10465441SEvalZero /* 恢复CPSR */ 310*10465441SEvalZero msr CPSR_cxsf, r4 311*10465441SEvalZero 312*10465441SEvalZero ldmfd sp!, {r0-r12,lr,pc} /* pop new task's r0-r12,lr & pc */ 313*10465441SEvalZero /* 恢复R0 – R12,LR及PC寄存器 */ 314*10465441SEvalZero 315*10465441SEvalZero/* 代码加密功能 */ 316*10465441SEvalZero#if defined(CODE_PROTECTION) 317*10465441SEvalZero.org 0x01FC 318*10465441SEvalZero.word 0x87654321 319*10465441SEvalZero#endif 320*10465441SEvalZero 321