xref: /nrf52832-nimble/rt-thread/libcpu/arm/AT91SAM7S/start_rvds.S (revision 104654410c56c573564690304ae786df310c91fc)
1;/*****************************************************************************/
2;/* SAM7.S: Startup file for Atmel AT91SAM7 device series                     */
3;/*****************************************************************************/
4;/* <<< Use Configuration Wizard in Context Menu >>>                          */
5;/*****************************************************************************/
6;/* This file is part of the uVision/ARM development tools.                   */
7;/* Copyright (c) 2005-2006 Keil Software. All rights reserved.               */
8;/* This software may only be used under the terms of a valid, current,       */
9;/* end user licence from KEIL for a compatible version of KEIL software      */
10;/* development tools. Nothing else gives you the right to use this software. */
11;/*****************************************************************************/
12
13
14;/*
15; *  The SAM7.S code is executed after CPU Reset. This file may be
16; *  translated with the following SET symbols. In uVision these SET
17; *  symbols are entered under Options - ASM - Define.
18; *
19; *  REMAP: when set the startup code remaps exception vectors from
20; *  on-chip RAM to address 0.
21; *
22; *  RAM_INTVEC: when set the startup code copies exception vectors
23; *  from on-chip Flash to on-chip RAM.
24; */
25
26
27; Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs
28
29Mode_USR        EQU     0x10
30Mode_FIQ        EQU     0x11
31Mode_IRQ        EQU     0x12
32Mode_SVC        EQU     0x13
33Mode_ABT        EQU     0x17
34Mode_UND        EQU     0x1B
35Mode_SYS        EQU     0x1F
36
37I_Bit           EQU     0x80            ; when I bit is set, IRQ is disabled
38F_Bit           EQU     0x40            ; when F bit is set, FIQ is disabled
39
40
41; Internal Memory Base Addresses
42FLASH_BASE      EQU     0x00100000
43RAM_BASE        EQU     0x00200000
44
45
46;// <h> Stack Configuration (Stack Sizes in Bytes)
47;//   <o0> Undefined Mode      <0x0-0xFFFFFFFF:8>
48;//   <o1> Supervisor Mode     <0x0-0xFFFFFFFF:8>
49;//   <o2> Abort Mode          <0x0-0xFFFFFFFF:8>
50;//   <o3> Fast Interrupt Mode <0x0-0xFFFFFFFF:8>
51;//   <o4> Interrupt Mode      <0x0-0xFFFFFFFF:8>
52;//   <o5> User/System Mode    <0x0-0xFFFFFFFF:8>
53;// </h>
54
55UND_Stack_Size  EQU     0x00000000
56SVC_Stack_Size  EQU     0x00000100
57ABT_Stack_Size  EQU     0x00000000
58FIQ_Stack_Size  EQU     0x00000000
59IRQ_Stack_Size  EQU     0x00000100
60USR_Stack_Size  EQU     0x00000100
61
62ISR_Stack_Size  EQU     (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \
63                         FIQ_Stack_Size + IRQ_Stack_Size)
64
65                AREA    STACK, NOINIT, READWRITE, ALIGN=3
66
67Stack_Mem       SPACE   USR_Stack_Size
68__initial_sp    SPACE   ISR_Stack_Size
69Stack_Top
70
71
72;// <h> Heap Configuration
73;//   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF>
74;// </h>
75
76Heap_Size       EQU     0x00000000
77
78                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
79__heap_base
80Heap_Mem        SPACE   Heap_Size
81__heap_limit
82
83
84; Reset Controller (RSTC) definitions
85RSTC_BASE       EQU     0xFFFFFD00      ; RSTC Base Address
86RSTC_MR         EQU     0x08            ; RSTC_MR Offset
87
88;/*
89;// <e> Reset Controller (RSTC)
90;//   <o1.0>     URSTEN: User Reset Enable
91;//              <i> Enables NRST Pin to generate Reset
92;//   <o1.8..11> ERSTL: External Reset Length <0-15>
93;//              <i> External Reset Time in 2^(ERSTL+1) Slow Clock Cycles
94;// </e>
95;*/
96RSTC_SETUP      EQU     1
97RSTC_MR_Val     EQU     0xA5000401
98
99
100; Embedded Flash Controller (EFC) definitions
101EFC_BASE        EQU     0xFFFFFF00      ; EFC Base Address
102EFC0_FMR        EQU     0x60            ; EFC0_FMR Offset
103EFC1_FMR        EQU     0x70            ; EFC1_FMR Offset
104
105;// <e> Embedded Flash Controller 0 (EFC0)
106;//   <o1.16..23> FMCN: Flash Microsecond Cycle Number <0-255>
107;//               <i> Number of Master Clock Cycles in 1us
108;//   <o1.8..9>   FWS: Flash Wait State
109;//               <0=> Read: 1 cycle / Write: 2 cycles
110;//               <1=> Read: 2 cycle / Write: 3 cycles
111;//               <2=> Read: 3 cycle / Write: 4 cycles
112;//               <3=> Read: 4 cycle / Write: 4 cycles
113;// </e>
114EFC0_SETUP      EQU     1
115EFC0_FMR_Val    EQU     0x00320100
116
117;// <e> Embedded Flash Controller 1 (EFC1)
118;//   <o1.16..23> FMCN: Flash Microsecond Cycle Number <0-255>
119;//               <i> Number of Master Clock Cycles in 1us
120;//   <o1.8..9>   FWS: Flash Wait State
121;//               <0=> Read: 1 cycle / Write: 2 cycles
122;//               <1=> Read: 2 cycle / Write: 3 cycles
123;//               <2=> Read: 3 cycle / Write: 4 cycles
124;//               <3=> Read: 4 cycle / Write: 4 cycles
125;// </e>
126EFC1_SETUP      EQU     0
127EFC1_FMR_Val    EQU     0x00320100
128
129
130; Watchdog Timer (WDT) definitions
131WDT_BASE        EQU     0xFFFFFD40      ; WDT Base Address
132WDT_MR          EQU     0x04            ; WDT_MR Offset
133
134;// <e> Watchdog Timer (WDT)
135;//   <o1.0..11>  WDV: Watchdog Counter Value <0-4095>
136;//   <o1.16..27> WDD: Watchdog Delta Value <0-4095>
137;//   <o1.12>     WDFIEN: Watchdog Fault Interrupt Enable
138;//   <o1.13>     WDRSTEN: Watchdog Reset Enable
139;//   <o1.14>     WDRPROC: Watchdog Reset Processor
140;//   <o1.28>     WDDBGHLT: Watchdog Debug Halt
141;//   <o1.29>     WDIDLEHLT: Watchdog Idle Halt
142;//   <o1.15>     WDDIS: Watchdog Disable
143;// </e>
144WDT_SETUP       EQU     1
145WDT_MR_Val      EQU     0x00008000
146
147
148; Power Mangement Controller (PMC) definitions
149PMC_BASE        EQU     0xFFFFFC00      ; PMC Base Address
150PMC_MOR         EQU     0x20            ; PMC_MOR Offset
151PMC_MCFR        EQU     0x24            ; PMC_MCFR Offset
152PMC_PLLR        EQU     0x2C            ; PMC_PLLR Offset
153PMC_MCKR        EQU     0x30            ; PMC_MCKR Offset
154PMC_SR          EQU     0x68            ; PMC_SR Offset
155PMC_MOSCEN      EQU     (1<<0)          ; Main Oscillator Enable
156PMC_OSCBYPASS   EQU     (1<<1)          ; Main Oscillator Bypass
157PMC_OSCOUNT     EQU     (0xFF<<8)       ; Main OScillator Start-up Time
158PMC_DIV         EQU     (0xFF<<0)       ; PLL Divider
159PMC_PLLCOUNT    EQU     (0x3F<<8)       ; PLL Lock Counter
160PMC_OUT         EQU     (0x03<<14)      ; PLL Clock Frequency Range
161PMC_MUL         EQU     (0x7FF<<16)     ; PLL Multiplier
162PMC_USBDIV      EQU     (0x03<<28)      ; USB Clock Divider
163PMC_CSS         EQU     (3<<0)          ; Clock Source Selection
164PMC_PRES        EQU     (7<<2)          ; Prescaler Selection
165PMC_MOSCS       EQU     (1<<0)          ; Main Oscillator Stable
166PMC_LOCK        EQU     (1<<2)          ; PLL Lock Status
167PMC_MCKRDY      EQU     (1<<3)          ; Master Clock Status
168
169;// <e> Power Mangement Controller (PMC)
170;//   <h> Main Oscillator
171;//     <o1.0>      MOSCEN: Main Oscillator Enable
172;//     <o1.1>      OSCBYPASS: Oscillator Bypass
173;//     <o1.8..15>  OSCCOUNT: Main Oscillator Startup Time <0-255>
174;//   </h>
175;//   <h> Phase Locked Loop (PLL)
176;//     <o2.0..7>   DIV: PLL Divider <0-255>
177;//     <o2.16..26> MUL: PLL Multiplier <0-2047>
178;//                 <i> PLL Output is multiplied by MUL+1
179;//     <o2.14..15> OUT: PLL Clock Frequency Range
180;//                 <0=> 80..160MHz  <1=> Reserved
181;//                 <2=> 150..220MHz <3=> Reserved
182;//     <o2.8..13>  PLLCOUNT: PLL Lock Counter <0-63>
183;//     <o2.28..29> USBDIV: USB Clock Divider
184;//                 <0=> None  <1=> 2  <2=> 4  <3=> Reserved
185;//   </h>
186;//   <o3.0..1>   CSS: Clock Source Selection
187;//               <0=> Slow Clock
188;//               <1=> Main Clock
189;//               <2=> Reserved
190;//               <3=> PLL Clock
191;//   <o3.2..4>   PRES: Prescaler
192;//               <0=> None
193;//               <1=> Clock / 2    <2=> Clock / 4
194;//               <3=> Clock / 8    <4=> Clock / 16
195;//               <5=> Clock / 32   <6=> Clock / 64
196;//               <7=> Reserved
197;// </e>
198PMC_SETUP       EQU     1
199PMC_MOR_Val     EQU     0x00000601
200PMC_PLLR_Val    EQU     0x00191C05
201PMC_MCKR_Val    EQU     0x00000007
202
203
204                PRESERVE8
205
206
207; Area Definition and Entry Point
208;  Startup Code must be linked first at Address at which it expects to run.
209
210                AREA    RESET, CODE, READONLY
211                ARM
212
213
214; Exception Vectors
215;  Mapped to Address 0.
216;  Absolute addressing mode must be used.
217;  Dummy Handlers are implemented as infinite loops which can be modified.
218
219Vectors         LDR     PC,Reset_Addr
220                LDR     PC,Undef_Addr
221                LDR     PC,SWI_Addr
222                LDR     PC,PAbt_Addr
223                LDR     PC,DAbt_Addr
224                NOP                            ; Reserved Vector
225                LDR     PC,IRQ_Addr
226                LDR     PC,FIQ_Addr
227
228Reset_Addr      DCD     Reset_Handler
229Undef_Addr      DCD     Undef_Handler
230SWI_Addr        DCD     SWI_Handler
231PAbt_Addr       DCD     PAbt_Handler
232DAbt_Addr       DCD     DAbt_Handler
233                DCD     0                      ; Reserved Address
234IRQ_Addr        DCD     IRQ_Handler
235FIQ_Addr        DCD     FIQ_Handler
236
237Undef_Handler   B       Undef_Handler
238SWI_Handler     B       SWI_Handler
239PAbt_Handler    B       PAbt_Handler
240DAbt_Handler    B       DAbt_Handler
241FIQ_Handler     B       FIQ_Handler
242
243
244; Reset Handler
245
246                EXPORT  Reset_Handler
247Reset_Handler
248
249
250; Setup RSTC
251                IF      RSTC_SETUP != 0
252                LDR     R0, =RSTC_BASE
253                LDR     R1, =RSTC_MR_Val
254                STR     R1, [R0, #RSTC_MR]
255                ENDIF
256
257
258; Setup EFC0
259                IF      EFC0_SETUP != 0
260                LDR     R0, =EFC_BASE
261                LDR     R1, =EFC0_FMR_Val
262                STR     R1, [R0, #EFC0_FMR]
263                ENDIF
264
265; Setup EFC1
266                IF      EFC1_SETUP != 0
267                LDR     R0, =EFC_BASE
268                LDR     R1, =EFC1_FMR_Val
269                STR     R1, [R0, #EFC1_FMR]
270                ENDIF
271
272; Setup WDT
273                IF      WDT_SETUP != 0
274                LDR     R0, =WDT_BASE
275                LDR     R1, =WDT_MR_Val
276                STR     R1, [R0, #WDT_MR]
277                ENDIF
278
279
280; Setup PMC
281                IF      PMC_SETUP != 0
282                LDR     R0, =PMC_BASE
283
284;  Setup Main Oscillator
285                LDR     R1, =PMC_MOR_Val
286                STR     R1, [R0, #PMC_MOR]
287
288;  Wait until Main Oscillator is stablilized
289                IF      (PMC_MOR_Val:AND:PMC_MOSCEN) != 0
290MOSCS_Loop      LDR     R2, [R0, #PMC_SR]
291                ANDS    R2, R2, #PMC_MOSCS
292                BEQ     MOSCS_Loop
293                ENDIF
294
295;  Setup the PLL
296                IF      (PMC_PLLR_Val:AND:PMC_MUL) != 0
297                LDR     R1, =PMC_PLLR_Val
298                STR     R1, [R0, #PMC_PLLR]
299
300;  Wait until PLL is stabilized
301PLL_Loop        LDR     R2, [R0, #PMC_SR]
302                ANDS    R2, R2, #PMC_LOCK
303                BEQ     PLL_Loop
304                ENDIF
305
306;  Select Clock
307                IF      (PMC_MCKR_Val:AND:PMC_CSS) == 1     ; Main Clock Selected
308                LDR     R1, =PMC_MCKR_Val
309                AND     R1, #PMC_CSS
310                STR     R1, [R0, #PMC_MCKR]
311WAIT_Rdy1       LDR     R2, [R0, #PMC_SR]
312                ANDS    R2, R2, #PMC_MCKRDY
313                BEQ     WAIT_Rdy1
314                LDR     R1, =PMC_MCKR_Val
315                STR     R1, [R0, #PMC_MCKR]
316WAIT_Rdy2       LDR     R2, [R0, #PMC_SR]
317                ANDS    R2, R2, #PMC_MCKRDY
318                BEQ     WAIT_Rdy2
319                ELIF    (PMC_MCKR_Val:AND:PMC_CSS) == 3     ; PLL  Clock Selected
320                LDR     R1, =PMC_MCKR_Val
321                AND     R1, #PMC_PRES
322                STR     R1, [R0, #PMC_MCKR]
323WAIT_Rdy1       LDR     R2, [R0, #PMC_SR]
324                ANDS    R2, R2, #PMC_MCKRDY
325                BEQ     WAIT_Rdy1
326                LDR     R1, =PMC_MCKR_Val
327                STR     R1, [R0, #PMC_MCKR]
328WAIT_Rdy2       LDR     R2, [R0, #PMC_SR]
329                ANDS    R2, R2, #PMC_MCKRDY
330                BEQ     WAIT_Rdy2
331                ENDIF   ; Select Clock
332                ENDIF   ; PMC_SETUP
333
334
335; Copy Exception Vectors to Internal RAM
336
337                IF      :DEF:RAM_INTVEC
338                ADR     R8, Vectors         ; Source
339                LDR     R9, =RAM_BASE       ; Destination
340                LDMIA   R8!, {R0-R7}        ; Load Vectors
341                STMIA   R9!, {R0-R7}        ; Store Vectors
342                LDMIA   R8!, {R0-R7}        ; Load Handler Addresses
343                STMIA   R9!, {R0-R7}        ; Store Handler Addresses
344                ENDIF
345
346
347; Remap on-chip RAM to address 0
348
349MC_BASE EQU     0xFFFFFF00      ; MC Base Address
350MC_RCR  EQU     0x00            ; MC_RCR Offset
351
352                IF      :DEF:REMAP
353                LDR     R0, =MC_BASE
354                MOV     R1, #1
355                STR     R1, [R0, #MC_RCR]   ; Remap
356                ENDIF
357
358
359; Setup Stack for each mode
360
361                LDR     R0, =Stack_Top
362
363;  Enter Undefined Instruction Mode and set its Stack Pointer
364                MSR     CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit
365                MOV     SP, R0
366                SUB     R0, R0, #UND_Stack_Size
367
368;  Enter Abort Mode and set its Stack Pointer
369                MSR     CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit
370                MOV     SP, R0
371                SUB     R0, R0, #ABT_Stack_Size
372
373;  Enter FIQ Mode and set its Stack Pointer
374                MSR     CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit
375                MOV     SP, R0
376                SUB     R0, R0, #FIQ_Stack_Size
377
378;  Enter IRQ Mode and set its Stack Pointer
379                MSR     CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
380                MOV     SP, R0
381                SUB     R0, R0, #IRQ_Stack_Size
382
383;  Enter Supervisor Mode and set its Stack Pointer
384                MSR     CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
385                MOV     SP, R0
386                SUB     R0, R0, #SVC_Stack_Size
387
388;  Enter User Mode and set its Stack Pointer
389                ; MSR     CPSR_c, #Mode_USR
390                IF      :DEF:__MICROLIB
391
392                EXPORT __initial_sp
393
394                ELSE
395
396                ; No usr mode stack here.
397                ;MOV     SP, R0
398                ;SUB     SL, SP, #USR_Stack_Size
399
400                ENDIF
401
402
403; Enter the C code
404
405                IMPORT  __main
406                LDR     R0, =__main
407                BX      R0
408
409				IMPORT rt_interrupt_enter
410				IMPORT rt_interrupt_leave
411				IMPORT rt_thread_switch_interrupt_flag
412				IMPORT rt_interrupt_from_thread
413				IMPORT rt_interrupt_to_thread
414				IMPORT rt_hw_trap_irq
415
416IRQ_Handler		PROC
417				EXPORT IRQ_Handler
418				STMFD	sp!, {r0-r12,lr}
419				BL	rt_interrupt_enter
420				BL	rt_hw_trap_irq
421				BL	rt_interrupt_leave
422
423				; if rt_thread_switch_interrupt_flag set, jump to
424				; rt_hw_context_switch_interrupt_do and don't return
425				LDR	r0, =rt_thread_switch_interrupt_flag
426				LDR	r1, [r0]
427				CMP	r1, #1
428				BEQ	rt_hw_context_switch_interrupt_do
429
430				LDMFD	sp!, {r0-r12,lr}
431				SUBS	pc, lr, #4
432				ENDP
433
434; /*
435; * void rt_hw_context_switch_interrupt_do(rt_base_t flag)
436; */
437rt_hw_context_switch_interrupt_do	PROC
438				EXPORT rt_hw_context_switch_interrupt_do
439				MOV		r1,  #0			; clear flag
440				STR		r1,  [r0]
441
442				LDMFD	sp!, {r0-r12,lr}; reload saved registers
443				STMFD	sp!, {r0-r3}	; save r0-r3
444				MOV		r1,  sp
445				ADD		sp,  sp, #16	; restore sp
446				SUB		r2,  lr, #4		; save old task's pc to r2
447
448				MRS		r3,  spsr		; get cpsr of interrupt thread
449
450				; switch to SVC mode and no interrupt
451                MSR     cpsr_c, #I_Bit|F_Bit|Mode_SVC
452
453				STMFD	sp!, {r2}		; push old task's pc
454				STMFD	sp!, {r4-r12,lr}; push old task's lr,r12-r4
455				MOV		r4,  r1			; Special optimised code below
456				MOV		r5,  r3
457				LDMFD	r4!, {r0-r3}
458				STMFD	sp!, {r0-r3}	; push old task's r3-r0
459				STMFD	sp!, {r5}		; push old task's cpsr
460				MRS		r4,  spsr
461				STMFD	sp!, {r4}		; push old task's spsr
462
463				LDR		r4,  =rt_interrupt_from_thread
464				LDR		r5,  [r4]
465				STR		sp,  [r5]		; store sp in preempted tasks's TCB
466
467				LDR		r6,  =rt_interrupt_to_thread
468				LDR		r6,  [r6]
469				LDR		sp,  [r6]		; get new task's stack pointer
470
471				LDMFD	sp!, {r4}		; pop new task's spsr
472				MSR		spsr_cxsf, r4
473				LDMFD	sp!, {r4}		; pop new task's psr
474				MSR		cpsr_cxsf, r4
475
476				LDMFD	sp!, {r0-r12,lr,pc}	; pop new task's r0-r12,lr & pc
477				ENDP
478
479                IF      :DEF:__MICROLIB
480
481                EXPORT  __heap_base
482                EXPORT  __heap_limit
483
484                ELSE
485; User Initial Stack & Heap
486                AREA    |.text|, CODE, READONLY
487
488                IMPORT  __use_two_region_memory
489                EXPORT  __user_initial_stackheap
490__user_initial_stackheap
491
492                LDR     R0, =  Heap_Mem
493                LDR     R1, = (Stack_Mem + IRQ_Stack_Size)
494                LDR     R2, = (Heap_Mem +      Heap_Size)
495                LDR     R3, = Stack_Mem
496                BX      LR
497                ENDIF
498
499                END
500