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