2 * CF_Startup.c - Default init/startup/termination routines for
\r
3 * Embedded Metrowerks C++
\r
5 * Copyright © 1993-1998 Metrowerks, Inc. All Rights Reserved.
\r
6 * Copyright © 2005 Freescale semiConductor Inc. All Rights Reserved.
\r
9 * THEORY OF OPERATION
\r
11 * This version of thestartup code is intended for linker relocated
\r
12 * executables. The startup code will assign the stack pointer to
\r
13 * __SP_INIT, assign the address of the data relative base address
\r
14 * to a5, initialize the .bss/.sbss sections to zero, call any
\r
15 * static C++ initializers and then call main. Upon returning from
\r
16 * main it will call C++ destructors and call exit to terminate.
\r
20 #pragma cplusplus off
\r
25 #include "startcf.h"
\r
26 #include "RuntimeConfig.h"
\r
30 extern unsigned long far _SP_INIT, _SDA_BASE;
\r
31 extern unsigned long far _START_BSS, _END_BSS;
\r
32 extern unsigned long far _START_SBSS, _END_SBSS;
\r
33 extern unsigned long far __DATA_RAM, __DATA_ROM, __DATA_END;
\r
35 /* imported routines */
\r
37 extern void __call_static_initializers(void);
\r
38 extern int main(int, char **);
\r
39 extern void exit(int);
\r
41 /* exported routines */
\r
43 extern void _ExitProcess(void);
\r
44 extern asm void _startup(void);
\r
45 extern void __initialize_hardware(void);
\r
46 extern void __initialize_system(void);
\r
50 * Dummy routine for initializing hardware. For user's custom systems, you
\r
51 * can create your own routine of the same name that will perform HW
\r
52 * initialization. The linker will do the right thing to ignore this
\r
53 * definition and use the version in your file.
\r
55 #pragma overload void __initialize_hardware(void);
\r
56 void __initialize_hardware(void)
\r
61 * Dummy routine for initializing systems. For user's custom systems,
\r
62 * you can create your own routine of the same name that will perform
\r
63 * initialization. The linker will do the right thing to ignore this
\r
64 * definition and use the version in your file.
\r
66 #pragma overload void __initialize_system(void);
\r
67 void __initialize_system(void)
\r
72 * Dummy routine for initializing C++. This routine will get overloaded by the C++ runtime.
\r
74 #pragma overload void __call_static_initializers(void);
\r
75 void __call_static_initializers(void)
\r
80 * Routine to copy a single section from ROM to RAM ...
\r
82 static __declspec(register_abi) void __copy_rom_section(char* dst, const char* src, unsigned long size)
\r
90 * Routine that copies all sections the user marked as ROM into
\r
91 * their target RAM addresses ...
\r
93 * __S_romp is automatically generated by the linker if it
\r
94 * is referenced by the program. It is a table of RomInfo
\r
95 * structures. The final entry in the table has all-zero
\r
98 static void __copy_rom_sections_to_ram(void)
\r
103 * Go through the entire table, copying sections from ROM to RAM.
\r
105 for (info = _S_romp; info->Source != 0L || info->Target != 0L || info->Size != 0; ++info)
\r
106 __copy_rom_section( (char *)info->Target,(char *)info->Source, info->Size);
\r
111 * Exit handler called from the exit routine, if your OS needs
\r
112 * to do something special for exit handling just replace this
\r
113 * routines with what the OS needs to do ...
\r
115 asm void _ExitProcess(void)
\r
122 * Routine to clear out blocks of memory should give good
\r
123 * performance regardless of 68k or ColdFire part.
\r
125 static __declspec(register_abi) void clear_mem(char *dst, unsigned long n)
\r
132 /* align start address to a 4 byte boundary */
\r
133 i = (- (unsigned long) dst) & 3;
\r
143 /* use an unrolled loop to zero out 32byte blocks */
\r
147 lptr = (long *)dst;
\r
164 /* handle any 4 byte blocks left */
\r
167 lptr = (long *)dst;
\r
176 /* handle any byte blocks left */
\r
184 * Startup routine for embedded application ...
\r
187 asm void _startup(void)
\r
189 /* disable interrupts */
\r
192 /* Pre-init SP, in case memory for stack is not valid it should be setup using
\r
193 MEMORY_INIT before __initialize_hardware is called
\r
195 lea __SP_AFTER_RESET,a7;
\r
197 /* initialize memory */
\r
200 /* initialize any hardware specific issues */
\r
201 jsr __initialize_hardware
\r
203 /* setup the stack pointer */
\r
206 /* setup A6 dummy stackframe */
\r
214 /* zero initialize the .bss section */
\r
225 /* call clear_mem with base pointer in a0 and size in d0 */
\r
230 /* zero initialize the .sbss section */
\r
233 lea _START_SBSS, a1
\r
239 lea _START_SBSS, a0
\r
241 /* call clear_mem with base pointer in a0 and size in d0 */
\r
246 /* copy all ROM sections to their RAM locations ... */
\r
247 #if SUPPORT_ROM_TO_RAM
\r
250 * _S_romp is a null terminated array of
\r
251 * typedef struct RomInfo {
\r
252 * unsigned long Source;
\r
253 * unsigned long Target;
\r
254 * unsigned long Size;
\r
257 * Watch out if you're rebasing using _PICPID_DELTA
\r
262 beq __skip_rom_copy__
\r
263 jsr __copy_rom_sections_to_ram
\r
268 * There's a single block to copy from ROM to RAM, perform
\r
269 * the copy directly without using the __S_romp structure
\r
276 beq __skip_rom_copy__
\r
278 move.l #__DATA_END, d0
\r
281 jsr __copy_rom_section
\r
286 /* call C++ static initializers (__sinit__(void)) */
\r
287 jsr __call_static_initializers
\r
289 jsr __initialize_system
\r
291 /* call main(int, char **) */
\r
293 clr.l -(sp) /* clearing a long is ok since it's caller cleanup */
\r
299 /* now call exit(0) to terminate the application */
\r
304 /* should never reach here but just in case */
\r
308 /* exit will never return */
\r