blob: 6ddd120dd088d78b503594ba50e61d3f6ca22b4d [file] [log] [blame]
/* --COPYRIGHT--,ESD
* Copyright (c) 2008-2019 Texas Instruments Incorporated
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License
* v. 1.0 which accompanies this distribution. The Eclipse Public License is
* available at http://www.eclipse.org/legal/epl-v10.html and the Eclipse
* Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Texas Instruments - initial implementation
* --/COPYRIGHT--*/
/*
* ======== Startup.xdc ========
*/
package xdc.runtime;
/*!
* ======== Startup ========
* The `xdc.runtime` startup bootstrap
*
* This module manages the very early startup initialization that occurs
* before C's `main()` function is invoked. This initialization typically
* consists of setting hardware specific registers that control watchdog
* timers, access to memory, cache settings, clock speeds, etc.
*
* In addition to configuration parameters that allow the user to add custom
* startup functions, this module also provides services that allow modules
* to automatically add initialization functions to the startup sequence.
*
* @a(Startup Sequence)
* The following list defines the startup sequence and, in particular, when
* user provided startup functions are invoked:
* @p(nlist)
* - CPU is initialized and initial C stack setup is performed.
* - The function specified by `Startup.resetFxn` is called.
* `Startup.resetFxn` is called only on platforms where reset is performed
* before running a program. For example, boot code for all TI targets
* invokes `Startup.resetFxn`, but this function is not invoked on
* Microsoft targets.
* - C runtime initialization is performed.
* - Functions from the array `Startup.firstFxns` are called.
* - All `Mod_Module_startup` functions (see Module Initialization below)
* are called in a loop until all such functions return
* `{@link #Startup_DONE}` or the `{@link #maxPasses}` threshold is
* reached.
* - Functions from the array `Startup.lastFxns` are called.
* - The function `main` is called.
* @p
* The steps 4 - 6 occur during C++ static object initialization. Since
* the ANSI C++ Language Standard does not provide a means to control
* the order of C++ constructors, if a C++ constructor uses an XDC module,
* there is no guarantee that the module's startup function already ran.
* Therefore, any C++ constructor that needs XDC modules' services should
* call `Startup_exec` first to force all startup related functions from
* steps 4 - 6 to run, before the constructor uses any XDC module.
* @p
* Also, if a target does not support C++, the steps 4 - 6 will not run
* automatically. It is then up to a user's code to invoke `Startup_exec`,
* possibly as the first step in `main`.
* @p
*
* @a(Module Initialization)
* Every module can optionally define a startup function which is called
* before `main()`. Modules declare that they want to participate in this
* startup sequence via the `@ModuleStartup` attribute in the module's spec
* file. Modules that use this attribute must also implement the following
* startup function:
* @p(code)
* Int Mod_Module_startup(Int state);
* @p
* where "Mod" is the name of the module requesting startup support.
*
* The parameter to the startup function serves as "state variable" whose
* initial value will be `Startup_NOTDONE`. If `startup()` returns a value
* other than `Startup_DONE`, it will be called in a subsequent pass with this
* return value passed in as `state`. To ensure this process terminates,
* no startup function is ever called more than `{@link #maxPasses}`
* times.
*
* For situations in which the startup of one module depends upon another
* having completed its startup processing, the following function is
* automatically defined for all modules and proxies:
* @p(code)
* Bool Mod_Module_startupDone();
* @p
* where "Mod" is the name of some module or proxy. These predicates can
* be used as guards inside of a startup function to probe whether a
* particular module has completed its own startup processing. As a
* convenience, the function `Startup_rtsDone()` probes the necessary set of
* `xdc.runtime` modules required to support instance `create()` functions, and
* should be called before any startup-time instance creation and/or
* memory allocation is performed.
* @p(code)
* Int Mod_Module_startup(Int state)
* {
* if (!Startup_rtsDone()) {
* return (Startup_NOTDONE);
* }
* .
* .
* .
* return (Startup_DONE);
* }
* @p
*
* @a(Examples)
* The following code shows how to add custom startup functions to this module.
* @p(code)
* var Startup = xdc.useModule('xdc.runtime.Startup');
* Startup.resetFxn = "&myResetFxn";
* Startup.firstFxns[Startup.firstFxns.length++] = "&myFirst";
* Startup.lastFxns[Startup.lastFxns.length++] = "&myLast";
* @p
*
*/
@Template("./Startup.xdt")
@DirectCall
module Startup {
/*!
* ======== DONE ========
* Returned from module startup functions no further calls are required
*/
const Int DONE = -1;
/*!
* ======== NOTDONE ========
* Initial value of state argument passed to module startup functions
*/
const Int NOTDONE = 0;
/*!
* ======== ModuleView ========
* @_nodoc
*/
metaonly struct ModuleView {
Bool rtsStartupDone;
Bool startupBegun;
String resetFxn;
String firstFxns[];
String lastFxns[];
}
/*!
* ======== StartupStateView ========
* @_nodoc
*/
metaonly struct StartupStateView {
Int order;
String moduleName;
String done;
}
/*!
* ======== rovViewInfo ========
* @_nodoc
*/
@Facet
metaonly config xdc.rov.ViewInfo.Instance rovViewInfo =
xdc.rov.ViewInfo.create({
viewMap: [
['Module',
{
type: xdc.rov.ViewInfo.MODULE,
viewInitFxn: 'viewInitModule',
structName: 'ModuleView'
}
],
['Startup State',
{
type: xdc.rov.ViewInfo.MODULE_DATA,
viewInitFxn: 'viewInitStartupState',
structName: 'StartupStateView'
}
]
]
});
/*!
* ======== maxPasses ========
* Max number of iterations over the set of startup functions
*/
config Int maxPasses = 32;
/*!
* ======== InitFxn ========
* Type of function assignable to `firstFxns`, `lastFxns`, or `resetFxn`
*/
typedef Void (*InitFxn)();
/*!
* ======== firstFxns ========
* List of functions called before module startup
*
* @see
* #xdoc-sect-2 Startup Sequence
*/
config InitFxn firstFxns[length] = [];
/*!
* ======== lastFxns ========
* List of functions called after module startup
*
* @see
* #xdoc-sect-2 Startup Sequence
*/
config InitFxn lastFxns[length] = [];
/*!
* ======== resetFxn ========
* Function to be called by during initialization
*
* This function is called only on platforms where reset is performed
* before running the program. The purpose of this function is to set up
* the hardware registers (cache, external memory interface, etc.) before
* any other code executes.
*
* This function is called as early as possible in the
* {@link #xdoc-sect-2 program initialization} process.
*
* @see
* #xdoc-sect-2 Startup Sequence
*/
metaonly config InitFxn resetFxn = null;
/*!
* ======== exec ========
* Execute the startup functions of all resident modules
*
* Note that this function is idempotent, and can be called at any point
* in the platform/target startup sequence in which "ordinary" C functions
* can execute. By default, this function is called as part of the
* standard C++ static initialization sequence.
*
* If your target compiler does not support C++, this function must be
* called at least once prior to using any `xdc.runtime` modules.
* Simply call this function at the very beginning of `main()`.
*/
Void exec();
/*!
* ======== rtsDone ========
* Query the state of the `xdc.runtime` package
*
* This function is used by module startup functions to determine
* when it is possible to use the `xdc.runtime` modules; e.g. to
* allocate memory, create instances managed by some module (even
* those outside the `xdc.runtime` package), call a `Log` function,
* etc.
*
* @a(returns)
* Returns `TRUE` when all `xdc.runtime` modules have completed
* initialization.
*/
Bool rtsDone();
internal:
/*!
* ======== reset ========
* Application-specific reset function
*
* This function is defined in `Startup.xdt`
* (`xdc_runtime_Startup_reset__I`) and is called as early as
* possible in the {@link #xdoc-sect-2 program initialization}
* process; for many platforms, it is called prior the the
* initialization of the C runtime environment.
*
* @see
* #xdoc-sect-2 Startup Sequence
*/
Void reset();
Void startMods(Int state[], Int len);
readonly config Void (*startModsFxn)(Int[], Int) = startMods;
extern Void execImplFxn() = xdc_runtime_Startup_exec__I;
readonly config Void (*execImpl)() = execImplFxn;
typedef Int (*SFxn)(Int);
config SFxn sfxnTab[];
/*!
* ======== sfxnRts ========
* Array of runtime modules' startup functions
*
* This array also contains startup functions of the modules that inherit
* from interfaces in `xdc.runtime`. Functions added to this array are
* called only once before the startup procedure for all modules begins.
*
* @see
* #xdoc-sect-2 Startup Sequence
*/
config Bool sfxnRts[];
/*!
* ======== getState ========
* Function that returns the value of the startup state.
*
* Modules for which the config C code is generated separately, and
* possibly before the configuration step is run, must call a function
* to get their startup state. They cannot reach into the state array
* directly because they don't know their indices in that array.
*/
Int getState(Types.ModuleId id);
/*!
* ======== IdMap ========
* keeps track of modules in stateTab and their module IDs for purposes
* of the function getState.
*/
struct IdMap {
UInt ind;
Types.ModuleId modId;
}
struct Module_State {
Int *stateTab; /* initially null */
Bool execFlag; /* if true, startup code processing started */
Bool rtsDoneFlag;
};
}