summaryrefslogtreecommitdiff
path: root/firmware/src/start/Cstartup.S
blob: e91fd8664b6a587e23ff9cd2b72ae83613fe9dd4 (plain)
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
/*------------------------------------------------------------------------------
//*-         ATMEL Microcontroller Software Support  -  ROUSSET  -
//*------------------------------------------------------------------------------
//* The software is delivered "AS IS" without warranty or condition of any
//* kind, either express, implied or statutory. This includes without
//* limitation any warranty or condition with respect to merchantability or
//* fitness for any particular purpose, or against the infringements of
//* intellectual property rights of others.
//*-----------------------------------------------------------------------------
//*- File source          : Cstartup.s
//*- Object               : Generic CStartup for KEIL and GCC No Use REMAP
//*- Compilation flag     : None
//*-
//*- 1.0 18/Oct/04 JPP    : Creation
//*- 1.1 21/Feb/05 JPP    : Set Interrupt
//*- 1.1 01/Apr/05 JPP    : save SPSR 
//*-----------------------------------------------------------------------------*/

#define CONFIG_DFU_SWITCH

//#define DEBUG_LL

#ifdef DEBUG_LL
/* Debugging macros for switching on/off LED1 (green) */
#define PIOA_PER	0xFFFFF400
#define PIOA_OER	0xFFFFF410
#define PIOA_SODR	0xFFFFF430
#define PIOA_CODR	0xFFFFF434
#define LED1		25		/* this only works on OpenPICC, not Olimex */
	.macro	led1on
		ldr	r2, =PIOA_CODR
		mov	r1, #(1 << LED1)
		str	r1, [r2]
	.endm
	.macro	led1off
		ldr	r2, =PIOA_SODR
		mov	r1, #(1 << LED1)
		str	r1, [r2]
	.endm
	.macro	ledinit
		ldr	r2, =PIOA_PER
		mov	r1, #(1 << LED1)
		str	r1, [r2]
		ldr	r2, =PIOA_OER
		str	r1, [r2]
		led1off
	.endm
#else
	.macro ledinit
	.endm
	.macro led1on
	.endm
	.macro led1off
	.endm
#endif

     .equ   IRQ_Stack_Size,     0x00000400

	.equ AIC_IVR,         (256) 
	.equ AIC_FVR,         (260) 
	.equ AIC_EOICR,       (304)
	.equ AIC_MCR_RCR,     (0xf00)
	.equ AT91C_BASE_AIC,  (0xFFFFF000)
	.equ AT91C_PMC_PCER,  (0xFFFFFC10)
	.equ AT91C_BASE_PIOA, (0xFFFFF400)
	.equ AT91C_ID_PIOA,   (2)
	.equ PIOA_PDSR,	      (0x3c)
	.equ PIO_BOOTLDR,     (1 << 27)
	#.equ PIO_BOOTLDR,     (1 << 6)


/* #include "AT91SAM7S64_inc.h"	  */

/* Exception Vectors in RAM */

	.text
	.arm
	.section	.vectram, "ax"
resetvecR:	B	resetvecR
undefvecR:	B	undefvecR
swivecR:	B	swivecR
pabtvecR:	B	pabtvecR
dabtvecR:	B	dabtvecR
rsvdvecR:	B	rsvdvecR
irqvecR:	B	IRQ_Handler_EntryR
fiqvecR:	

FIQ_Handler_EntryR:

/*- Switch in SVC/User Mode to allow User Stack access for C code 	*/
/* because the FIQ is not yet acknowledged*/

/*- Save and r0 in FIQ_Register */
            mov         r9,r0
	        ldr         r0 , [r8, #AIC_FVR]
            msr         CPSR_c,#I_BIT | F_BIT | ARM_MODE_SVC

/*- Save scratch/used registers and LR in User Stack */
            stmfd       sp!, { r1-r3, r12, lr}

/*- Branch to the routine pointed by the AIC_FVR */
            mov         r14, pc
            bx          r0

/*- Restore scratch/used registers and LR from User Stack */
            ldmia       sp!, { r1-r3, r12, lr}

/*- Leave Interrupts disabled and switch back in FIQ mode */
            msr         CPSR_c, #I_BIT | F_BIT | ARM_MODE_FIQ

/*- Restore the R0 ARM_MODE_SVC register */
            mov         r0,r9

/*- Restore the Program Counter using the LR_fiq directly in the PC */
            subs        pc,lr,#4

        .global IRQ_Handler_EntryR
        .func   IRQ_Handler_EntryR

IRQ_Handler_EntryR:

/*- Manage Exception Entry  */
/*- Adjust and save LR_irq in IRQ stack  */
            sub         lr, lr, #4
            stmfd       sp!, {lr}

/*- Save SPSR need to be saved for nested interrupt */
            mrs         r14, SPSR
            stmfd       sp!, {r14}

/*- Save and r0 in IRQ stack  */
            stmfd       sp!, {r0}

/*- Write in the IVR to support Protect Mode  */
/*- No effect in Normal Mode  */
/*- De-assert the NIRQ and clear the source in Protect Mode */
            ldr         r14, =AT91C_BASE_AIC
	    ldr         r0 , [r14, #AIC_IVR]
	    str         r14, [r14, #AIC_IVR]

/*- Enable Interrupt and Switch in Supervisor Mode */
            msr         CPSR_c, #ARM_MODE_SVC

/*- Save scratch/used registers and LR in User Stack */
            stmfd       sp!, { r1-r3, r12, r14}

/*- Branch to the routine pointed by the AIC_IVR  */
            mov         r14, pc
            bx          r0
/*- Restore scratch/used registers and LR from User Stack*/
            ldmia       sp!, { r1-r3, r12, r14}

/*- Disable Interrupt and switch back in IRQ mode */
            msr         CPSR_c, #I_BIT | ARM_MODE_IRQ

/*- Mark the End of Interrupt on the AIC */
            ldr         r14, =AT91C_BASE_AIC
            str         r14, [r14, #AIC_EOICR]

/*- Restore SPSR_irq and r0 from IRQ stack */
            ldmia       sp!, {r0}

/*- Restore SPSR_irq and r0 from IRQ stack */
            ldmia       sp!, {r14}
            msr         SPSR_cxsf, r14

/*- Restore adjusted  LR_irq from IRQ stack directly in the PC */
            ldmia       sp!, {pc}^
	
        .size   IRQ_Handler_EntryR, . - IRQ_Handler_EntryR
        .endfunc

	.global remap
	.func	remap
_remap:
#		led1on
# Remap RAM to 0x00000000 for DFU 
		ldr	r1, =AT91C_BASE_AIC
		mov	r2, #0x01
		str	r2, [r1, #AIC_MCR_RCR]

		/* prepare c function call to main */
		mov	r0, #0	/* argc = 0 */
		ldr	lr,=exit
		ldr	r10,=main

#ifdef CONFIG_DFU_SWITCH
		/* check whether bootloader button is pressed */
		ldr	r1, =AT91C_PMC_PCER
		mov	r2, #(1 << AT91C_ID_PIOA)
		str	r2, [r1] 

		ldr 	r1, =AT91C_BASE_PIOA
		ldr	r2, [r1, #PIOA_PDSR]
		tst	r2, #PIO_BOOTLDR
		ldrne	r10,=dfu_main
#endif

		bx	r10
	.size	remap, . - remap
	.endfunc

/* "exit" dummy added by mthomas to avoid sbrk write read etc. needed
   by the newlib default "exit" */
        .global exit
        .func   exit
exit:
        b    .
		.size   exit, . - exit
        .endfunc

/*---------------------------------------------------------------
//* ?EXEPTION_VECTOR
//* This module is only linked if needed for closing files.
//*---------------------------------------------------------------*/
        .global AT91F_Default_FIQ_handler
        .func   AT91F_Default_FIQ_handler
AT91F_Default_FIQ_handler:
            b     AT91F_Default_FIQ_handler
        .size   AT91F_Default_FIQ_handler, . - AT91F_Default_FIQ_handler
        .endfunc

        .global AT91F_Default_IRQ_handler
        .func   AT91F_Default_IRQ_handler
AT91F_Default_IRQ_handler:
            b     AT91F_Default_IRQ_handler
        .size   AT91F_Default_IRQ_handler, . - AT91F_Default_IRQ_handler
        .endfunc

        .global AT91F_Spurious_handler
        .func   AT91F_Spurious_handler
AT91F_Spurious_handler:
            b     AT91F_Spurious_handler
        .size   AT91F_Spurious_handler, . - AT91F_Spurious_handler
        .endfunc



#;------------------------------------------------------------------------------
#;- Section Definition
#;-----------------
#;-  Section    
#;- .internal_ram_top 	Top_Stack: used by the cstartup for vector initalisation 
#;-			management defined by ld and affect from ldscript 
#;------------------------------------------------------------------------------
	.section 	.internal_ram_top
	.code 32
	.align 	0
	.global	Top_Stack
Top_Stack:
	
/*------------------------------------------------------------------------------
*- Area Definition
*------------------------------------------------------------------------------
* .text is used instead of .section .text so it works with arm-aout too.  */
        .section 	.reset
        .text
        .global _startup
        .func   _startup
_startup:
reset: 
/*------------------------------------------------------------------------------
//*- Exception vectors 
//*--------------------
//*- These vectors can be read at address 0 or at RAM address
//*- They ABSOLUTELY requires to be in relative addresssing mode in order to
//*- guarantee a valid jump. For the moment, all are just looping.
//*- If an exception occurs before remap, this would result in an infinite loop.
//*- To ensure if a exeption occurs before start application to infinite loop.
//*------------------------------------------------------------------------------*/

                B           InitReset           /* 0x00 Reset handler */
undefvec:
                B           undefvec            /* 0x04 Undefined Instruction */
swivec:
                B           swivec              /* 0x08 Software Interrupt */
pabtvec:
                B           pabtvec             /* 0x0C Prefetch Abort */
dabtvec:
                B           dabtvec             /* 0x10 Data Abort */
rsvdvec:
                B           rsvdvec             /* 0x14 reserved  */
irqvec:
                B           irqvec		/* 0x18 IRQ	 */
fiqvec:               		  
		B	    fiqvec          	/* 0x1c FIQ	*/
	.align 0
.RAM_TOP:
	.word	Top_Stack

InitReset:
/*------------------------------------------------------------------------------
/*- Low level Init (PMC, AIC, ? ....) by C function AT91F_LowLevelInit
/*------------------------------------------------------------------------------*/
            	.extern   AT91F_LowLevelInit
/*- minumum C initialization */
/*- call  AT91F_LowLevelInit( void) */

	ldr	r13,.RAM_TOP            /* temporary stack in internal RAM */
/*--Call Low level init function in ABSOLUTE through the Interworking	*/
        ldr	r0,=AT91F_LowLevelInit
	mov	lr, pc
	bx	r0
	ledinit
/*------------------------------------------------------------------------------
//*- Stack Sizes Definition
//*------------------------
//*- Interrupt Stack requires 2 words x 8 priority level x 4 bytes when using
//*- the vectoring. This assume that the IRQ management.
//*- The Interrupt Stack must be adjusted depending on the interrupt handlers.
//*- Fast Interrupt not requires stack If in your application it required you must
//*- be definehere.
//*- The System stack size is not defined and is limited by the free internal
//*- SRAM.
//*------------------------------------------------------------------------------*/

/*------------------------------------------------------------------------------
//*- Top of Stack Definition
//*-------------------------
//*- Interrupt and Supervisor Stack are located at the top of internal memory in 
//*- order to speed the exception handling context saving and restoring.
//*- ARM_MODE_SVC (Application, C) Stack is located at the top of the external memory.
//*------------------------------------------------------------------------------*/

	  .EQU		IRQ_STACK_SIZE,    (3*8*4)
          .EQU		ARM_MODE_FIQ,       0x11
          .EQU		ARM_MODE_IRQ,       0x12
          .EQU		ARM_MODE_SVC,       0x13

          .EQU		I_BIT,              0x80
          .EQU		F_BIT,              0x40

/*------------------------------------------------------------------------------
//*- Setup the stack for each mode
//*-------------------------------*/
                mov     r0,r13

/*- Set up Fast Interrupt Mode and set FIQ Mode Stack*/
                msr     CPSR_c, #ARM_MODE_FIQ | I_BIT | F_BIT
/*- Init the FIQ register*/
            	ldr     r8, =AT91C_BASE_AIC

/*- Set up Interrupt Mode and set IRQ Mode Stack*/
                msr     CPSR_c, #ARM_MODE_IRQ | I_BIT | F_BIT
                mov     r13, r0                     /* Init stack IRQ */
                sub     r0, r0, #IRQ_Stack_Size
/*- Set up Supervisor Mode and set Supervisor Mode Stack*/
                msr     CPSR_c, #ARM_MODE_SVC
                mov     r13, r0                     /* Init stack Sup */

/*- Relocate DFU .data section (Copy from ROM to RAM)*/
		ldr	r1, =_etext_dfu
		ldr	r2, =_data_dfu
		ldr	r3, =_edata_dfu
LoopRelDFU:	cmp	r2, r3
		ldrlo	r0, [r1], #4
		strlo	r0, [r2], #4
                blo	LoopRelDFU

# Relocate .data section (Copy from ROM to RAM)
                LDR     R1, =_etext
                LDR     R2, =_data
                LDR     R3, =_edata
LoopRel:        CMP     R2, R3
                LDRLO   R0, [R1], #4
                STRLO   R0, [R2], #4
                BLO     LoopRel

# Clear .bss section (Zero init)
                MOV     R0, #0
                LDR     R1, =__bss_start__
                LDR     R2, =__bss_end__
LoopZI:         CMP     R1, R2
                STRLO   R0, [R1], #4
                BLO     LoopZI

		led1on

		ldr	r0, =_remap
		bx	r0

        .size   _startup, . - _startup
        .endfunc
		
        .end

personal git repositories of Harald Welte. Your mileage may vary