1 2 3 4 5 6 7 8 9 10 11 12
13 14 15
16
17 package xdc.runtime;
18
19 /*!
20 * ======== Startup ========
21 * The `xdc.runtime` startup bootstrap
22 *
23 * This module manages the very early startup initialization that occurs
24 * before C's `main()` function is invoked. This initialization typically
25 * consists of setting hardware specific registers that control watchdog
26 * timers, access to memory, cache settings, clock speeds, etc.
27 *
28 * In addition to configuration parameters that allow the user to add custom
29 * startup functions, this module also provides services that allow modules
30 * to automatically add initialiazation functions to the startup sequence.
31 *
32 * @a(Startup Sequence)
33 * The following list defines the startup sequence and, in particular, when
34 * user provided startup functions are invoked:
35 * @p(nlist)
36 * - CPU is initialized and initial C stack setup is performed.
37 * - The function specified by `Startup.resetFxn` is called.
38 * `Startup.resetFxn` is called only on platforms where reset is performed
39 * before running a program. For example, boot code for all TI targets
40 * invokes `Startup.resetFxn`, but this function is not invoked on
41 * Microsoft targets.
42 * - C runtime initialization is performed.
43 * - Functions from the array `Startup.firstFxns` are called.
44 * - All `Mod_Module_startup` functions (see Module Initialization below)
45 * are called in a loop until all such functions return
46 * `{@link #Startup_DONE}` or the `{@link #maxPasses}` threshold is
47 * reached.
48 * - Functions from the array `Startup.lastFxns` are called.
49 * - The function `main` is called.
50 * @p
51 * The steps 4 - 6 occur during C++ static object initialization. Since
52 * the ANSI C++ Language Standard does not provide a means to control
53 * the order of C++ constructors, if a C++ constructor uses an XDC module,
54 * there is no guarantee that the module's startup function already ran.
55 * Therefore, any C++ constructor that needs XDC modules' services should
56 * call `Startup_exec` first to force all startup related functions from
57 * steps 4 - 6 to run, before the constructor uses any XDC module.
58 * @p
59 * Also, if a target does not support C++, the steps 4 - 6 will not run
60 * automatically. It is then up to a user's code to invoke `Startup_exec`,
61 * possibly as the first step in `main`.
62 * @p
63 *
64 * @a(Module Initialization)
65 * Every module can optionally define a startup function which is called
66 * before `main()`. Modules declare that they want to participate in this
67 * startup sequence via the `@ModuleStartup` attribute in the module's spec
68 * file. Modules that use this attribute must also implement the following
69 * startup function:
70 * @p(code)
71 * Int Mod_Module_startup(Int state);
72 * @p
73 * where "Mod" is the name of the module requesting startup support.
74 *
75 * The parameter to the startup function serves as "state variable" whose
76 * initial value will be `Startup_NOTDONE`. If `startup()` returns a value
77 * other than `Startup_DONE`, it will be called in a subsequent pass with this
78 * return value passed in as `state`. To ensure this process terminates,
79 * no startup function is ever called more than `{@link #maxPasses}`
80 * times.
81 *
82 * For situations in which the startup of one module depends upon another
83 * having completed its startup processing, the following function is
84 * automatically defined for all modules and proxies:
85 * @p(code)
86 * Bool Mod_Module_startupDone();
87 * @p
88 * where "Mod" is the name of some module or proxy. These predicates can
89 * be used as guards inside of a startup function to probe whether a
90 * particular module has completed its own startup processing. As a
91 * convenience, the function `Startup_rtsDone()` probes the necessary set of
92 * `xdc.runtime` modules required to support instance `create()` functions, and
93 * should be called before any startup-time instance creation and/or
94 * memory allocation is performed.
95 * @p(code)
96 * Int Mod_Module_startup(Int state)
97 * {
98 * if (!Startup_rtsDone()) {
99 * return (Startup_NOTDONE);
100 * }
101 * .
102 * .
103 * .
104 * return (Startup_DONE);
105 * }
106 * @p
107 *
108 * @a(Examples)
109 * The following code shows how to add custom startup functions to this module.
110 * @p(code)
111 * var Startup = xdc.useModule('xdc.runtime.Startup');
112 * Startup.resetFxn = "&myResetFxn";
113 * Startup.firstFxns[Startup.firstFxns.length++] = "&myFirst";
114 * Startup.lastFxns[Startup.lastFxns.length++] = "&myLast";
115 * @p
116 *
117 */
118 @Template("./Startup.xdt")
119 @DirectCall
120 @RomConsts
121
122 module Startup {
123
124 /*!
125 * ======== DONE ========
126 * Returned from module startup functions no further calls are required
127 */
128 const Int DONE = -1;
129
130 /*!
131 * ======== NOTDONE ========
132 * Initial value of state argument passed to module startup functions
133 */
134 const Int NOTDONE = 0;
135
136 /*!
137 * ======== ModuleView ========
138 * @_nodoc
139 */
140 metaonly struct ModuleView {
141 Bool rtsStartupDone;
142 Bool startupBegun;
143 String resetFxn;
144 String firstFxns[];
145 String lastFxns[];
146 }
147
148 /*!
149 * ======== StartupStateView ========
150 * @_nodoc
151 */
152 metaonly struct StartupStateView {
153 Int order;
154 String moduleName;
155 String done;
156 }
157
158 /*!
159 * ======== rovViewInfo ========
160 * @_nodoc
161 */
162 @Facet
163 metaonly config xdc.rov.ViewInfo.Instance rovViewInfo =
164 xdc.rov.ViewInfo.create({
165 viewMap: [
166 ['Module',
167 {
168 type: xdc.rov.ViewInfo.MODULE,
169 viewInitFxn: 'viewInitModule',
170 structName: 'ModuleView'
171 }
172 ],
173 ['Startup State',
174 {
175 type: xdc.rov.ViewInfo.MODULE_DATA,
176 viewInitFxn: 'viewInitStartupState',
177 structName: 'StartupStateView'
178 }
179 ]
180 ]
181 });
182
183 /*!
184 * ======== maxPasses ========
185 * Max number of iterations over the set of startup functions
186 */
187 config Int maxPasses = 32;
188
189 /*!
190 * ======== InitFxn ========
191 * Type of function assignable to `firstFxns`, `lastFxns`, or `resetFxn`
192 */
193 typedef Void (*InitFxn)();
194
195 /*!
196 * ======== firstFxns ========
197 * List of functions called before module startup
198 *
199 * @see
200 * #xdoc-sect-2 Startup Sequence
201 */
202 config InitFxn firstFxns[length] = [];
203
204 /*!
205 * ======== lastFxns ========
206 * List of functions called after module startup
207 *
208 * @see
209 * #xdoc-sect-2 Startup Sequence
210 */
211 config InitFxn lastFxns[length] = [];
212
213 /*!
214 * ======== resetFxn ========
215 * Function to be called by during initialization
216 *
217 * This function is called only on platforms where reset is performed
218 * before running the program. The purpose of this function is to set up
219 * the hardware registers (cache, external memory interface, etc.) before
220 * any other code executes.
221 *
222 * This function is called as early as possible in the
223 * {@link #xdoc-sect-2 program initialization} process.
224 *
225 * @see
226 * #xdoc-sect-2 Startup Sequence
227 */
228 metaonly config InitFxn resetFxn = null;
229
230 /*!
231 * ======== exec ========
232 * Execute the startup functions of all resident modules
233 *
234 * Note that this function is idempotent, and can be called at any point
235 * in the platform/target startup sequence in which "ordinary" C functions
236 * can execute. By default, this function is called as part of the
237 * standard C++ static initialization sequence.
238 *
239 * If your target compiler does not support C++, this function must be
240 * called at least once prior to using any `xdc.runtime` modules.
241 * Simply call this function at the very beginning of `main()`.
242 */
243 Void exec();
244
245 /*!
246 * ======== rtsDone ========
247 * Query the state of the `xdc.runtime` package
248 *
249 * This function is used by module startup functions to determine
250 * when it is possible to use the `xdc.runtime` modules; e.g. to
251 * allocate memory, create instances managed by some module (even
252 * those outside the `xdc.runtime` package), call a `Log` function,
253 * etc.
254 *
255 * @a(returns)
256 * Returns `TRUE` when all `xdc.runtime` modules have completed
257 * initialization.
258 */
259 Bool rtsDone();
260
261 internal:
262
263 /*!
264 * ======== reset ========
265 * Application-specific reset function
266 *
267 * This function is defined in `Startup.xdt`
268 * (`xdc_runtime_Startup_reset__I`) and is called as early as
269 * possible in the {@link #xdoc-sect-2 program initialization}
270 * process; for many platforms, it is called prior the the
271 * initialization of the C runtime environment.
272 *
273 * @see
274 * #xdoc-sect-2 Startup Sequence
275 */
276 Void reset();
277
278 Void startMods(Int state[], Int len);
279 readonly config Void (*startModsFxn)(Int[], Int) = startMods;
280
281 extern Void execImplFxn() = xdc_runtime_Startup_exec__I;
282
283 readonly config Void (*execImpl)() = execImplFxn;
284
285 typedef Int (*SFxn)(Int);
286 config SFxn sfxnTab[];
287
288 /*!
289 * ======== sfxnRts ========
290 * Array of runtime modules' startup functions
291 *
292 * This array also contains startup functions of the modules that inherit
293 * from interfaces in `xdc.runtime`. Functions added to this array are
294 * called only once before the startup procedure for all modules begins.
295 *
296 * @see
297 * #xdoc-sect-2 Startup Sequence
298 */
299 config Bool sfxnRts[];
300
301 /*!
302 * ======== getState ========
303 * Function that returns the value of the startup state.
304 *
305 * Modules for which the config C code is generated separately, and
306 * possibly before the configuration step is run, must call a function
307 * to get their startup state. They cannot reach into the state array
308 * directly because they don't know their indices in that array.
309 */
310 Int getState(Types.ModuleId id);
311
312 /*!
313 * ======== IdMap ========
314 * keeps track of modules in stateTab and their module IDs for purposes
315 * of the function getState.
316 */
317 struct IdMap {
318 UInt ind;
319 Types.ModuleId modId;
320 }
321
322 struct Module_State {
323 Int *stateTab;
324 Bool execFlag;
325 Bool rtsDoneFlag;
326 };
327
328 }
329 330 331
332