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