1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
|
/*****************************************************
start12.c - standard startup code
The startup code may be optimized to special user requests
----------------------------------------------------
Copyright (c) Metrowerks, Basel, Switzerland
All rights reserved
Do not modify!
Note: ROM libraries are not implemented in this startup code
Note: C++ destructors of global objects are NOT yet supported in the HIWARE Object File Format.
To use this feature, please build your application with the ELF object file format.
*****************************************************/
#include "hidef.h"
#include "start12.h"
/* Macros to control how the startup code handles the COP: */
/* #define _DO_FEED_COP_ : do feed the COP */
/* #define _DO_ENABLE_COP_: do enable the COP */
/* #define _DO_DISABLE_COP_: disable the COP */
/* Without defining any of these, the startup code does NOT handle the COP */
#pragma DATA_SEG __NEAR_SEG STARTUP_DATA /* _startupData can be accessed using 16 bit accesses. This is needed because it contains the stack top, and without stack, far data cannot be accessed */
struct _tagStartup _startupData; /* read-only: */
/* _startupData is allocated in ROM and */
/* initialized by the linker */
#pragma DATA_SEG DEFAULT
#if defined(FAR_DATA)
#include "non_bank.sgm"
/* the init function must be in non banked memory if banked variables are used */
/* because _SET_PAGE is called, which may change any page register. */
#ifdef __cplusplus
extern "C"
#endif
void _SET_PAGE(void); /* the inline assembler needs a prototype */
/* this is a runtime routine with a special */
/* calling convention, dont use it in c code! */
static void Init(void);
static void Fini(void);
#else
#include "default.sgm"
#if defined( __BANKED__) || defined(__LARGE__)
static void __far Init(void);
static void __far Fini(void);
#endif /* defined( __BANKED__) || defined(__LARGE__) */
#endif /* FAR_DATA */
/* define value and bits for Windef Register */
#ifdef HC812A4
#define WINDEF (*(volatile unsigned char*) 0x37)
#if defined( __BANKED__) || defined(__LARGE__) || defined(__PPAGE__)
#define __ENABLE_PPAGE__ 0x40
#else
#define __ENABLE_PPAGE__ 0x0
#endif
#if defined(__DPAGE__)
#define __ENABLE_DPAGE__ 0x80
#else
#define __ENABLE_DPAGE__ 0x0
#endif
#if defined(__EPAGE__)
#define __ENABLE_EPAGE__ 0x20
#else
#define __ENABLE_EPAGE__ 0x0
#endif
#endif /* HC812A4 */
#ifdef _HCS12_SERIALMON
/* for Monitor based software remap the RAM & EEPROM to adhere
to EB386. Edit RAM and EEPROM sections in PRM file to match these. */
#define ___INITRM (*(volatile unsigned char *) 0x0010)
#define ___INITRG (*(volatile unsigned char *) 0x0011)
#define ___INITEE (*(volatile unsigned char *) 0x0012)
#endif
#if defined(_DO_FEED_COP_)
#define __FEED_COP_IN_HLI() } __asm movb #0x55, _COP_RST_ADR; __asm movb #0xAA, _COP_RST_ADR; __asm {
#else
#define __FEED_COP_IN_HLI() /* do nothing */
#endif
#if !defined(FAR_DATA) && (defined( __BANKED__) || defined(__LARGE__))
static void __far Init(void)
#else
static void Init(void)
#endif
{
/* purpose: 1) zero out RAM-areas where data is allocated */
/* 2) copy initialization data from ROM to RAM */
/* 3) call global constructors in C++ */
/* called from: _Startup, LibInits */
__asm {
ZeroOut:
#if defined(__HIWARE_OBJECT_FILE_FORMAT__) && defined(__LARGE__)
LDX _startupData.pZeroOut:1 ; in the large memory model in the HIWARE format, pZeroOut is a 24 bit pointer
#else
LDX _startupData.pZeroOut ; *pZeroOut
#endif
LDY _startupData.nofZeroOuts ; nofZeroOuts
BEQ CopyDown ; if nothing to zero out
NextZeroOut: PSHY ; save nofZeroOuts
#ifdef FAR_DATA
LDAB 1,X+ ; load page of destination address
LDY 2,X+ ; load offset of destination address
__PIC_JSR(_SET_PAGE) ; sets the page in the correct page register
#else /* FAR_DATA */
LDY 2,X+ ; start address and advance *pZeroOut (X = X+4)
#endif /* FAR_DATA */
LDD 2,X+ ; byte count
#ifdef __OPTIMIZE_FOR_SIZE__ /* -os, default */
NextWord: CLR 1,Y+ ; clear memory byte
__FEED_COP_IN_HLI() ; feed the COP if necessary /*lint !e505 !e522 asm code */
DBNE D, NextWord ; dec byte count
#else
LSRD ; /2 and save bit 0 in the carry
PSHX
LDX #0
LoopClrW: STX 2,Y+ ; Word-Clear
__FEED_COP_IN_HLI() ; feed the COP if necessary /*lint !e505 !e522 asm code */
DBNE D, LoopClrW
PULX
BCC LastClr ; handle last byte
CLR 1,Y+
LastClr:
#endif
PULY ; restore nofZeroOuts
DEY ; dec nofZeroOuts
BNE NextZeroOut
CopyDown:
#ifdef __ELF_OBJECT_FILE_FORMAT__
LDX _startupData.toCopyDownBeg ; load address of copy down desc.
#else
LDX _startupData.toCopyDownBeg:2 ; load address of copy down desc.
#endif
NextBlock:
LDD 2,X+ ; size of init-data -> D
BEQ funcInits ; end of copy down desc.
#ifdef FAR_DATA
PSHD ; save counter
LDAB 1,X+ ; load destination page
LDY 2,X+ ; destination address
__PIC_JSR(_SET_PAGE) ; sets the destinations page register
PULD ; restore counter
#else /* FAR_DATA */
LDY 2,X+ ; load destination address
#endif /* FAR_DATA */
#ifdef __OPTIMIZE_FOR_SIZE__ /* -os, default */
Copy: MOVB 1,X+,1,Y+ ; move a byte from ROM to the data area
__FEED_COP_IN_HLI() ; feed the COP if necessary /*lint !e505 !e522 asm code */
DBNE D,Copy ; copy-byte loop
#else
LSRD ; /2 and save bit 0 in the carry
Copy: MOVW 2,X+,2,Y+ ; move a word from ROM to the data area
__FEED_COP_IN_HLI() ; feed the COP if necessary /*lint !e505 !e522 asm code */
DBNE D,Copy ; copy-word loop
BCC NextBlock ; handle last byte?
MOVB 1,X+,1,Y+ ; copy the last byte
#endif
BRA NextBlock
funcInits: ; call of global construtors is only in c++ necessary
#if defined(__cplusplus)
#if defined(__ELF_OBJECT_FILE_FORMAT__)
#if defined( __BANKED__) || defined(__LARGE__)
LDY _startupData.nofInitBodies; load number of cpp.
BEQ done ; if cppcount == 0, goto done
LDX _startupData.initBodies ; load address of first module to initialize
nextInit:
LEAX 3,X ; increment to next init
PSHX ; save address of next function to initialize
PSHY ; save cpp counter
CALL [-3,X] ; use double indirect call to load the page register also
PULY ; restore cpp counter
PULX ; restore actual address
DEY ; decrement cpp counter
BNE nextInit
#else /* defined( __BANKED__) || defined(__LARGE__) */
LDD _startupData.nofInitBodies; load number of cpp.
BEQ done ; if cppcount == 0, goto done
LDX _startupData.initBodies ; load address of first module to initialize
nextInit:
LDY 2,X+ ; load address of first module to initialize
PSHD
PSHX ; save actual address
JSR 0,Y ; call initialization function
PULX ; restore actual address
PULD ; restore cpp counter
DBNE D, nextInit
#endif /* defined( __BANKED__) || defined(__LARGE__) */
#else /* __ELF_OBJECT_FILE_FORMAT__ */
LDX _startupData.mInits ; load address of first module to initialize
#if defined( __BANKED__) || defined(__LARGE__)
nextInit: LDY 3,X+ ; load address of initialization function
BEQ done ; stop when address == 0
; in common environments the offset of a function is never 0, so this test could be avoided
#ifdef __InitFunctionsMayHaveOffset0__
BRCLR -1,X, done, 0xff ; stop when address == 0
#endif /* __InitFunctionsMayHaveOffset0__ */
PSHX ; save address of next function to initialize
CALL [-3,X] ; use double indirect call to load the page register also
#else /* defined( __BANKED__) || defined(__LARGE__) */
nextInit:
LDY 2,X+ ; load address of first module to initialize
BEQ done ; stop when address of function == 0
PSHX ; save actual address
JSR 0,Y ; call initialization function
#endif /* defined( __BANKED__) || defined(__LARGE__) */
PULX ; restore actual address
BRA nextInit
#endif /* __ELF_OBJECT_FILE_FORMAT__ */
done:
#endif /* __cplusplus */
}
}
#if defined( __ELF_OBJECT_FILE_FORMAT__) && defined(__cplusplus )
#if !defined(FAR_DATA) && (defined( __BANKED__) || defined(__LARGE__))
static void __far Fini(void)
#else
static void Fini(void)
#endif
{
/* purpose: 1) call global destructors in C++ */
__asm {
#if defined( __BANKED__) || defined(__LARGE__)
LDY _startupData.nofFiniBodies; load number of cpp.
BEQ done ; if cppcount == 0, goto done
LDX _startupData.finiBodies ; load address of first module to finalize
nextInit2:
LEAX 3,X ; increment to next init
PSHX ; save address of next function to finalize
PSHY ; save cpp counter
CALL [-3,X] ; use double indirect call to load the page register also
PULY ; restore cpp counter
PULX ; restore actual address
DEY ; decrement cpp counter
BNE nextInit2
#else /* defined( __BANKED__) || defined(__LARGE__) */
LDD _startupData.nofFiniBodies; load number of cpp.
BEQ done ; if cppcount == 0, goto done
LDX _startupData.finiBodies ; load address of first module to finalize
nextInit2:
LDY 2,X+ ; load address of first module to finalize
PSHD
PSHX ; save actual address
JSR 0,Y ; call finalize function
PULX ; restore actual address
PULD ; restore cpp counter
DBNE D, nextInit2
#endif /* defined( __BANKED__) || defined(__LARGE__) */
done:;
}
}
#endif
#include "non_bank.sgm"
#pragma MESSAGE DISABLE C12053 /* Stack-pointer change not in debugging-information */
#pragma NO_FRAME
#pragma NO_ENTRY
#pragma NO_EXIT
#ifdef __cplusplus
extern "C"
#endif
/* The function _Startup must be called in order to initialize global variables and to call main */
/* You can adapt this function or call it from your startup code to implement a different startup */
/* functionality. */
/* You should also setup the needed IO registers as WINDEF (HC12A4 only) or the COP registers to run */
/* on hardware */
/* to set the reset vector several ways are possible : */
/* 1. define the function with "interrupt 0" as done below in the first case */
/* 2. add the following line to your prm file : VECTOR ADDRESS 0xfffe _Startup */
/* of course, even more posibilities exists */
/* the reset vector must be set so that the application has a defined entry point */
#define STARTUP_FLAGS_NOT_INIT_SP (1<<1)
#if defined(__SET_RESET_VECTOR__)
void __interrupt 0 _Startup(void) {
#else
void _Startup(void) {
#endif
/* purpose: 1) initialize the stack
2) initialize the RAM, copy down init data etc (Init)
3) call main;
parameters: NONE
called from: _PRESTART-code generated by the Linker
or directly referenced by the reset vector */
for(;;) { /* forever: initialize the program; call the root-procedure */
if (!(_startupData.flags&STARTUP_FLAGS_NOT_INIT_SP)) {
/* initialize the stack pointer */
INIT_SP_FROM_STARTUP_DESC(); /*lint !e522 asm code */ /* HLI macro definition in hidef.h */
}
#ifdef _HCS12_SERIALMON
/* for Monitor based software remap the RAM & EEPROM to adhere
to EB386. Edit RAM and EEPROM sections in PRM file to match these. */
___INITRG = 0x00; /* lock registers block to 0x0000 */
___INITRM = 0x39; /* lock Ram to end at 0x3FFF */
___INITEE = 0x09; /* lock EEPROM block to end at 0x0fff */
#endif
/* Here user defined code could be inserted, the stack could be used */
#if defined(_DO_DISABLE_COP_)
_DISABLE_COP();
#endif
/* Example : Set up WinDef Register to allow Paging */
#ifdef HC812A4 /* HC12 A4 derivative needs WINDEF to configure which pages are available */
#if (__ENABLE_EPAGE__ != 0 || __ENABLE_DPAGE__ != 0 || __ENABLE_PPAGE__ != 0)
WINDEF= __ENABLE_EPAGE__ | __ENABLE_DPAGE__ | __ENABLE_PPAGE__;
#endif
#endif
Init(); /* zero out, copy down, call constructors */
/* Here user defined code could be inserted, all global variables are initilized */
#if defined(_DO_ENABLE_COP_)
_ENABLE_COP(1);
#endif
/* call main() */
(*_startupData.main)();
/* call destructors. Only done when this file is compiled as C++ and for the ELF object file format */
/* the HIWARE object file format does not support this */
#if defined( __ELF_OBJECT_FILE_FORMAT__) && defined(__cplusplus )
Fini();
#endif
} /* end loop forever */
}
|