summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/arm/shared/start/start.S
blob: 30501be1e8054938f59ca7e4b2d8fb214b5a9692 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
/**
 * @file
 *
 * @brief Boot and system start code.
 */

/*
 * Copyright (c) 2008-2014 embedded brains GmbH.  All rights reserved.
 *
 *  embedded brains GmbH
 *  Obere Lagerstr. 30
 *  82178 Puchheim
 *  Germany
 *  <rtems@embedded-brains.de>
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://www.rtems.org/license/LICENSE.
 */

#include <rtems/asm.h>
#include <rtems/system.h>	
#include <rtems/score/cpu.h>
	
#include <bspopts.h>
#include <bsp/irq.h>
#include <bsp/linker-symbols.h>

	/* External symbols */
	.extern	bsp_reset
	.extern	boot_card
	.extern	bsp_start_hook_0
	.extern	bsp_start_hook_1
	.extern bsp_stack_irq_end
	.extern bsp_stack_fiq_end
	.extern bsp_stack_abt_end
	.extern bsp_stack_und_end
	.extern bsp_stack_svc_end
#ifdef RTEMS_SMP
	.extern bsp_stack_all_size
#endif
	.extern	_ARMV4_Exception_undef_default
	.extern	_ARMV4_Exception_swi_default
	.extern	_ARMV4_Exception_data_abort_default
	.extern	_ARMV4_Exception_pref_abort_default
	.extern	_ARMV4_Exception_reserved_default
	.extern	_ARMV4_Exception_interrupt
	.extern	_ARMV4_Exception_fiq_default
	.extern	_ARMV7M_Exception_default

#ifdef BSP_START_NEEDS_REGISTER_INITIALIZATION
	.extern bsp_start_init_registers_core
	.extern bsp_start_init_registers_banked_fiq
	.extern bsp_start_init_registers_vfp
#endif

#ifdef BSP_START_IN_HYP_SUPPORT
	.extern	bsp_start_arm_drop_hyp_mode
	.globl	bsp_start_hyp_vector_table_begin
#endif

	/* Global symbols */
	.globl	_start
	.globl	bsp_start_vector_table_begin
	.globl	bsp_start_vector_table_end
	.globl	bsp_start_vector_table_size
	.globl	bsp_vector_table_size

	.section	".bsp_start_text", "ax"

#if defined(ARM_MULTILIB_ARCH_V4)

	.arm

/*
 * This is the exception vector table and the pointers to the default
 * exceptions handlers.
 */

bsp_start_vector_table_begin:

	ldr	pc, handler_addr_reset
	ldr	pc, handler_addr_undef
	ldr	pc, handler_addr_swi
	ldr	pc, handler_addr_prefetch
	ldr	pc, handler_addr_abort

	/* Program signature checked by boot loader */
	.word	0xb8a06f58

	ldr	pc, handler_addr_irq
	ldr	pc, handler_addr_fiq

handler_addr_reset:

#ifdef BSP_START_RESET_VECTOR
	.word	BSP_START_RESET_VECTOR
#else
	.word	_start
#endif

handler_addr_undef:

	.word	_ARMV4_Exception_undef_default

handler_addr_swi:

	.word	_ARMV4_Exception_swi_default

handler_addr_prefetch:

	.word	_ARMV4_Exception_pref_abort_default

handler_addr_abort:

	.word	_ARMV4_Exception_data_abort_default

handler_addr_reserved:

	.word	_ARMV4_Exception_reserved_default

handler_addr_irq:

	.word	_ARMV4_Exception_interrupt

handler_addr_fiq:

	.word	_ARMV4_Exception_fiq_default

bsp_start_vector_table_end:

#ifdef BSP_START_IN_HYP_SUPPORT
bsp_start_hyp_vector_table_begin:
	ldr	pc, handler_addr_hyp_reset
	ldr	pc, handler_addr_hyp_undef
	ldr	pc, handler_addr_hyp_swi
	ldr	pc, handler_addr_hyp_prefetch
	ldr	pc, handler_addr_hyp_abort
	ldr	pc, handler_addr_hyp_hyp
	ldr	pc, handler_addr_hyp_irq
	ldr	pc, handler_addr_hyp_fiq

handler_addr_hyp_reset:
	.word	_ARMV4_Exception_reserved_default

handler_addr_hyp_undef:
	.word	_ARMV4_Exception_reserved_default

handler_addr_hyp_swi:
	.word	_ARMV4_Exception_reserved_default

handler_addr_hyp_prefetch:
	.word	_ARMV4_Exception_reserved_default

handler_addr_hyp_abort:
	.word	_ARMV4_Exception_reserved_default

handler_addr_hyp_hyp:
	.word	_ARMV4_Exception_reserved_default

handler_addr_hyp_irq:
	.word	_ARMV4_Exception_reserved_default

handler_addr_hyp_fiq:
	.word	_ARMV4_Exception_reserved_default

bsp_start_hyp_vector_table_end:
#endif

/* Start entry */

_start:

	/*
	 * We do not save the context since we do not return to the boot
	 * loader but preserve r1 and r2 to allow access to bootloader parameters
	 */
#ifndef BSP_START_NEEDS_REGISTER_INITIALIZATION
	mov	r5, r1		/* machine type number or ~0 for DT boot */
	mov	r6, r2		/* physical address of ATAGs or DTB */
#else /* BSP_START_NEEDS_REGISTER_INITIALIZATION */
	bl bsp_start_init_registers_core
#endif

#ifdef RTEMS_SMP
	/* Read MPIDR */
	mrc	p15, 0, r0, c0, c0, 5

	/* Calculate stack offset */
	and	r0, #0xff
	ldr	r1, =bsp_stack_all_size
	mul	r1, r0
#endif

	mrs	r4, cpsr	/* save original procesor status value  */
#ifdef BSP_START_IN_HYP_SUPPORT
	orr	r0, r4, #(ARM_PSR_I | ARM_PSR_F)
	msr	cpsr, r4

	and	r0, r4, #ARM_PSR_M_MASK
	cmp	r0, #ARM_PSR_M_HYP
	bne	bsp_start_skip_hyp_svc_switch

	/* Boot loader stats kernel in HYP mode, switch to SVC necessary */
	ldr	sp, =bsp_stack_hyp_end
#ifdef RTEMS_SMP
	add	sp, r1
#endif
	bl	bsp_start_arm_drop_hyp_mode

bsp_start_skip_hyp_svc_switch:
#endif
	/*
	 * Set SVC mode, disable interrupts and enable ARM instructions.
	 */
	mov	r0, #(ARM_PSR_M_SVC | ARM_PSR_I | ARM_PSR_F)
	msr	cpsr, r0

	/* Initialize stack pointer registers for the various modes */

	/* Enter IRQ mode and set up the IRQ stack pointer */
	mov	r0, #(ARM_PSR_M_IRQ | ARM_PSR_I | ARM_PSR_F)
	msr	cpsr, r0
	ldr	sp, =bsp_stack_irq_end
#ifdef RTEMS_SMP
	add	sp, r1
#endif

	/* Enter FIQ mode and set up the FIQ stack pointer */
	mov	r0, #(ARM_PSR_M_FIQ | ARM_PSR_I | ARM_PSR_F)
	msr	cpsr, r0
	ldr	sp, =bsp_stack_fiq_end
#ifdef RTEMS_SMP
	add	sp, r1
#endif

#ifdef BSP_START_NEEDS_REGISTER_INITIALIZATION
	bl bsp_start_init_registers_banked_fiq
#endif

	/* Enter ABT mode and set up the ABT stack pointer */
	mov	r0, #(ARM_PSR_M_ABT | ARM_PSR_I | ARM_PSR_F)
	msr	cpsr, r0
	ldr	sp, =bsp_stack_abt_end
#ifdef RTEMS_SMP
	add	sp, r1
#endif

	/* Enter UND mode and set up the UND stack pointer */
	mov	r0, #(ARM_PSR_M_UND | ARM_PSR_I | ARM_PSR_F)
	msr	cpsr, r0
	ldr	sp, =bsp_stack_und_end
#ifdef RTEMS_SMP
	add	sp, r1
#endif

	/* Enter SVC mode and set up the SVC stack pointer */
	mov	r0, #(ARM_PSR_M_SVC | ARM_PSR_I | ARM_PSR_F)
	msr	cpsr, r0
	ldr	sp, =bsp_stack_svc_end
#ifdef RTEMS_SMP
	add	sp, r1
#endif

	/* Stay in SVC mode */

#ifdef ARM_MULTILIB_VFP
	/* Read CPACR */
	mrc p15, 0, r0, c1, c0, 2

	/* Enable CP10 and CP11 */
	orr r0, r0, #(1 << 20)
	orr r0, r0, #(1 << 22)

	/*
	 * Clear ASEDIS and D32DIS.  Writes to D32DIS are ignored for VFP-D16.
	 */
	bic r0, r0, #(3 << 30)

	/* Write CPACR */
	mcr p15, 0, r0, c1, c0, 2
	isb

	/* Enable FPU */
	mov r0, #(1 << 30)
	vmsr FPEXC, r0

#ifdef BSP_START_NEEDS_REGISTER_INITIALIZATION
	bl bsp_start_init_registers_vfp
#endif

#endif /* ARM_MULTILIB_VFP */

	/*
	 * Branch to start hook 0.
	 *
	 * The previous code and parts of the start hook 0 may run with an
	 * address offset.  This implies that only branches relative to the
	 * program counter are allowed.  After the start hook 0 it is assumed
	 * that the code can run at its intended position.  Thus the link
	 * register will be loaded with the absolute address.  In THUMB mode
	 * the start hook 0 must be within a 2kByte range due to the branch
	 * instruction limitation.
	 */

	ldr	lr, =bsp_start_hook_0_done
#ifdef __thumb__
	orr	lr, #1
#endif

	SWITCH_FROM_ARM_TO_THUMB	r0

	mov	r0, r4		/* original cpsr value */
	mov	r1, r5		/* machine type number or ~0 for DT boot */
	mov	r2, r6		/* physical address of ATAGs or DTB */

	b	bsp_start_hook_0

bsp_start_hook_0_done:

	SWITCH_FROM_THUMB_TO_ARM

	/*
	 * Initialize the exception vectors.  This includes the exceptions
	 * vectors and the pointers to the default exception handlers.
	 */

	stmdb	sp!, {r4, r5, r6}

	ldr	r0, =bsp_vector_table_begin
	adr	r1, bsp_start_vector_table_begin
	cmp	r0, r1
	beq	bsp_vector_table_copy_done
	ldmia	r1!, {r2-r9}
	stmia	r0!, {r2-r9}
	ldmia	r1!, {r2-r9}
	stmia	r0!, {r2-r9}

bsp_vector_table_copy_done:

	ldmia	sp!, {r0, r1, r2}

	SWITCH_FROM_ARM_TO_THUMB	r3

	/* Branch to start hook 1 */
	bl	bsp_start_hook_1

	/* Branch to boot card */
	mov	r0, #0
	bl	boot_card

twiddle:

	/* Branch to reset function */
	bl	bsp_reset

	b	twiddle

#elif defined(ARM_MULTILIB_ARCH_V7M)

#include <rtems/score/armv7m.h>

	.syntax	unified

	.extern	bsp_stack_main_end

	.thumb

bsp_start_vector_table_begin:

	.word	bsp_stack_main_end
	.word	_start /* Reset */
	.word	_ARMV7M_Exception_default /* NMI */
	.word	_ARMV7M_Exception_default /* Hard Fault */
	.word	_ARMV7M_Exception_default /* MPU Fault */
	.word	_ARMV7M_Exception_default /* Bus Fault */
	.word	_ARMV7M_Exception_default /* Usage Fault */
	.word	_ARMV7M_Exception_default /* Reserved */
	.word	_ARMV7M_Exception_default /* Reserved */
	.word	_ARMV7M_Exception_default /* Reserved */
	.word	_ARMV7M_Exception_default /* Reserved */
	.word	_ARMV7M_Exception_default /* SVC */
	.word	_ARMV7M_Exception_default /* Debug Monitor */
	.word	_ARMV7M_Exception_default /* Reserved */
	.word	_ARMV7M_Exception_default /* PendSV */
	.word	_ARMV7M_Exception_default /* SysTick */
	.rept	BSP_INTERRUPT_VECTOR_MAX + 1
	.word	_ARMV7M_Exception_default /* IRQ */
	.endr

bsp_start_vector_table_end:

	.thumb_func

_start:

#ifdef BSP_START_NEEDS_REGISTER_INITIALIZATION
	bl bsp_start_init_registers_core
#endif

#ifdef ARM_MULTILIB_VFP
	/*
	 * Enable CP10 and CP11 coprocessors for privileged and user mode in
	 * CPACR (bits 20-23).  Ensure that write to register completes.
	 */
	ldr	r0, =ARMV7M_CPACR
	ldr	r1, [r0]
	orr	r1, r1, #(0xf << 20)
	str	r1, [r0]
	dsb
	isb

#ifdef BSP_START_NEEDS_REGISTER_INITIALIZATION
	bl bsp_start_init_registers_vfp
#endif

#endif /* ARM_MULTILIB_VFP */

	ldr	sp, =bsp_stack_main_end
	ldr	lr, =bsp_start_hook_0_done + 1
	b	bsp_start_hook_0

bsp_start_hook_0_done:

	bl	bsp_start_hook_1
	movs	r0, #0
	bl	boot_card

twiddle:

	bl	bsp_reset
	b	twiddle

#endif /* defined(ARM_MULTILIB_ARCH_V7M) */

	.set	bsp_start_vector_table_size, bsp_start_vector_table_end - bsp_start_vector_table_begin
	.set	bsp_vector_table_size, bsp_start_vector_table_size