Using xdc.runtime System

From RTSC-Pedia

Jump to: navigation, search
revision tip
—— LANDSCAPE orientation
[printable version]  [offline version]offline version generated on 24-Feb-2019 01:02 UTC 

Using xdc.runtime System

How to boot, print a message, and shutdown



The xdc.runtime package contains two modules that together provide the minimal set of services necessary to enable modular application startup and shutdown as well as basic message display.

  1. Startup - a module that provides a framework for the orderly initialization of modules prior to main(), and
  2. System - a module that provides exit handling similar to the ANSI C atexit() mechanism as well as basic printf() message output.

Use of these modules is illustrated below by a series of examples that use one of two other distinguished xdc.runtime modules that provide the "back end" support functions required by the System module:

  1. SysMin - a self-contained module appropriate for deeply embedded applications or early system development, and
  2. SysStd - a module that relies on standard ANSI C runtime library functions such as putchar() and fflush() and is appropriate for systems with an already functional ANSI C Standard I/O library.


Each embedded application runs in a unique environment with specific resource requirements and, as a result, adopts application-specific policies for basic character output, application startup, and shutdown. The xdc.runtime package provides an extensible platform-independent framework for application startup (from processor boot), initialization, and shutdown. In addition, it provides a platform-independent interface for character output which allows for platform-specific implementations that can range from simple memory writes to a circular buffer to flow-controlled output via a platform-specific I/O device.

The System and Startup modules provide the foundation for early application "bring up", and continue to serve in deployed applications to manage the initialization of higher-level services and provide simple "fail-safe" diagnostics. These modules together with, say, the SysMin system support module are sufficient to enable complete C-based application development using "printf" debugging.

Because Startup and System are platform-independent, entire embedded applications can be ported to alternative execution environments (Unix or Windows workstations, for example) without making any change to their sources. Porting to a different environment involves a simple reconfiguration of the application to replace the System support module with an implementation appropriate for the new execution environment; no change to the application's sources are required and, if you're porting between platforms with the same target, no recompilation is required.


Every module in an application can optionally supply a "startup" function that must be run prior to the first use of the module by application code. This startup function might read memory mapped registers necessary to initialize the module's internal data structures, for example. Modules specify that they have startup functions via the @ModuleStartup attribute in their module specification file. The Startup module runs these startup functions prior to the application's main() entry point and provides numerous configuration parameters to enable the developer to augment the startup process with custom C functions.

The System module, on the other hand, provides mechanisms for modules (initialized under the control of Startup) to shutdown. Between the initialization of the application's modules and shutdown of the application, System is also used to perform simple character output via "printf-like" methods. By not supporting all the format specifications required by a full ANSI C Standard implementation of printf(), these methods provide a much smaller and faster implementation that satisfies most uses and can be embedded in very small applications.

Finally, the System module also provides a low-level "gate" that is used to protect global data structures maintained within the xdc.runtime package; this gate allows multi-threaded applications to safely use the xdc.runtime package's modules concurrently. This same gate can also be used by application code.

Startup and initialization

Startup and initialization.  The Startup module provides a standard mechanism for the orderly initialization of all modules within an application before main() begins. The Startup module defines just two entry points that need to be integrated into the execution environment's startup code. Once this is done, Startup handles the initialization of all other modules in the application - xdc.runtime modules as well as any other modules used by the application.

Using xdc.runtime Startup describes the startup (and shutdown) process in detail and provides the information required to port applications from your development environment to your custom hardware.

Character output and shutdown

Character output and shutdown.  The System module provides a facade for two key system level areas: character output and program termination. Since application termination and basic character output can be very different depending on the product and stage of development, the System module relies on a user supplied module that implements these very basic functions (defined by the ISystemSupport interface). Developers specify the module that implements these functions by setting the System.SupportProxy configuration parameter.

System Support Architecture

The xdc.runtime package includes two system support proxy options: SysMin and SysStd. These modules are sufficient for early development but, because they are written to be 100% portable, they don't take advantage of any platform-specific features (such as an embedded UART). Fortunately it is easy to create a custom system support module that can be bound to System as easily as SyMin or SysStd and takes full advantage advantage of your platform's execution environment. The System Support Section contains more details about how to create system support modules and includes a simple example that can easily be extended to leverage unique platform capabilities.

Concurrency support

Concurrency support.  The System module is a gated module. The gate associated with the System module, also called the "System gate", is a used for two purposes:

  1. to protect critical regions within the xdc.runtime package by serializing concurrent accesses to global data; and
  2. to protect small critical regions within the application via the Gate_enterSystem() and Gate_leaveSystem() APIs.

Concurrency Architecture

For more information about using the xdc.runtime package in multi-threaded applications, see Multi-Threading Support. Using xdc.runtime Gates contains more details about gates, how to protect shared data structures using gates, and how to create new gates.


Users can configure their application to specify on a per-application basis:

  • what module provides the output and shutdown services,
  • the maximum number of "at exit" handlers can can be dynamically added at runtime,
  • a custom reset handler called as early as possible during the boot process,
  • a list of functions to be called prior to any module initialization function, and
  • a list of functions to be called after all module initialization functions have completed.

System support proxy

System support proxy.  The System module declares a SupportProxy configuration parameter that allows the developer to "bind" alternate implementations of low-level functions required for the operation of the System module's methods. The SupportProxy configuration parameter is unique in that rather than it being set to a string or numeric value, it must be set to a module that inherits from the xdc.runtime.ISystemSupport interface. This module implements the functions (abort, exit, flush, putch and ready) required by the System module to operate.

The xdc.runtime package includes two modules that implement the ISystemSupport interface:

  1. xdc.runtime.SysStd: relies on a functioning ANSI C Standard Library, and
  2. xdc.runtime.SysMin: completely self-contained implementation used for footprint or performance constrained applications or for low-level diagnostic support within larger deployed applications.

The following configuration script statements set the System module's SupportProxy to xdc.runtime.SysStd:

var System = xdc.useModule("xdc.runtime.System");
System.SupportProxy = xdc.useModule("xdc.runtime.SysStd");

If you want to minimize your application's memory footprint, you should use SysMin as the SupportProxy by either omitting the lines above or substituting SysMin for SysStd above.

The System gate

The System gate.  The System gate must be restrictive enough to insure that critical regions protected by this gate are never "entered" by more than one thread at a time. For example, if these regions can be accessed by both interrupt service routines (ISRs) and non-ISR code, the gate must disable interrupts on entering and restore interrupts on leaving.

If the System gate is not configured by your configuration script or some RTOS package in the system, it will default to an instance of GateNull. Since GateNull provides no synchronization, it is usually a mistake to use GateNull to create the System gate in multi-threaded applications.

Multi-threaded applications must either

  1. configure the System module's gate with a mutex that serializes all threads that access the xdc.runtime modules, or
  2. ensure that there are no concurrent accesses to the xdc.runtime modules

For example, the following configuration script sets the System module's gate to an instance of the GateHwi module in the ti.sysbios.gates package. This allows any xdc.runtime module to be used from any ti.sysbios thread — including hardware interrupt service routines.

GateHwi = xdc.useModule("ti.sysbios.gates.GateHwi");
System.common$.gate = GateHwi.create();

The ti.sysbios package automatically configures the System gate as shown above. So there is no need to add these lines to your configuration scripts. However, if you are using an RTOS that does not implicitly set System.common$.gate, it's critically important that you add RTOS-specific lines to your configuration script similar to those shown above.


In the table below, we provide examples that illustrate the key capabilities of the Startup and System modules.

Example Description Purpose
Example 1 Using System to print a message a minimal "hello world" example to illustrate using System in existing code bases

Although it is possible to use one of the ISystemSupport modules that are part of the xdc.runtime package to complete the implementation of the System module (see below), you may find it necessary to "port" the System module to your platform. The table below lists examples of custom ISystemSupport modules that can serve as a basis for platform-specific customization. See Extending xdc.runtime System for more information about customizing System for you needs.

Example Description Purpose
Example 1 Creating a new ISystemSupport module illustrate adding a minimal System support module appropriate for deeply embedded devices

Built-in System Support Modules

The xdc.runtime package includes two built-in System support modules:

  1. SysMin - minimal support suitable for deeply embedded systems, and
  2. SysStd - a support module that assumes a thread-safe ANSI C Standard Library.

These modules inherit the xdc.runtime.ISystemSupport interface and are used to provide the underlying services required by the System module via the System module's SupportProxy configuration parameter.

The following sections briefly describe these modules and show examples of their use. Extending xdc.runtime System describes how to create additional System support modules.

The SysStd Module

SysStd directly calls the ANSI Standard C Library runtime functions putchar and fflush. It does not perform any additional functionality. Both the SysStd module's abort and exit functions flush the standard output via the standard C runtime fflush function.

To use this module as the System module's support proxy you must explicitly set this in your configuration script; otherwise the SysMin module with be used.

var System = xdc.useModule("xdc.runtime.System");
System.SupportProxy = xdc.useModule("xdc.runtime.SysStd");

The SysMin Module

SysMin is the System module's default Support Proxy; it is intended to be flexible but minimal. When SysMin is the Support Proxy, all output—from functions such as System_printf() and System_putch()—goes into an internally managed buffer. There are several configuration parameters that let you change the features as needed.

  • bufSize. The size in MAUs of the internal buffer used for output.
  • sectionName. The section in which the internal buffer should be created.
  • flushAtExit. If true, the internal buffer is flushed via SysMin_flush() during a System_exit() or System_abort().

If an application wants to minimize the memory footprint, it should use the SysMin module as the Support Proxy. If the application needs minimal printing capabilities, the bufSize configuration parameter can be set to 0, and flushAtExit can be set to false to further reduce the footprint.

var System = xdc.useModule("xdc.runtime.System");
var SysMin = xdc.useModule("xdc.runtime.SysMin");
SysMin.bufSize = 0;
SysMin.flushAtExit = false;
System.SupportProxy = SysMin; /* not really necessary since SysMin is the default */

If you want to retain the characters in the SysMin character buffer but want to handle their output using your own function, you can use the SysMin.outputFxn configuration parameter.

var System = xdc.useModule("xdc.runtime.System");
var SysMin = xdc.useModule("xdc.runtime.SysMin");
SysMin.outputFxn = "&myOutputFxn";
System.SupportProxy = SysMin;
app.c (myOutputFxn)
Void myOutputFxn(Char *buf, UInt len)
    ...; /* output len chars starting from buf */

Notice that the assignment to outputFxn 1 is a string whose first character is "&". Normally assignment to a configuration parameter requires values to types that match the type of the parameter. In the case of function pointers, RTSC also allows the assignment of specially formatted strings. In this case, the string "&myOutputFxn" tells the RTSC to assume that there is an external function named myOutputFxn with the right type signature that should be used to output characters. Of course, any function specified in a module that has the right type signature can also be directly assigned to SysMin.outputFxn.

Performance Considerations

Interrupt latency and calling context

Interrupt latency and calling context.  The System module's functions are intended to be callable from any execution context, including Interrupt Service Routines (ISR). So it is important that any ISystemProvider implementation bound to the System module's SupportProxy be appropriate for the application as a whole.

In particular, if System_printf() is callable from an ISR, the implementation of putch() provided by the ISystemProvider must be designed to never suspend the calling thread (otherwise the ISR could block and most operating environments don't support this).

Although SysStd does not explicitly suspend the caller on any function, the underlying implementation of the ANSI C Standard Library functions (that SysStd calls) may try to block the caller. If you're not sure whether or not the System module's functions can be called from an ISR, you should use SysMin in lieu of SysStd.

Of course, if you know that System_printf() is always called in a context in which, say, the ANSI C Standard I/O functions may be safely called, then use of SysStd is safe.

Although SysMin never suspends the caller on any function, its implementation of ISystemSupport.flush() enters and remains in the System gate until all characters are "flushed". If the System gate disables interrupts and you use System_flush(), your interrupt latency will be a function of the size the configuration parameter SysMin.bufSize.

Execution time

Execution time.  Although the System module's System_printf() function is much smaller and faster than a full ANSI C compliant implementation of printf(), the System module relies on the underlying ISystemSupport module to output characters one at a time. To be thread-safe and callable from any execution context, the SysMin module's implementation of putch() must acquire the System gate, update the output buffer, and release the System gate. The overhead of acquiring and releasing the system gate on every character can quickly overwhelm the execution time benefit of System_printf() over a full printf() implementation.

If you're willing to write a small amount of platform-specific code, it is usually easy to write a very efficient function that outputs a single character at a time in a thread-safe manner; e.g., disable interrupts around the instructions that update an output buffer or use platform-specific "atomic" instructions (load-lock/store-conditional, compare-and-swap, etc.). To use such a function, you must implement a custom ISystemProvider module. For information about how to create your own ISystemProvider module, see Extending xdc.runtime System.


Footprint.  Depending on the implementation of your target's ANSI C Standard Library, the code size footprint of SysStd may be significantly larger than the footprint of SysMin. The SysStd module minimizes its use of the ANSI C Standard Library functions, so in most cases the footprint difference between SysMin and SysStd are relatively minor. But, in situations where code space is tight, it's always good to try both and compare the difference.

[printable version]  [offline version]offline version generated on 24-Feb-2019 01:02 UTC 
Copyright © 2008 The Eclipse Foundation. All Rights Reserved
Personal tools
package reference