Add startup from nut/os.
[bertos.git] / cpu / arm / hw / crtat91sam7s256_rom.S
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
6  * Bertos is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * As a special exception, you may use this file as part of a free software
21  * library without restriction.  Specifically, if other files instantiate
22  * templates or use macros or inline functions from this file, or you compile
23  * this file and link it with other files to produce an executable, this
24  * file does not by itself cause the resulting executable to be covered by
25  * the GNU General Public License.  This exception does not however
26  * invalidate any other reasons why the executable file might be covered by
27  * the GNU General Public License.
28  *
29  * Copyright 2007 Develer S.r.l. (http://www.develer.com/)
30  *
31  * -->
32  *
33  * \version $Id: $
34  *
35  * \author Francesco Sacchi <batt@develer.com>
36  *
37  * \brief AT91SAM7S256 CRT, adapted from NUt/OS, see license below.
38  */
39
40 /*
41  * Copyright (C) 2005-2007 by egnite Software GmbH. All rights reserved.
42  *
43  * Redistribution and use in source and binary forms, with or without
44  * modification, are permitted provided that the following conditions
45  * are met:
46  *
47  * 1. Redistributions of source code must retain the above copyright
48  *    notice, this list of conditions and the following disclaimer.
49  * 2. Redistributions in binary form must reproduce the above copyright
50  *    notice, this list of conditions and the following disclaimer in the
51  *    documentation and/or other materials provided with the distribution.
52  * 3. Neither the name of the copyright holders nor the names of
53  *    contributors may be used to endorse or promote products derived
54  *    from this software without specific prior written permission.
55  *
56  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
57  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
58  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
59  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
60  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
61  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
62  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
63  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
64  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
65  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
66  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67  * SUCH DAMAGE.
68  *
69  * For additional information see http://www.ethernut.de/
70  *
71  */
72
73 #include <cfg/clock.h>
74 #include <cfg/memory.h>
75
76 #include <arch/arm.h>
77
78 #ifndef PLL_MUL_VAL
79 #define PLL_MUL_VAL 72
80 #endif
81
82 #ifndef PLL_DIV_VAL
83 #define PLL_DIV_VAL 14
84 #endif
85
86 #if MASTER_CLOCK_PRES == 1
87 #define AT91MCK_PRES    PMC_PRES_CLK
88 #elif MASTER_CLOCK_PRES == 4
89 #define AT91MCK_PRES    PMC_PRES_CLK_4
90 #elif MASTER_CLOCK_PRES == 8
91 #define AT91MCK_PRES    PMC_PRES_CLK_8
92 #elif MASTER_CLOCK_PRES == 16
93 #define AT91MCK_PRES    PMC_PRES_CLK_16
94 #elif MASTER_CLOCK_PRES == 32
95 #define AT91MCK_PRES    PMC_PRES_CLK_32
96 #elif MASTER_CLOCK_PRES == 64
97 #define AT91MCK_PRES    PMC_PRES_CLK_64
98 #else
99 #define AT91MCK_PRES    PMC_PRES_CLK_2
100 #endif
101
102 #ifndef IRQ_STACK_SIZE
103 #define IRQ_STACK_SIZE  512
104 #endif
105
106 #ifndef FIQ_STACK_SIZE
107 #define FIQ_STACK_SIZE  256
108 #endif
109
110 #ifndef ABT_STACK_SIZE
111 #define ABT_STACK_SIZE  128
112 #endif
113
114 #ifndef UND_STACK_SIZE
115 #define UND_STACK_SIZE  128
116 #endif
117
118
119 /*
120  * Section 0: Vector table and reset entry.
121  */
122         .section .init0,"ax",%progbits
123
124         .global __vectors
125 __vectors:
126         ldr     pc, [pc, #24]   /* Reset */
127         ldr     pc, [pc, #24]   /* Undefined instruction */
128         ldr     pc, [pc, #24]   /* Software interrupt */
129         ldr     pc, [pc, #24]   /* Prefetch abort */
130         ldr     pc, [pc, #24]   /* Data abort */
131         ldr     pc, [pc, #24]   /* Reserved */
132
133         /*
134          * On IRQ the PC will be loaded from AIC_IVR, which
135          * provides the address previously set in AIC_SVR.
136          * The interrupt routine will be called in ARM_MODE_IRQ
137          * with IRQ disabled and FIQ unchanged.
138          */
139         ldr     pc, [pc, #-0xF20]   /* Interrupt request, auto vectoring. */
140         ldr     pc, [pc, #-0xF20]   /* Fast interrupt request, auto vectoring. */
141
142         .word   _start
143         .word   __undef
144         .word   __swi
145         .word   __prefetch_abort
146         .word   __data_abort
147
148         .weak   __undef
149         .set    __undef, __xcpt_dummy
150         .weak   __swi
151         .set    __swi, __xcpt_dummy
152         .weak   __prefetch_abort
153         .set    __prefetch_abort, __xcpt_dummy
154         .weak   __data_abort
155         .set    __data_abort, __xcpt_dummy
156
157         .global __xcpt_dummy
158 __xcpt_dummy:
159         b       __xcpt_dummy
160
161         .ltorg
162 /*
163  * Section 1: Hardware initialization.
164  */
165         .section .init1, "ax", %progbits
166         .globl  _start
167 _start:
168
169         /*
170          * Use 2 cycles for flash access.
171          */
172         ldr     r1, =MC_BASE
173         mov     r0, #MC_FWS_2R3W
174         str     r0, [r1, #MC_FMR_OFF]
175
176         /*
177          * Disable all interrupts. Useful for debugging w/o target reset.
178          */
179         ldr     r1, =AIC_BASE
180         mvn     r0, #0
181         str     r0, [r1, #AIC_EOICR_OFF]
182         str     r0, [r1, #AIC_IDCR_OFF]
183
184         /*
185          * The watchdog is enabled after processor reset. Disable it.
186          */
187         ldr     r1, =WDT_BASE
188         ldr     r0, =WDT_WDDIS
189         str     r0, [r1, #WDT_MR_OFF]
190
191         /*
192          * Enable the main oscillator. Set startup time of 6 * 8 slow 
193          * clock cycles and wait until oscillator is stabilized.
194          */
195         ldr     r1, =PMC_BASE
196         mov     r0, #(6 << 8)
197         orr     r0, r0, #CKGR_MOSCEN
198         str     r0, [r1, #CKGR_MOR_OFF]
199 wait_moscs:
200         ldr     r0, [r1, #PMC_SR_OFF]
201         tst     r0, #PMC_MOSCS
202         beq     wait_moscs
203
204         /*
205          * Set PLL:
206          * PLLfreq = crystal / divider * (multiplier + 1)
207          * Wait 28 clock cycles until PLL is locked.
208          */
209         ldr     r0, =((PLL_MUL_VAL << CKGR_MUL_LSB) | (28 << CKGR_PLLCOUNT_LSB) | (PLL_DIV_VAL << CKGR_DIV_LSB))
210
211         str     r0, [r1, #CKGR_PLLR_OFF]
212 wait_lock:
213         ldr     r0, [r1, #PMC_SR_OFF]
214         tst     r0, #PMC_LOCK
215         beq     wait_lock
216
217         /*
218          * Set master clock prescaler.
219          */
220         mov     r0, #AT91MCK_PRES
221         str     r0, [r1, #PMC_MCKR_OFF]
222 wait_presrdy:
223         ldr     r0, [r1, #PMC_SR_OFF]
224         tst     r0, #PMC_MCKRDY
225         beq     wait_presrdy
226
227         /*
228          * Switch to PLL clock. Trying to set this together with the
229          * prescaler fails for unknown reason.
230          */
231         ldr     r0, [r1, #PMC_MCKR_OFF]
232         orr     r0, r0, #PMC_CSS_PLL_CLK
233         str     r0, [r1, #PMC_MCKR_OFF]
234 wait_pllsel:
235         ldr     r0, [r1, #PMC_SR_OFF]
236         tst     r0, #PMC_MCKRDY
237         beq     wait_pllsel
238
239         /*
240          * Enable external reset key.
241          */
242         ldr     r0, =(RSTC_KEY | RSTC_URSTEN)
243         ldr     r1, =RSTC_MR
244         str     r0, [r1, #0]
245         
246         b       __set_stacks
247
248         .ltorg
249
250
251 /*
252  * Section 2: Set stack pointers.
253  */
254         .section .init2,"ax",%progbits        
255         .global __set_stacks
256 __set_stacks:
257
258         /*
259          * Set exception stack pointers and enable interrupts.
260          */
261         ldr     r0, =__exp_stack
262         msr     CPSR_c, #ARM_MODE_FIQ | 0xC0
263         mov     r13, r0
264         sub     r0, r0, #FIQ_STACK_SIZE
265         msr     CPSR_c, #ARM_MODE_IRQ | 0xC0
266         mov     r13, r0
267         sub     r0, r0, #IRQ_STACK_SIZE
268         msr     CPSR_c, #ARM_MODE_ABORT | 0xC0
269         mov     r13, r0
270         sub     r0, r0, #ABT_STACK_SIZE
271         msr     CPSR_c, #ARM_MODE_UNDEF | 0xC0
272         mov     r13, r0
273         sub     r0, r0, #UND_STACK_SIZE
274         msr     CPSR_c, #ARM_MODE_SVC | 0xC0
275         mov     r13, r0
276         b       __enter_mode
277         
278         .ltorg
279
280 /*
281  * Section 3: Enter user mode.
282  */
283         .section .init3,"ax",%progbits
284
285         .global __enter_mode
286 __enter_mode:
287
288         b       __clear_bss
289
290         .ltorg
291
292 /*
293  * Section 4: Clear bss and copy data.
294  */
295         .section .init4,"ax",%progbits
296         .global __clear_bss
297 __clear_bss:
298
299         ldr     r1, =__bss_start
300         ldr     r2, =__bss_end
301         ldr     r3, =0
302
303 _40:
304         cmp     r1, r2
305         strne   r3, [r1], #+4
306         bne     _40
307
308         /*
309          * Relocate .data section (Copy from ROM to RAM).
310          */
311         ldr     r1, =__etext
312         ldr     r2, =__data_start
313         ldr     r3, =__data_end
314
315 _41:
316         cmp     r2, r3
317         ldrlo   r0, [r1], #4
318         strlo   r0, [r2], #4
319         blo     _41
320
321         /*
322          * Initialize user stack pointer.
323          */
324         ldr     r13, =__stack
325         b       __call_rtos
326
327         .ltorg
328
329 /*
330  * Section 5: Call RTOS
331  */
332         .section .init5,"ax",%progbits
333         .global __call_rtos
334 __call_rtos:
335
336         /*
337          * Jump to Nut/OS initialization.
338          */
339         ldr     r0, =NutInit
340         bx      r0
341
342 End:
343         b       End
344
345         .ltorg