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 * 2011-01-13 weety first version 9 * 2015-04-15 ArdaFu Split from AT91SAM9260 BSP 10 * 2015-04-21 ArdaFu Remove remap code. Using mmu to map vector table 11 * 2015-06-04 aozima Align stack address to 8 byte. 12 */ 13 14#include "rt_low_level_init.h" 15 16#define S_FRAME_SIZE (18*4) //72 17 18@#define S_SPSR (17*4) //SPSR 19@#define S_CPSR (16*4) //CPSR 20#define S_PC (15*4) //R15 21@#define S_LR (14*4) //R14 22@#define S_SP (13*4) //R13 23 24@#define S_IP (12*4) //R12 25@#define S_FP (11*4) //R11 26@#define S_R10 (10*4) 27@#define S_R9 (9*4) 28@#define S_R8 (8*4) 29@#define S_R7 (7*4) 30@#define S_R6 (6*4) 31@#define S_R5 (5*4) 32@#define S_R4 (4*4) 33@#define S_R3 (3*4) 34@#define S_R2 (2*4) 35@#define S_R1 (1*4) 36@#define S_R0 (0*4) 37 38#define MODE_SYS 0x1F 39#define MODE_FIQ 0x11 40#define MODE_IRQ 0x12 41#define MODE_SVC 0x13 42#define MODE_ABT 0x17 43#define MODE_UND 0x1B 44#define MODEMASK 0x1F 45 46#define NOINT 0xC0 47 48@;----------------------- Stack and Heap Definitions --------------------------- 49 .section .nobss, "w" 50 51 .space UND_STK_SIZE 52 .align 3 53 .global UND_STACK_START 54UND_STACK_START: 55 56 .space ABT_STK_SIZE 57 .align 3 58 .global ABT_STACK_START 59ABT_STACK_START: 60 61 .space FIQ_STK_SIZE 62 .align 3 63 .global FIQ_STACK_START 64FIQ_STACK_START: 65 66 .space IRQ_STK_SIZE 67 .align 3 68 .global IRQ_STACK_START 69IRQ_STACK_START: 70 71 .skip SYS_STK_SIZE 72 .align 3 73 .global SYS_STACK_START 74SYS_STACK_START: 75 76 .space SVC_STK_SIZE 77 .align 3 78 .global SVC_STACK_START 79SVC_STACK_START: 80 81@;--------------Jump vector table----------------------------------------------- 82 .section .init, "ax" 83 .arm 84 85 .global start 86start: 87 LDR PC, vector_reset 88 LDR PC, vector_undef 89 LDR PC, vector_swi 90 LDR PC, vector_pabt 91 LDR PC, vector_dabt 92 LDR PC, vector_resv 93 LDR PC, vector_irq 94 LDR PC, vector_fiq 95 96vector_reset: 97 .word Reset_Handler 98vector_undef: 99 .word Undef_Handler 100vector_swi: 101 .word SWI_Handler 102vector_pabt: 103 .word PAbt_Handler 104vector_dabt: 105 .word DAbt_Handler 106vector_resv: 107 .word Resv_Handler 108vector_irq: 109 .word IRQ_Handler 110vector_fiq: 111 .word FIQ_Handler 112 113 .balignl 16,0xdeadbeef 114 115@;----------------- Reset Handler --------------------------------------------- 116 .global rt_low_level_init 117 .global main 118 .global Reset_Handler 119Reset_Handler: 120 @; Set the cpu to SVC32 mode 121 MRS R0, CPSR 122 BIC R0, R0, #MODEMASK 123 ORR R0, R0, #MODE_SVC|NOINT 124 MSR CPSR_cxsf, R0 125 126 @; Set CO-Processor 127 @; little-end锛宒isbale I/D Cache MMU, vector table is 0x00000000 128 MRC P15, 0, R0, C1, C0, 0 @; Read CP15 129 LDR R1, =0x00003085 @; set clear bits 130 BIC R0, R0, R1 131 MCR P15, 0, R0, C1, C0, 0 @; Write CP15 132 133 @; Call low level init function, 134 @; disable and clear all IRQs, Init MMU, Init interrupt controller, etc. 135 LDR SP, =SVC_STACK_START 136 LDR R0, =rt_low_level_init 137 BLX R0 138 139Setup_Stack: 140 @; Setup Stack for each mode 141 MRS R0, CPSR 142 BIC R0, R0, #MODEMASK 143 144 ORR R1, R0, #MODE_UND|NOINT 145 MSR CPSR_cxsf, R1 @; Undef mode 146 LDR SP, =UND_STACK_START 147 148 ORR R1, R0, #MODE_ABT|NOINT 149 MSR CPSR_cxsf, R1 @; Abort mode 150 LDR SP, =ABT_STACK_START 151 152 ORR R1, R0, #MODE_IRQ|NOINT 153 MSR CPSR_cxsf, R1 @; IRQ mode 154 LDR SP, =IRQ_STACK_START 155 156 ORR R1, R0, #MODE_FIQ|NOINT 157 MSR CPSR_cxsf, R1 @; FIQ mode 158 LDR SP, =FIQ_STACK_START 159 160 ORR R1, R0, #MODE_SYS|NOINT 161 MSR CPSR_cxsf,R1 @; SYS/User mode 162 LDR SP, =SYS_STACK_START 163 164 ORR R1, R0, #MODE_SVC|NOINT 165 MSR CPSR_cxsf, R1 @; SVC mode 166 LDR SP, =SVC_STACK_START 167 168 @; clear .bss 169 MOV R0, #0 @; get a zero 170 LDR R1, =__bss_start__ @; bss start 171 LDR R2, =__bss_end__ @; bss end 172 173bss_clear_loop: 174 CMP R1, R2 @; check if data to clear 175 STRLO R0, [R1], #4 @; clear 4 bytes 176 BLO bss_clear_loop @; loop until done 177 178 @; call C++ constructors of global objects 179 LDR R0, =__ctors_start__ 180 LDR R1, =__ctors_end__ 181 182ctor_loop: 183 CMP R0, R1 184 BEQ ctor_end 185 LDR R2, [R0], #4 186 STMFD SP!, {R0-R1} 187 MOV LR, PC 188 BX R2 189 LDMFD SP!, {R0-R1} 190 B ctor_loop 191ctor_end: 192 193 @; Enter the C code 194 LDR R0, =rtthread_startup 195 BLX R0 196 197@;----------------- Exception Handler ----------------------------------------- 198 .global rt_hw_trap_udef 199 .global rt_hw_trap_swi 200 .global rt_hw_trap_pabt 201 .global rt_hw_trap_dabt 202 .global rt_hw_trap_resv 203 .global rt_hw_trap_irq 204 .global rt_hw_trap_fiq 205 206 .global rt_interrupt_enter 207 .global rt_interrupt_leave 208 .global rt_thread_switch_interrupt_flag 209 .global rt_interrupt_from_thread 210 .global rt_interrupt_to_thread 211 212 .align 5 213Undef_Handler: 214 SUB SP, SP, #S_FRAME_SIZE 215 STMIA SP, {R0 - R12} @; Calling R0-R12 216 ADD R8, SP, #S_PC 217 STMDB R8, {SP, LR} @; Calling SP, LR 218 STR LR, [R8, #0] @; Save calling PC 219 MRS R6, SPSR 220 STR R6, [R8, #4] @; Save CPSR 221 STR R0, [R8, #8] @; Save SPSR 222 MOV R0, SP 223 BL rt_hw_trap_udef 224 225 .align 5 226SWI_Handler: 227 BL rt_hw_trap_swi 228 229 .align 5 230PAbt_Handler: 231 BL rt_hw_trap_pabt 232 233 .align 5 234DAbt_Handler: 235 SUB SP, SP, #S_FRAME_SIZE 236 STMIA SP, {R0 - R12} @; Calling R0-R12 237 ADD R8, SP, #S_PC 238 STMDB R8, {SP, LR} @; Calling SP, LR 239 STR LR, [R8, #0] @; Save calling PC 240 MRS R6, SPSR 241 STR R6, [R8, #4] @; Save CPSR 242 STR R0, [R8, #8] @; Save SPSR 243 MOV R0, SP 244 BL rt_hw_trap_dabt 245 246 .align 5 247Resv_Handler: 248 BL rt_hw_trap_resv 249 250 .align 5 251FIQ_Handler: 252 STMFD SP!, {R0-R7,LR} 253 BL rt_hw_trap_fiq 254 LDMFD SP!, {R0-R7,LR} 255 SUBS PC, LR, #4 256 257 .align 5 258IRQ_Handler: 259 STMFD SP!, {R0-R12,LR} 260 BL rt_interrupt_enter 261 BL rt_hw_trap_irq 262 BL rt_interrupt_leave 263 264 @; If rt_thread_switch_interrupt_flag set, 265 @; jump to rt_hw_context_switch_interrupt_do and don't return 266 LDR R0, =rt_thread_switch_interrupt_flag 267 LDR R1, [R0] 268 CMP R1, #1 269 BEQ rt_hw_context_switch_interrupt_do 270 271 LDMFD SP!, {R0-R12,LR} 272 SUBS PC, LR, #4 273 274@;------ void rt_hw_context_switch_interrupt_do(rt_base_t flag) ----------------- 275rt_hw_context_switch_interrupt_do: 276 MOV R1, #0 @; Clear flag 277 STR R1, [R0] @; Save to flag variable 278 279 LDMFD SP!, {R0-R12,LR} @; Reload saved registers 280 STMFD SP, {R0-R2} @; Save R0-R2 281 SUB R1, SP, #4*3 @; Save old task's SP to R1 282 SUB R2, LR, #4 @; Save old task's PC to R2 283 284 MRS R0, SPSR @; Get CPSR of interrupt thread 285 286 MSR CPSR_c, #MODE_SVC|NOINT @; Switch to SVC mode and no interrupt 287 288 STMFD SP!, {R2} @; Push old task's PC 289 STMFD SP!, {R3-R12,LR} @; Push old task's LR,R12-R3 290 LDMFD R1, {R1-R3} 291 STMFD SP!, {R1-R3} @; Push old task's R2-R0 292 STMFD SP!, {R0} @; Push old task's CPSR 293 294 LDR R4, =rt_interrupt_from_thread 295 LDR R5, [R4] @; R5 = stack ptr in old tasks's TCB 296 STR SP, [R5] @; Store SP in preempted tasks's TCB 297 298 LDR R6, =rt_interrupt_to_thread 299 LDR R6, [R6] @; R6 = stack ptr in new tasks's TCB 300 LDR SP, [R6] @; Get new task's stack pointer 301 302 LDMFD SP!, {R4} @; Pop new task's SPSR 303 MSR SPSR_cxsf, R4 304 305 LDMFD SP!, {R0-R12,LR,PC}^ @; pop new task's R0-R12,LR & PC SPSR 2 CPSR 306