]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/ColdFire_MCF52221_CodeWarrior/sources/startcf.c
Prepare for V7.4.0 release.
[freertos] / FreeRTOS / Demo / ColdFire_MCF52221_CodeWarrior / sources / startcf.c
1 /*\r
2  *    CF_Startup.c - Default init/startup/termination routines for\r
3  *                     Embedded Metrowerks C++\r
4  *\r
5  *    Copyright © 1993-1998 Metrowerks, Inc. All Rights Reserved.\r
6  *    Copyright © 2005 Freescale semiConductor Inc. All Rights Reserved.\r
7  *\r
8  *\r
9  *    THEORY OF OPERATION\r
10  *\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
17  */\r
18 \r
19 #ifdef __cplusplus\r
20 #pragma cplusplus off\r
21 #endif\r
22 #pragma PID off\r
23 #pragma PIC off\r
24 \r
25 #include "startcf.h"\r
26 #include "RuntimeConfig.h"\r
27 \r
28         /* imported data */\r
29 \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
34 \r
35         /* imported routines */\r
36 \r
37 extern void __call_static_initializers(void);\r
38 extern int main(int, char **);\r
39 extern void exit(int);\r
40 \r
41         /* exported routines */\r
42 \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
47 \r
48 \r
49 /*\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
54  */\r
55 #pragma overload void __initialize_hardware(void);\r
56 void __initialize_hardware(void)\r
57 {\r
58 }\r
59 \r
60 /*\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
65  */\r
66 #pragma overload void __initialize_system(void);\r
67 void __initialize_system(void)\r
68 {\r
69 }\r
70 \r
71 /*\r
72  *    Dummy routine for initializing C++.  This routine will get overloaded by the C++ runtime.\r
73  */\r
74 #pragma overload void __call_static_initializers(void);\r
75 void __call_static_initializers(void)\r
76 {\r
77 }\r
78 \r
79 /*\r
80  *      Routine to copy a single section from ROM to RAM ...\r
81  */\r
82 static __declspec(register_abi) void __copy_rom_section(char* dst, const char* src, unsigned long size)\r
83 {\r
84         if (dst != src)\r
85                  while (size--)\r
86                     *dst++ = *src++;\r
87 }\r
88 \r
89 /*\r
90  *      Routine that copies all sections the user marked as ROM into\r
91  *      their target RAM addresses ...\r
92  *\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
96  *      fields.\r
97  */\r
98 static void __copy_rom_sections_to_ram(void)\r
99 {\r
100         RomInfo         *info;\r
101 \r
102         /*\r
103          *      Go through the entire table, copying sections from ROM to RAM.\r
104          */\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
107                                                         \r
108 }\r
109 \r
110 /*\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
114  */\r
115 asm void _ExitProcess(void)\r
116 {\r
117         illegal\r
118         rts\r
119 }\r
120 \r
121 /*\r
122  *    Routine to clear out blocks of memory should give good\r
123  *    performance regardless of 68k or ColdFire part.\r
124  */\r
125 static __declspec(register_abi) void clear_mem(char *dst, unsigned long n)\r
126 {\r
127         unsigned long i;\r
128         long *lptr;\r
129 \r
130         if (n >= 32)\r
131         {\r
132                 /* align start address to a 4 byte boundary */\r
133                 i = (- (unsigned long) dst) & 3;\r
134 \r
135                 if (i)\r
136                 {\r
137                         n -= i;\r
138                         do\r
139                                 *dst++ = 0;\r
140                         while (--i);\r
141                 }\r
142 \r
143                 /* use an unrolled loop to zero out 32byte blocks */\r
144                 i = n >> 5;\r
145                 if (i)\r
146                 {\r
147                         lptr = (long *)dst;\r
148                         dst += i * 32;\r
149                         do\r
150                         {\r
151                                 *lptr++ = 0;\r
152                                 *lptr++ = 0;\r
153                                 *lptr++ = 0;\r
154                                 *lptr++ = 0;\r
155                                 *lptr++ = 0;\r
156                                 *lptr++ = 0;\r
157                                 *lptr++ = 0;\r
158                                 *lptr++ = 0;\r
159                         }\r
160                         while (--i);\r
161                 }\r
162                 i = (n & 31) >> 2;\r
163 \r
164                 /* handle any 4 byte blocks left */\r
165                 if (i)\r
166                 {\r
167                         lptr = (long *)dst;\r
168                         dst += i * 4;\r
169                         do\r
170                                 *lptr++ = 0;\r
171                         while (--i);\r
172                 }\r
173                 n &= 3;\r
174         }\r
175 \r
176         /* handle any byte blocks left */\r
177         if (n)\r
178                 do\r
179                         *dst++ = 0;\r
180                 while (--n);\r
181 }\r
182 \r
183 /*\r
184  *    Startup routine for embedded application ...\r
185  */\r
186 \r
187 asm void _startup(void)\r
188 {\r
189         /* disable interrupts */\r
190     move.w        #0x2700,sr\r
191     \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
194         */\r
195         lea __SP_AFTER_RESET,a7; \r
196 \r
197     /* initialize memory */\r
198     MEMORY_INIT\r
199 \r
200         /* initialize any hardware specific issues */\r
201     jsr           __initialize_hardware   \r
202   \r
203         /* setup the stack pointer */\r
204     lea           _SP_INIT,a7\r
205 \r
206         /* setup A6 dummy stackframe */\r
207     movea.l       #0,a6\r
208     link          a6,#0\r
209 \r
210         /* setup A5 */\r
211     lea           _SDA_BASE,a5\r
212 \r
213 \r
214         /* zero initialize the .bss section */\r
215 \r
216     lea           _END_BSS, a0\r
217     lea           _START_BSS, a1\r
218     suba.l        a1, a0\r
219     move.l        a0, d0\r
220 \r
221     beq           __skip_bss__\r
222 \r
223     lea           _START_BSS, a0\r
224 \r
225     /* call clear_mem with base pointer in a0 and size in d0 */\r
226     jsr           clear_mem\r
227 \r
228 __skip_bss__:\r
229 \r
230         /* zero initialize the .sbss section */\r
231 \r
232     lea           _END_SBSS, a0\r
233     lea           _START_SBSS, a1\r
234     suba.l        a1, a0\r
235     move.l        a0, d0\r
236 \r
237     beq           __skip_sbss__\r
238 \r
239     lea           _START_SBSS, a0\r
240 \r
241     /* call clear_mem with base pointer in a0 and size in d0 */\r
242     jsr           clear_mem\r
243 \r
244 __skip_sbss__:\r
245 \r
246         /* copy all ROM sections to their RAM locations ... */\r
247 #if SUPPORT_ROM_TO_RAM\r
248 \r
249         /*\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
255      *  } RomInfo;\r
256      *\r
257      * Watch out if you're rebasing using _PICPID_DELTA\r
258      */\r
259 \r
260     lea           _S_romp, a0\r
261     move.l        a0, d0\r
262     beq           __skip_rom_copy__            \r
263     jsr           __copy_rom_sections_to_ram\r
264 \r
265 #else\r
266 \r
267         /*\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
270    */\r
271 \r
272     lea           __DATA_RAM, a0\r
273     lea           __DATA_ROM, a1\r
274     \r
275     cmpa          a0,a1\r
276     beq           __skip_rom_copy__\r
277               \r
278     move.l        #__DATA_END, d0\r
279     sub.l         a0, d0\r
280                   \r
281     jsr           __copy_rom_section\r
282 \r
283 #endif\r
284 __skip_rom_copy__:\r
285         \r
286         /* call C++ static initializers (__sinit__(void)) */\r
287         jsr                       __call_static_initializers\r
288 \r
289         jsr                       __initialize_system\r
290 \r
291         /* call main(int, char **) */\r
292         pea                       __argv\r
293         clr.l             -(sp)                         /* clearing a long is ok since it's caller cleanup */\r
294         jsr                       main\r
295         addq.l          #8, sp\r
296         \r
297         unlk              a6\r
298         \r
299         /* now call exit(0) to terminate the application */\r
300         clr.l             -(sp)\r
301         jsr                       exit\r
302         addq.l          #4, sp\r
303 \r
304         /* should never reach here but just in case */\r
305         illegal\r
306         rts\r
307 \r
308         /* exit will never return */\r
309 __argv:\r
310     dc.l          0\r
311 }\r
312 \r