| ======================== |
| XDC Runtime Architecture |
| ======================== |
| |
| Revision History |
| ================ |
| |
| +------------+------------+-------------------------------------------+ |
| | Version | Date | Description | |
| +============+============+===========================================+ |
| | 0.1 | 2/12/2019 | First draft | |
| +------------+------------+-------------------------------------------+ |
| | 0.2 | 6/1/2019 | Added internal xdc.runtime.Core material | |
| +------------+------------+-------------------------------------------+ |
| | 0.3 | 1/20/2020 | Added SysMin, Text, and Timestamp content | |
| +------------+------------+-------------------------------------------+ |
| | 0.4 | 3/25/2020 | Added "Uses" diagram and API conventions | |
| +------------+------------+-------------------------------------------+ |
| |
| Introduction |
| ============ |
| |
| Purpose & Scope |
| --------------- |
| |
| This document is intended to explain and illustrate the inner workings |
| of the xdc.runtime package. |
| |
| Disclaimer |
| ---------- |
| |
| While this document attempts to explain all the key details related to |
| the xdc.runtime package, certain details are bound to be left out. For |
| further explanation of such missing details, please refer to |
| `RTSCpedia <http://rtsc.eclipseprojects.io/docs-tip>`__ and or the source code |
| of xdc.runtime. |
| |
| Terms & Abbreviations |
| --------------------- |
| |
| +-------------+-----------------------------------------------------------------------------------------------------------------------------+ |
| | package | A named collection of modules which forms a component | |
| +-------------+-----------------------------------------------------------------------------------------------------------------------------+ |
| | module | The RTSC equivalent of a Java or C++ class | |
| +-------------+-----------------------------------------------------------------------------------------------------------------------------+ |
| | interface | The RTSC equivalent of a Java Class | |
| +-------------+-----------------------------------------------------------------------------------------------------------------------------+ |
| | RTSC | Real-Time Software Components - a portable C based component model appropriate for resource constrained embedded systems. | |
| +-------------+-----------------------------------------------------------------------------------------------------------------------------+ |
| | XDCtools | A collection of host tools for the development of RTSC components | |
| +-------------+-----------------------------------------------------------------------------------------------------------------------------+ |
| |
| References |
| ---------- |
| |
| Much of the text and organization of this document is derived from the |
| xdc.runtime documentation maintained in the |
| `RTSCpedia <http://rtsc.eclipseprojects.io/docs-tip>`__ - a wiki provided by |
| `eclipse.org <https://www.eclipse.org/>`__ as part of the `Eclipse RTSC |
| project <https://projects.eclipse.org/projects/technology.rtsc>`__. |
| |
| +------+-----------------------------------------------------------------------------------------------+---------------+ |
| | # | Title | Author | |
| +------+-----------------------------------------------------------------------------------------------+---------------+ |
| | 1. | `XDCtools User's Guide <http://rtsc.eclipseprojects.io/docs-tip/XDCtools_User%27s_Guide>`__ | David Russo | |
| +------+-----------------------------------------------------------------------------------------------+---------------+ |
| | 2. | `RTSC Glossary <http://rtsc.eclipseprojects.io/docs-tip/Glossary>`__ | David Russo | |
| +------+-----------------------------------------------------------------------------------------------+---------------+ |
| | 3. | `RTSC Bibliography <http://rtsc.eclipseprojects.io/docs-tip/Bibliography>`__ | David Russo | |
| +------+-----------------------------------------------------------------------------------------------+---------------+ |
| |
| xdc.runtime Package |
| =================== |
| |
| Functional Goals |
| ---------------- |
| |
| The xdc.runtime package contains many low-level modules that work |
| together to provide "core" services appropriate for any embedded |
| C/C++ application: |
| |
| - *memory management*: basic memory allocation and freeing from |
| multiple heaps |
| |
| - *concurrency support*: low-level critical region protection |
| mechanisms |
| |
| - *real-time diagnostics*: printf-like logging, error management, and |
| assertion support |
| |
| - *system services*: system initialization and shutdown (exit(), |
| atexit(), abort(), etc.) and basic character output (printf()) |
| |
| - *core instance support*: common runtime functions that manage the |
| life-cycle of all instances defined by any module; e.g., support for |
| the static or dynamic creation and deletion of any module's instance |
| objects. |
| |
| All of these services provide portable C interfaces that are |
| appropriate for virtually any 16, 32, and 64-bit embedded |
| microprocessor; from highly resource constrained 16-bit CPUs with as |
| little as 1K bytes of RAM and 32K bytes of Flash (MSP430F2274) to |
| 64-bit CPUs with gigabyte address spaces (AM57x). |
| |
| In addition to the services above, the xdc.runtime package provides |
| a low-level "internal" machine interface that supports the `RTSC |
| Interface Definition |
| Language <http://rtsc.eclipseprojects.io/docs-tip/Glossary#RTSC_IDL>`__ |
| (IDL) compiler; see `Core Instance Support`_. This IDL allows module developers to formally specify the interface of |
| a module in a C-like declarative language. The IDL compiler then |
| generates both C and JavaScript "stubs" that reference implementation |
| functions provided by the module developer. |
| |
| Interface Conventions |
| ~~~~~~~~~~~~~~~~~~~~~ |
| The services provided by the xdc.runtime package must be both highly |
| efficient and general enough to support a wide variety of applications |
| - from simple pedagogical examples to safty-critical real-time |
| applications. To balance these application requirements with a single |
| functional interface, all functions must: |
| |
| - document all pre-conditions necessary for proper operation as well |
| as all parameters and return values |
| |
| - return an error status when the pre-conditions are met but the |
| function fails |
| |
| - support reentrant operation |
| |
| xdc.runtime module functions are designed to maximize the C compiler's |
| static type checking ability by defining unique types for most input |
| and output parameters and using const wherever possible. |
| |
| Finally, where static checks and preconditions are insufficient to |
| catch common programming mistakes, xdc.runtime modules may also provide input |
| parameter sanity checks. For example, all parameter structures passed |
| to an instance constructor are checked to ensure the parameter |
| initialization function was used to initialize the structure. |
| |
| |
| Architectural Introduction |
| -------------------------- |
| |
| The services provided by the xdc.runtime package are partitioned into |
| numerous modules. The relationship between the modules in the |
| xdc.runtime package and the services they provide is depicted in the |
| figure below. |
| |
| |image0| |
| |
| All of the modules and interfaces provided in the xdc.runtime |
| package are supplied in portable C source code form. In addition, |
| all of the modules are designed to be thread-safe and, where |
| necessary, use the Gate module to serialize access to global data |
| structures. |
| |
| In order to ensure platform independence, those modules that require |
| platform-specific services are designed to support one (or more) |
| platform-specific "service providers". Each of these providers |
| implements one of the interfaces supplied. Simple implementations of |
| each service provider interface are also included in this package. |
| |
| Memory Management |
| ================= |
| |
| Functional Goals |
| ---------------- |
| |
| Memory management within embedded systems often requires |
| |
| - explicit management of distinct memory "classes"; |
| |
| - control over alignment of critical buffers; |
| |
| - deterministic memory allocation, support for variable length |
| allocation; and in some cases |
| |
| - the ability to eliminate *all* runtime allocation and freeing of |
| memory |
| |
| Explicit use of different "classes" of memory, such as high-speed |
| on-chip memory versus bulk external DRAM, is critical for embedded |
| real-time applications. For example, careful use and efficient |
| management of precious high-speed on-chip memory often determines |
| whether an application meets its real-time deadlines or not. Even |
| with different classes of memory, to get full entitlement from |
| modern CPU cores, it is important that critical buffers be allocated |
| on appropriate address boundaries - either for improved cache |
| performance or to take advantage of specialized "zero overhead" |
| looping constructs. |
| |
| Different applications have widely differing "policy" requirements. |
| For example, traditional embedded applications do not need, nor can |
| they afford, extra memory management code to allow the system to |
| automatically free memory from a terminated thread. On the other |
| hand, some embedded systems allow for the execution of untrusted |
| (but not malicious) code. In this case, the robustness requirements |
| of the system all but require a memory manager that can track the |
| ownership of every allocated memory block. Similarly, because |
| real-time applications provide "guaranteed" response times for |
| certain events and variable length memory allocators often have |
| execution times that vary as a function of the number and size of |
| previous allocations, real-time applications generally take one of |
| two approaches to dynamic heap memory management: |
| |
| 1. use "fixed size" block allocation algorithms which have deterministic |
| execution times but have poor memory utilization, or |
| |
| 2. use a distinguished "low priority" thread to perform all functions |
| that require memory allocation so the "real-time" threads never |
| stall waiting to allocate or free memory. |
| |
| From these examples, it's clear that embedded systems have unique |
| memory management requirements and that no one memory allocation |
| algorithm is appropriate for all embedded applications. |
| |
| The xdc.runtime package provides core memory management functions |
| suitable for virtually any embedded application. In particular, it |
| includes a single module, Memory that supports |
| |
| - multiple heaps and allows each heap to manage its memory in a |
| memory-specific or application-specific manner; |
| |
| - aligned allocations on any boundary supported by the underlying |
| hardware; |
| |
| - static placement of buffers required by other modules that create |
| objects at configuration-time; and |
| |
| - zero-space-overhead allocations that do not require "allocation |
| header" information to be retained on each allocation. |
| |
| Architecture Introduction |
| ------------------------- |
| |
| The xdc.runtime package contains several modules that work together |
| to provide modular and extensible memory management support. This |
| support is centered on the |
| `Memory <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Memory.html>`__ |
| module that enables the application to allocate and free memory. All |
| memory allocations are eventually "handled" by a module that |
| implements the |
| `IHeap <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/IHeap.html>`__ |
| interface. These modules are responsible for managing a region of |
| memory in a manner appropriate for the application. |
| |
| Two such modules are provided in the xdc.runtime package: |
| |
| 1. `HeapMin <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/HeapMin.html>`__ - a module that simply maintains a "high water" mark for each managed memory block and never frees memory, and |
| |
| 2. `HeapStd <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/HeapStd.html>`__ - a module that uses the ANSI C standard library functions ``malloc()`` and ``free()``. |
| |
| While it is possible to create new implementations of the IHeap |
| interface that provide more sophisticated or even |
| application-specific memory management policies, most users will |
| rely on IHeap implementations from their preferred RTOS (such as |
| TI's SYS/BIOS). |
| |
| Architecture |
| ------------ |
| |
| The Memory module's methods take a first parameter that identifies |
| the heap from which to allocate memory. This parameter may be NULL |
| and, in this case, a "default heap" will be used. The "default heap" |
| is specified by the developer by setting the Memory module's |
| defaultHeapInstance configuration parameter. If this parameter is |
| not explicitly set by the developer, an instance of |
| `xdc.runtime.HeapStd <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/HeapStd.html>`__ |
| (of size |
| `Memory.defaultHeapSize <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Memory.html#default.Heap.Size>`__) |
| will be assigned to this parameter. |
| |
| |image1| |
| |
| The Memory module itself does very little work: it simply delegates |
| "real" memory management to the specified heap instance object. This |
| makes clients of Memory portable, but where do the heap instances |
| get created? If they are created by the application, the code that |
| creates these instances is not portable to other applications; |
| because it contains direct references to specific heap managers. Of |
| course, applications can factor this "non portable" code into a |
| single place and pass IHeap instance handles to other parts of the |
| application that need memory allocation services. But, an even |
| better solution is to entirely eliminate the runtime creation of |
| IHeap instances in favor of static creation. In this case, not only |
| do we eliminate unnecessary code, but we improve the portability of |
| the code by eliminating direct references to application-specific |
| heap managers. |
| |
| Memory simply provides the "glue" between portable clients and |
| underlying modules, heap managers, which actually manage the memory. |
| But the xdc.runtime package only provides two heap managers, HeapMin |
| and HeapStd, and these modules have limited usefulness; HeapMin does |
| not reuse freed memory and HeapStd has no advantage over malloc() |
| and free(). So where do you get "real" heap managers that realize |
| the benefits promised by the xdc.runtime package's memory |
| architecture? Heap managers are available from RTOS providers (such |
| as TI's SYS/BIOS). |
| |
| Concurrency Support |
| =================== |
| |
| Functional Goals |
| ---------------- |
| |
| Each embedded application runs in a unique environment with specific |
| mechanisms for managing multiple threads; some use a real-time |
| operating system while others simply run a control loop that |
| coordinates with interrupt service routines. The Gate module |
| provides an RTOS independent interface that allows applications to |
| portably protect shared data structures in multi-threaded |
| environments by simply "entering a gate" prior to using the data and |
| "leaving the gate" once access is no longer required. |
| |
| Gates are also used internally by the xdc.runtime package. In order |
| to allow the xdc.runtime functions to be called from different |
| threads, it is important that any global data managed by the |
| xdc.runtime modules is updated "atomically". The xdc.runtime package |
| atomically updates global data by always "entering the System gate" |
| (via |
| `Gate\_enterSystem() <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Gate.html#enter.System>`__) |
| prior to accessing the global data and "leaving the System gate" |
| (via |
| `Gate\_leaveSystem() <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Gate.html#leave.System>`__) |
| once the update is complete. |
| |
| While gates make it easy to protect shared data structures and |
| ensure the functional correctness of a multi-threaded application, |
| it is important to minimize the time spent within a gate; the longer |
| a thread operates within a gate the greater the chance that this |
| thread will interfere with the timely operation of other threads in |
| the system. If two (or more) threads need to enter the same gate, |
| all but one will be suspended until the thread in the gate leaves |
| *even if the thread inside the gate has lower priority than the |
| blocked threads*. Worse, for performance reasons, some gates work by |
| disabling *all* scheduling while inside the gate; even threads that |
| are not trying to modify the data protected by the gate are |
| potentially affected. |
| |
| By carefully selecting the type of gate used to protect shared data |
| structures and associating each shared data structure with a unique |
| gate, it is possible to strike a balance between the runtime |
| overhead caused by frequent gate method calls and the scheduling |
| latency engendered by unnecessarily blocking the execution of |
| threads that are operating on unrelated data. |
| |
| The xdc.runtime package |
| |
| - enables creation of portable thread-safe code with shared data |
| structures, |
| |
| - provides a distinguished "System gate" to efficiently protect very |
| short critical sections, |
| |
| - supports gates on both a per-module and a per-instance basis for |
| modules that need to operate within a gate for periods longer |
| than the worst-case scheduling latency allowed by the |
| application, and |
| |
| - allows system integrators to configure gates to achieve the proper |
| balance between runtime overhead and scheduling latency for their |
| application. |
| |
| Architecture Introduction |
| ------------------------- |
| |
| The xdc.runtime package contains modules that work together to |
| provide support for serializing access to shared data structures. |
| This section focuses on the |
| `Gate <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Gate.html>`__ |
| module which is used to "enter" and "leave" critical sections of |
| code that access shared data. |
| |
| Use of this module is illustrated by a series of examples that take |
| advantage of one other distinguished xdc.runtime module: |
| |
| - `GateNull <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/GateNull.html>`__ - a module that is used to eliminate unnecessary serialization |
| overhead for those situations where data is known to be accessed |
| by one thread at a time; e.g., in single threaded systems or for |
| modules that are known to be used by just one thread in a |
| multi-threaded application. |
| |
| Obviously the most interesting examples will require a "real" gate; |
| i.e., one that serializes access to a shared data structure in a |
| multi-threaded application. `Extending xdc.runtime |
| Gates <http://rtsc.eclipseprojects.io/docs-tip/Extending_xdc.runtime_Gates>`__ |
| provides an example that uses `posix |
| mutexes <http://pubs.opengroup.org/onlinepubs/9699919799/>`__ and |
| illustrates how, using services commonly provided by an RTOS, the |
| xdc.runtime package can be made thread-safe with respect to that |
| RTOS. |
| |
| Architecture |
| ------------ |
| |
| .. Requirement |
| | REQ_TAG(SYSBIOS-921), REQ_TAG(SYSBIOS-922), REQ_TAG(SYSBIOS-923) |
| | REQ_TAG(SYSBIOS-924), REQ_TAG(SYSBIOS-925), REQ_TAG(SYSBIOS-926) |
| | REQ_TAG(SYSBIOS-927), REQ_TAG(SYSBIOS-928), REQ_TAG(SYSBIOS-929) |
| | REQ_TAG(SYSBIOS-930) |
| |
| |
| Any module may declare that it is |
| "`gated <http://rtsc.eclipseprojects.io/docs-tip/Glossary#GatedModule>`__"; |
| i.e., that the module protects internal data shared among multiple |
| threads in the system via an xdc.runtime.Gate instance. Gated |
| modules always have at least one gate instance created implicitly. |
| However, it is possible to override the creation of this gate by |
| explicitly creating it and assigning it to the module's common$.gate |
| configuration parameter during configuration. |
| |
| Modules enter and leave gates via the methods provided by the |
| `xdc.runtime.Gate <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Gate.html>`__ |
| module. This Gate module provides methods that enable modules to |
| enter (and leave) their gate as well as dynamically create and |
| delete gates associated with their instance objects. Users of gated |
| modules don't need to use these methods (they are for use within the |
| implementation of RTSC modules) and should consult the documentation |
| of each gated module used to understand how best to balance the |
| module's need to protect shared data structures and the |
| application's scheduling latency requirements. |
| |
| In addition to the services provided to implement thread-safe |
| modules, the Gate module also provides access to the distinguished |
| "System gate" via |
| `Gate\_enterSystem() <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Gate.html#enter.System>`__ |
| and |
| `Gate\_leaveSystem <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Gate.html#leave.System>`__. |
| In fact, this System gate is the gate associated with the gated |
| `xdc.runtime.System <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/System.html>`__ |
| module. This one gate is used throughout the xdc.runtime package to |
| serialize access to global data and it's only used when the duration |
| of the critical section is known to be *deterministic and very |
| short*. |
| |
| Using the System gate to protect logically independent data |
| structures is contrary to the design principle that, to minimize |
| scheduling latency effects, you should use a unique gate for |
| independent data structures. This exception exists because, *if* the |
| duration of time required to update these independent structures is |
| always very short (less than any application's maximum scheduling |
| latency requirements), the System gate can be implemented very |
| efficiently by simply disabling *all* scheduling while inside the |
| gate. While this may sound excessive, it often results in a |
| significant overall performance gain, keeps data space requirements |
| to a minimum with just one gate, and has no impact to scheduling |
| latency. |
| |
| |image2| |
| |
| Deadlocks |
| ~~~~~~~~~ |
| |
| Although it is possible to "nest" gates - enter a gate while inside |
| another gate - care should be taken to avoid deadlocks; e.g., thread |
| 1 enters gate a, thread 2 enters gate b, thread 1 tries to enter |
| gate b and blocks waiting for thread 2 to leave, but thread 2 tries |
| to enter gate a and blocks waiting for thread 1 to leave. One way to |
| avoid deadlocks is to ensure that nested gates are always entered in |
| the same order. |
| |
| Since the System gate is used throughout the xdc.runtime and the |
| modules in this package are widely used, you should never enter |
| another gate while inside the System gate. If another thread enters |
| the same gate *and* makes a call to an xdc.runtime method, such as |
| System\_printf(), there is a risk of deadlock. |
| |
| The System gate should *only* be used to protect low-level data |
| structures where the total execution time within the gate has a |
| constant upper bound independent of the data being protected. |
| |
| Scheduling Latency |
| ~~~~~~~~~~~~~~~~~~ |
| |
| Undisciplined use of gates can lead to scheduling latencies that |
| violate a system's real-time constraints. Since the System gate is |
| used to protect a wide variety of independent data structures, it is |
| important to keep the time within the System gate to an absolute |
| minimum. Similarly, when assigning gates to gated modules it's |
| important to minimize sharing gates between different modules; while |
| sharing can reduce your application's data footprint, you risk |
| creating unnecessary scheduling blockages. |
| |
| Real-Time Diagnostics: Event Logging |
| ==================================== |
| |
| Functional Goals |
| ---------------- |
| |
| The xdc.runtime package's logging support enables developers to |
| embed "printf-like" Log statements virtually *anywhere* in an |
| embedded real-time code base. In addition to the traditional |
| printf() format string and arguments, each Log statement is |
| associated with a calling module and an "event mask" - a bit mask |
| that identifies the "type" of statement. The Log statements |
| |
| - provide all the functionality of a "normal" printf, |
| |
| - can be enabled or disabled at runtime on a per-module and per-type |
| basis, and |
| |
| - have fixed low execution time independent of the arguments passed. |
| |
| Applications can be configured to eliminate the data space required |
| for the format strings, permanently disable (or enable) selected |
| statements, eliminate the code space required for runtime control, |
| and provide application-specific handling of the "events" produced |
| by these statements. All of these configuration options are possible |
| *without requiring re-compilation of any source code*. |
| |
| Architecture Introduction |
| ------------------------- |
| |
| The xdc.runtime package contains several modules that work together |
| to provide rich application diagnostic support that can be |
| controlled in real-time within deployed systems. This section |
| focuses on those modules that are used to generate "events", |
| enable/disable their generation, and display the events: |
| `Log <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Log.html>`__, |
| `Diags <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Diags.html>`__, |
| and |
| `LoggerSys <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/LoggerSys.html>`__, |
| respectively. |
| |
| Use of these modules is illustrated by a series of examples that |
| take advantage of two other distinguished xdc.runtime modules: |
| |
| 1. `Main <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Main.html>`__ |
| - a module whose configuration applies to all code that is *not* a RTSC |
| module; e.g., existing C code bases, and |
| |
| 2. `Defaults <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Defaults.html>`__ |
| - a module whose configuration applies to all RTSC modules (including Main), |
| unless explicitly overridden on a per-module basis. |
| |
| Architecture |
| ------------ |
| |
| Loggers |
| ~~~~~~~ |
| For the purpose of logging, *every line* of code in an application |
| is treated as being part of some RTSC module. All code falls into |
| one of three classes: |
| |
| 1. code that is part of a RTSC module |
| |
| 2. code that is part of a dynamically registered module. Code can |
| dynamically register itself as a module through the |
| `xdc.runtime.Registry <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Registry.html>`__ |
| module. |
| |
| 3. all other code. Any code that is not part of a RTSC module or a |
| registered module is considered to be part of the distinguished |
| `xdc.runtime.Main <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Main.html>`__ |
| module. |
| |
| All RTSC target modules, including |
| `xdc.runtime.Main <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Main.html>`__, |
| have a |
| |
| - current "event mask" - a set of event categories that are enabled for |
| the module, |
| |
| - an optional |
| `ILogger <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/ILogger.html>`__ |
| service provider - a module that handles events generated by the |
| module, and |
| |
| - an optional string name used to display the source of events |
| |
| All dynamically registered modules also have an event mask and a |
| required string name. |
| |
| The |
| `Log\_print <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Log.html#print6>`__ |
| or |
| `Log\_write <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Log.html#write8>`__ |
| methods are used to generate or log "events". These methods are |
| simply in-line macros that conditionally invoke the calling module's |
| underlying ILogger service provider to "handle" the events. This |
| service provider is called only if: |
| |
| 1. the module has a non-null ILogger service provider, and |
| |
| 2. the mask argument passed to Log\_print (or the mask of the event |
| passed to Log\_write) anded with the calling module's current |
| "event mask" is non-zero |
| |
| The initial value of a module's event mask is specified during |
| configuration and may be changed at runtime via |
| `Diags\_setMask() <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Diags.html#set.Mask>`__. |
| |
| Beyond the parameters passed to Log\_print (or Log\_write), the id |
| of the module that called Log\_print (or Log\_write) is communicated |
| to the ILogger service provider so that it knows the source of the |
| events. This information, possibly in addition to a timestamp |
| recorded by the ILogger service provider, can be used to correlate |
| events from multiple sources (even from different CPUs). |
| |
| Two ILogger service providers are included in the xdc.runtime |
| package: |
| |
| 1. `LoggerBuf <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/LoggerBuf.html>`__ |
| - copies events to a circular buffer in a fixed small number of |
| cycles and is suitable for real-time high-frequency event |
| sources, and |
| |
| 2. `LoggerSys <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/LoggerSys.html>`__ |
| - outputs events as they occur using |
| `System\_printf() <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/System.html#printf>`__ |
| and is suitable for initial development or low-rate non-real-time |
| event sources. |
| |
| Custom ILogger service providers can easily be created to address |
| platform or application specific needs. These custom providers can, |
| of course, filter events and call LoggerBuf or LoggerSys. For |
| information about creating and deploying a custom logger see |
| `Extending xdc.runtime |
| Logging <http://rtsc.eclipseprojects.io/docs-tip/Extending_xdc.runtime_Logging>`__. |
| |
| As part of an application's configuration step, developers "bind" |
| zero or more ILogger service providers to the modules that comprise |
| the application. Each module in a system can have a different |
| ILogger service provider or they can all share the same provider. |
| Events generated by modules *without* an ILogger service provider |
| are silently ignored. |
| |
| Timestamps |
| ~~~~~~~~~~ |
| |
| .. Requirement |
| | REQ_TAG(SYSBIOS-881), REQ_TAG(SYSBIOS-882), REQ_TAG(SYSBIOS-883) |
| | REQ_TAG(SYSBIOS-884), REQ_TAG(SYSBIOS-885) |
| |
| By definition, real-time systems require some means to track and |
| measure elapsed time. However, different systems use very different |
| methods. Some systems leverage platform-specific timer peripherals |
| while others use application-specific data streams that are known to |
| produce data at a fixed rate (i.e., telephony TDM data). The choice of |
| how to measure time is application and platform specific, so it is |
| important that the timer services provided by xdc.runtime enable the |
| system integrator to specify an appropriate time source. |
| |
| In addition to variations in how time is measured, different |
| applications have very different precision and range |
| requirements. Applications that only require millisecond precision |
| often don't require more than 32-bits of range (almost 50 days), |
| whereas measurements used to causally relate events in a multi-core |
| system requires near nanosecond precision (yielding less than 5 |
| seconds of range from a 32-bit value). In fact, it is not unusual for |
| a single application to require more than one timer with different |
| precision and range requirements. |
| |
| The xdc.runtime package contains several modules that need timestamps; |
| e.g., LoggerBuf and LoggerSys. These modules obtain timestamps from |
| other modules that implement the xdc.runtime.ITimestampProvider |
| interface. Two such modules are provided in the xdc.runtime package: |
| |
| 1. `TimestampNull <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/TimestampNull.html>`__ |
| - a timestamp provider that always returns a timestamp of 0, and |
| |
| 2. `TimestampStd <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/TimestampStd.html>`__ |
| - a timestamp provider that uses the ANSI C Standard Library function clock() to obtain timestamps. |
| |
| The xdc.runtime.Timestamp module provides a platform-independent |
| interface that is sufficient for simple timestamping needs. This |
| module makes use of platform-specific implementations which can take |
| advantage of underlying hardware support, for example. Rather than |
| define a single "provider" interface that is sufficient for the needs |
| of the Timestamp module, the xdc.runtime package defines two |
| interfaces: |
| |
| 1. `ITimestampClient <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/ITimestampClient.html>`__ |
| - defines the platform-independent interface provided by Timestamp, and |
| |
| 2. `ITimestampProvider <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/ITimestampProvider.html>`__ |
| - defines the interface provided by platform-specific implementations and inherits from ITimestampClient |
| |
| While it may seem odd that underlying timestamp provider |
| implementations must implement the same interface as ITimestampClient, |
| this design enables applications to call timestamp providers directly, |
| when necessary, to leverage platform-specific capabilities. Suppose |
| there is device specific timestamp provider, say Timestamp64, that |
| provides additional methods that put an underlying timer into special |
| low-power modes. Since this Timestamp64 module must implement |
| ITimestampClient (because ITimestampProvider inherits from |
| ITimestampClient), developers that need to leverage the low-power |
| functionality can mechanically replace existing calls to Timestamp |
| methods with calls to Timestamp64 methods and be sure the application |
| will continue to function properly. The figure below illustrates the |
| relationship between the the various timestamp interfaces and modules |
| provided by xdc.runtime as well as this hypothetical Timestamp64 |
| timestamp. |
| |
| |RuntimeTime| |
| |
| |
| Real-Time Diagnostics: Error Handling |
| ===================================== |
| |
| Functional Goals |
| ---------------- |
| |
| Each embedded application runs in a unique environment with specific |
| resource requirements and, as a result, adopts application-specific |
| *policies* for managing runtime errors; e.g., reset-and-reboot, |
| catch-and-retry, log-and-continue, or a combination of these |
| policies for different parts of the system. The xdc.runtime package |
| provides a set of mechanisms for raising and handling runtime errors |
| that enables code to be written once and used in *any* application - |
| independent of the application's error handling policies. |
| |
| Architecture Introduction |
| ------------------------- |
| |
| The xdc.runtime package contains several modules that work together |
| to provide rich application diagnostic support that can be |
| controlled in real-time within deployed systems. This section |
| focuses on those modules that are used to raise and handle errors |
| and provide assertion support: |
| `Error <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Error.html>`__ |
| and |
| `Assert <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Assert.html>`__, |
| respectively. |
| |
| Use of these modules is illustrated by a series of examples that |
| take advantage of two other distinguished xdc.runtime modules: |
| |
| 1. `Main <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Main.html>`__ |
| - a module whose configuration applies to all code that is *not* |
| a RTSC module; e.g., existing C code bases, and |
| |
| 2. `Defaults <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Defaults.html>`__ |
| - a module whose configuration applies to all RTSC modules |
| (including Main), unless explicitly overridden on a per-module |
| basis. |
| |
| Architecture |
| ------------ |
| |
| .. Requirement |
| | REQ_TAG(SYSBIOS-852), REQ_TAG(SYSBIOS-853), REQ_TAG(SYSBIOS-854) |
| | REQ_TAG(SYSBIOS-855), REQ_TAG(SYSBIOS-856), REQ_TAG(SYSBIOS-857) |
| | REQ_TAG(SYSBIOS-858), REQ_TAG(SYSBIOS-859), REQ_TAG(SYSBIOS-860) |
| | REQ_TAG(SYSBIOS-861), REQ_TAG(SYSBIOS-862), REQ_TAG(SYSBIOS-863) |
| | REQ_TAG(SYSBIOS-864), REQ_TAG(SYSBIOS-865), REQ_TAG(SYSBIOS-866) |
| | REQ_TAG(SYSBIOS-867), REQ_TAG(SYSBIOS-868), REQ_TAG(SYSBIOS-869) |
| | REQ_TAG(SYSBIOS-870), REQ_TAG(SYSBIOS-959) |
| |
| |
| The xdc.runtime package supports two distinct "categories" of error: |
| |
| 1. *errors* that are explicitly checked for and handled by the code, and |
| |
| 2. *assertion violations* that arise when the current application state |
| is inconsistent with the range of states required by a piece of |
| code. |
| |
| The first category of errors is managed by the Error module and the |
| second category is managed by the Assert module. Rather than use |
| simple fixed-length error numbers, the xdc.runtime package uniformly |
| employs an opaque Error\_Block structure to "raise" errors via |
| `Error\_raise() <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Error.html#raise>`__. |
| Functions that raise errors are passed a pointer to an Error\_Block |
| structure which is passed to Error\_raise() when an error is |
| detected. When an error is raised, the Error\_Block structure |
| records the source of the error, a unique ID for for the error, a |
| message format string, and up to two arguments associated with this |
| particular occurrence. |
| |
| Using an Error\_Block structure has several advantages. Perhaps most |
| importantly, the information about the source of the error as well |
| as data specific to the particular occurrence is efficiently copied |
| into the structure for later processing. In effect, Error\_raise() |
| combines the efficiency of a simple error code with the richness of |
| a printf at the site of the error. Since the error information is |
| simply recorded in the Error\_Block structure, the application |
| developer can control when and how the information will be formatted |
| and displayed. |
| |
| Similar to the standard C assert() macro, the Assert module's |
| methods are interspersed with other code to add runtime checks - |
| primarily during early development - that ensure the code is being |
| called in the appropriate context. Unlike the standard C assert |
| support, the Assert module provides greater flexibility in managing |
| the messages displayed, the message string space overhead, and the |
| runtime handling of failures. In addition, because the Assert |
| methods build atop the Diags module, you can precisely control which |
| assertions remain in the final application, if any. |
| |
| When an assertion violation is detected, an |
| `Assert.E\_assertFailed <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Assert.html#/.E_assert/.Failed>`__ |
| error is raised (via Error\_raise()) with a NULL Error\_Block |
| reference; so, assertions are handled using the same error handling |
| hooks as "normal" errors. |
| |
| Real-Time Diagnostics: Text |
| =========================== |
| |
| Functional Goals |
| ---------------- |
| Adding "printf-like" statements to a C code base not only increases |
| code space (the instructions to put arguments in registers and call a |
| function) but it can significantly increase an application's data |
| space requirements; each "printf-like" format string is added to a |
| data section reserved for constants and the size of section can grow |
| quickly as more and more logging statements are added. While it's not |
| possible to stop the strings used in Log_print() statements from |
| taking up space in the target, it is possible to completely eliminate |
| the |
| |
| * format strings by used by Log_write(), |
| * error messages emitted by Error_raise(), and |
| * assertion messages triggered by Assert_isTrue() |
| |
| Since each of these strings is declared in the RTSC specification, |
| it's possible to sequester these strings into a compressed table that |
| *does not* need to be loaded on to the embedded system for normal |
| operation. These statically declared strings can be "encoded" into a |
| single 32-bit quantity that encodes _references_ to both the string |
| itself and where the string is defined. These references can be |
| interpreted by a host computer to display to the user the complete |
| message while the embedded system can enjoy the benefits of detailed |
| tracing and understandable error messages produced deterministically |
| and with small footprint. |
| |
| While the logger architecture enables deterministic execution time for |
| logging, there is a need to also minimize the overall footprint |
| overhead for these diagnostics. |
| |
| Architecture |
| ------------ |
| |
| .. Requirement |
| | REQ_TAG(SYSBIOS-886), REQ_TAG(SYSBIOS-887), REQ_TAG(SYSBIOS-888) |
| | REQ_TAG(SYSBIOS-889), REQ_TAG(SYSBIOS-890), REQ_TAG(SYSBIOS-891) |
| | REQ_TAG(SYSBIOS-892), REQ_TAG(SYSBIOS-893), REQ_TAG(SYSBIOS-894) |
| | REQ_TAG(SYSBIOS-895), REQ_TAG(SYSBIOS-896), REQ_TAG(SYSBIOS-897) |
| | REQ_TAG(SYSBIOS-898) |
| |
| In lieu of a mask and a format string as initial arguments, |
| Log_write() takes a Log_Event. A Log_Event is an opaque reference to a |
| structure that contains a mask and a format string. How does this |
| help? By eliminating direct references to literal strings in the C |
| sources, the C compiler only sees an integer index being passed to |
| Log_write() and never needs to allocate space for the constant format |
| string. During configuration, it's possible to generate a table of all |
| Log_Event format strings, define Log_Event as an index into this |
| table, and arrange for this table to loaded in a separate output |
| section. Since this table is only needed when the event is "decoded", |
| the table (with the strings) does not need to be loaded into the |
| target's memory; events can be decoded by host-based development tools |
| which simply lookup the event based on the index supplied by |
| Log_write(). |
| |
| The Error and Assert modules follow a similar pattern and *all* |
| "event" strings are included in a single table that is created |
| and managed by the `xdc.runtime.Text <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Text.html>`__ module. |
| |
| To eliminate the runtime strings you must configure the Text module to |
| place all strings in a special section that will not be loaded onto |
| the target. |
| |
| .. code-block:: c |
| :name: Text_isLoaded |
| |
| var Text = xdc.module("xdc.runtime.Text"); |
| Text.isLoaded = false; |
| |
| In addtion to providing the ability to remove the many of the static |
| strings from the embeded application's runtime image, the Text module |
| provides a functional interface used in the implementation of other |
| module's to generate output buffers with the fully qualified names of |
| any module in the system using a 16-bit Id; e.g., the single 37 byte |
| string ``"ti/sysbios/family/arm/a15/smp/Cache"`` is represented by |
| just 2 bytes on the target. |
| |
| System Services |
| =============== |
| |
| Functional Goals |
| ---------------- |
| |
| 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 <http://rtsc.eclipseprojects.io/docs-tip/Glossary#PlatformDefinition>`__ |
| with the same |
| `target <http://rtsc.eclipseprojects.io/docs-tip/Glossary#TargetDefinition>`__, |
| no recompilation is required. |
| |
| Architecture Introduction |
| ------------------------- |
| |
| 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 <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Startup.html>`__ |
| - a module that provides a framework for the orderly |
| initialization of modules *prior* to main(), and |
| |
| 2. `System <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/System.html>`__ |
| - 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 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 <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/SysMin.html>`__ |
| - a self-contained module appropriate for deeply embedded |
| applications or early system development, and |
| |
| 2. `SysStd <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/SysStd.html>`__ |
| - 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. |
| |
| Startup Architecture |
| -------------------- |
| |
| .. Requirement |
| | REQ_TAG(SYSBIOS-949), REQ_TAG(SYSBIOS-950), REQ_TAG(SYSBIOS-951) |
| | REQ_TAG(SYSBIOS-952), REQ_TAG(SYSBIOS-953), REQ_TAG(SYSBIOS-954) |
| | REQ_TAG(SYSBIOS-955), REQ_TAG(SYSBIOS-956) |
| |
| |
| 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 <http://rtsc.eclipseprojects.io/docs-tip/XDCspec_-_%40ModuleStartup>`__ |
| 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 |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| 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. |
| |
| Boot Sequence and Control Points |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| This section describes the sequence of events that occurs |
| immediately after a device is reset until execution reaches the |
| application's main() function. It also identifies the specific |
| points during this boot sequence at which user provided functions |
| ("boot hooks") are called. |
| |
| |image3| |
| |
| All targets follow the same set of boot sequence steps. In outline, |
| the target independent boot sequence steps are: |
| |
| 1. Immediately after CPU reset, perform target-specific CPU |
| initialization to, at a minimum, setup a C call stack. |
| |
| 2. Run user-supplied reset function (see |
| `Startup.resetFxn <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Startup.html#reset/.Fxn>`__). |
| |
| 3. Perform additional target-specific initialization to a complete C |
| execution environment for subsequent steps. |
| |
| 4. Run user-supplied "first functions" (See |
| `Startup.firstFxns <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Startup.html#first/.Fxns>`__). |
| |
| 5. Run all module initialization functions. |
| |
| 6. Run user-supplied last functions (See |
| `Startup.lastFxns <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Startup.html#last/.Fxns>`__). |
| |
| 7. Call main(). |
| |
| The reset function (in step 2 above) is run as early as possible in |
| the boot sequence. In fact, for some targets it is called before the |
| C environment is fully initialized; static variables may not be |
| fully initialized, for example. To maximize portability, reset |
| functions should only assume that a C stack is initialized. |
| |
| Although the functions in steps 4-6 are C functions, they are run |
| during normal C++ static object initialization. This has two |
| consequences: |
| |
| 1. Since the ANSI C++ Language Standard does not provide a means to |
| control the order of execution of static constructors, the |
| initialization of application modules may not run before a C++ |
| constructor runs. If you need to use a **module** (for memory |
| allocation, for example) before step 6 completes and all modules |
| are initialized, your code must explicitly call Startup\_exec() |
| before using any other module in the system. It is safe to call |
| Startup\_exec() more than once. So, you may call it from each C++ |
| constructor that needs a module's services. |
| |
| 2. If you are using a target that does not support C++, you must |
| explicitly call Startup\_exec() prior to using any module's |
| services. You can simply call Startup\_exec() as the first step |
| in main(), for example. |
| |
| Specific information about each environment's startup sequence is |
| provided by the topics indexed in the table below. |
| |
| +----------------------+---------------------------------------------------------------------------------------------------------------------------------+ |
| | **Target Family** | **Detailed Boot Sequence Information** | |
| +======================+=================================================================================================================================+ |
| | TI | `TI Compiler Runtime Startup Sequence <http://rtsc.eclipseprojects.io/docs-tip/Using_xdc.runtime_Startup/TI>`__ | |
| +----------------------+---------------------------------------------------------------------------------------------------------------------------------+ |
| | Gnu Unix | `GNU Native Compiler Runtime Startup Sequence <http://rtsc.eclipseprojects.io/docs-tip/Using_xdc.runtime_Startup/GNU>`__ | |
| +----------------------+---------------------------------------------------------------------------------------------------------------------------------+ |
| | Microsoft | `Microsoft Compiler Runtime Startup Sequence <http://rtsc.eclipseprojects.io/docs-tip/Using_xdc.runtime_Startup/Microsoft>`__ | |
| +----------------------+---------------------------------------------------------------------------------------------------------------------------------+ |
| |
| 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 <http://rtsc.eclipseprojects.io/docs-tip/XDCspec_-_%40ModuleStartup>`__ |
| attribute in the module's spec file. Modules that use this attribute |
| must also implement the following startup function: |
| |
| .. code-block:: c |
| :name: Mod_Module_startup |
| |
| Int Mod_Module_startup(Int state); |
| |
| 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 (0) and whose final |
| value will eventually be Startup\_DONE (-1). 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 |
| `Startup.maxPasses <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Startup.html#max/.Passes>`__ |
| 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: |
| |
| .. code-block:: c |
| :name: Mod_Module_starupDone |
| |
| Bool Mod_Module_startupDone(); |
| |
| 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 a module instance |
| create, and should be called before any startup-time instance |
| creation and/or memory allocation is performed. |
| |
| .. code-block:: c |
| :name: Mod_Module_startup_example |
| |
| Int Mod_Module_startup(Int state) |
| { |
| if (!Startup_rtsDone()) { |
| return (Startup_NOTDONE); |
| } |
| |
| // other code |
| |
| return (Startup_DONE); |
| } |
| |
| System Module Architecture |
| -------------------------- |
| |
| .. Requirement |
| | REQ_TAG(SYSBIOS-899), REQ_TAG(SYSBIOS-900), REQ_TAG(SYSBIOS-901) |
| | REQ_TAG(SYSBIOS-902), REQ_TAG(SYSBIOS-903), REQ_TAG(SYSBIOS-904) |
| | REQ_TAG(SYSBIOS-906), REQ_TAG(SYSBIOS-907), REQ_TAG(SYSBIOS-908) |
| | REQ_TAG(SYSBIOS-909), REQ_TAG(SYSBIOS-910), REQ_TAG(SYSBIOS-911) |
| | REQ_TAG(SYSBIOS-912), REQ_TAG(SYSBIOS-1069), REQ_TAG(SYSBIOS-1070) |
| | REQ_TAG(SYSBIOS-1071), REQ_TAG(SYSBIOS-1072), REQ_TAG(SYSBIOS-1073) |
| |
| |
| The System module 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. |
| |
| System 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 <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/ISystemSupport.html>`__ |
| interface). Developers specify the module that implements these |
| functions by setting the |
| `System.SupportProxy <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/System.html#.Support.Proxy>`__ |
| configuration parameter. |
| |
| |image4| |
| |
| 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. |
| |
| Customizing the System module requires that the end-user specify a |
| module that implements the ISystemSupport interface as the "proxy" |
| for the required platform or application-specific services. |
| |
| The relationship between the System module and an ISystemSupport |
| proxy is illustrated in the figure below. |
| |
| |image5| |
| |
| SysMin |
| ^^^^^^ |
| |
| .. Requirement |
| | REQ_TAG(SYSBIOS-913), REQ_TAG(SYSBIOS-914), REQ_TAG(SYSBIOS-915) |
| | REQ_TAG(SYSBIOS-916), REQ_TAG(SYSBIOS-917), REQ_TAG(SYSBIOS-918) |
| | REQ_TAG(SYSBIOS-919), REQ_TAG(SYSBIOS-920) |
| |
| The SysStd module uses putchar() and fflush() for basic character output. |
| However, SysMin simply copies characters to a pre-configured static buffer |
| for character output and provides a configuration parameter that allows you |
| to specify how these characters are output when System_flush() is called. As |
| a result, SysMin can be used in applications that need to avoid all |
| references to the ANSI C Standard Library I/O functions. |
| |
| With the exception of exit(), atexit(), and abort(), the System module does |
| not directly reference any ANSI C Standard Library functions; any other |
| references are the result of the System module's supporting module |
| System.SupportProxy. If the System.SupportProxy configuration parameter is |
| not set, it defaults to SysMin. |
| |
| By default, the SysMin support module will call fwrite() to output characters |
| written to its internal buffer. To eliminate this reference, it is sufficient |
| to define your own output function, say myOutputFxn, and set SysMin.outputFxn |
| to reference this function. |
| |
| .. code-block:: c |
| :linenos: |
| |
| var System = xdc.useModule("xdc.runtime.System"); |
| var SysMin = xdc.useModule("xdc.runtime.SysMin"); |
| SysMin.outputFxn = "&myOutputFxn"; |
| System.SupportProxy = SysMin; /* not really necessary since this is the default */ |
| |
| Of course there may be other reasons why the use of SysMin is not |
| appropriate. For example, you may want to output characters at the time they |
| are generated rather than buffering them. In this case, you'll need to create |
| your own ISystemProvider module. For information about how to create a new |
| ISystemProvider module see Extending xdc.runtime System. |
| |
| System Concurrency support |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| The System module is a `gated |
| module <http://rtsc.eclipseprojects.io/docs-tip/Glossary#GatedModule>`__. |
| 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() <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Gate.html#enter.System>`__ |
| and |
| `Gate\_leaveSystem() <http://rtsc.eclipseprojects.io/cdoc-tip/index.html#xdc/runtime/Gate.html#leave.System>`__ |
| APIs. |
| |
| |image6| |
| |
| For more information about using the xdc.runtime package in |
| multi-threaded applications, see `Multi-Threading |
| Support <http://rtsc.eclipseprojects.io/docs-tip/Working_with_xdc.runtime#Multi-Threading_Support>`__. |
| `Using xdc.runtime |
| Gates <http://rtsc.eclipseprojects.io/docs-tip/Using_xdc.runtime_Gates>`__ |
| contains more details about gates, how to protect shared data |
| structures using gates, and how to create new gates. |
| |
| Core Instance Support |
| ===================== |
| |
| Functional Goals |
| ---------------- |
| |
| The RTSC runtime model is intended support any real-time embedded system |
| and to usefully scale down to systems with extremely tight memory |
| constraints - as little as 1KB of RAM and 32KB of Flash - while |
| providing a uniform modular object oriented API for all target code. To |
| make this possible, RTSC module instances can be created statically, |
| dynamically using the heap, or dynamically using *any* memory managed by |
| the application. This allows applications to work with object oriented |
| APIs *without requiring any runtime heap memory management*. |
| |
| It's also important that low-level module instance objects, such as |
| queues and semaphores, are capable of being dynamically created entirely |
| from stack memory. Stack memory management can be done |
| *deterministically*, with effectively *no runtime overhead*, and without |
| any possibility of fragmentation issues inherent in heap memory |
| management. This makes stack memory ideal for small embedded systems |
| with must operate in a fail-safe manner within strict real-time |
| constraints. Thus, the non-heap instance construction methods must also |
| support memory dynamically allocated by the runtime stack (i.e., |
| ordinary C automatic variables). |
| |
| Finally, it's important to ensure that a single module implementation be |
| able support the full range of embedded applications - from the largest |
| embedded system to tiny 1KB RAM systems. It must be easy for modules to |
| support *all* forms of instance creation *without any additional |
| runtime* code. |
| |
| Architecture Introduction |
| ------------------------- |
| |
| All RTSC modules share a common design pattern similar to C++ or Java |
| classes: each module is associated with a module state object and |
| optionally defines an instance constructor. Both modules and instances |
| optionally supply methods that implicitly operate on the state of the |
| module or instance. Unlike instance objects that may be conditionally |
| created at runtime, module state objects are singletons that are |
| statically defined just once (i.e., before the application starts). |
| |
| The purpose of xdc.runtime.Core module is to provide common code for the |
| implementation of all module constructors and destructors, simplifying |
| their implementation, minimizing the total application runtime |
| footprint, and ensuring consistent behavior. Moreover, this design also |
| enables efficient trace of the lifecycle of any module's instances via |
| `Event Logging <#real\-time-diagnostics-event-logging>`__. |
| |
| The xdc.runtime.Core module is simple a collection of functions used in |
| the creation and destruction of *all* module instances. But, this module |
| is itself *never* directly called by application-level code; it is only |
| used in the *implementation* of RTSC modules. The figure below |
| illustrates the relationship between Core and all other RTSC modules, |
| including the xdc.runtime modules. |
| |
| |Runtime_use| |
| |
| This figure depicts several important aspects of the xdc.runtime modules |
| |
| - *all* modules that define instances (represented by the *ModX* node) |
| do so via the Core module |
| |
| - with the exception of the platform specific adapters (e.g., |
| HeapMin), the xdc.runtime modules are "static only"; i.e., they do |
| not directly define instances |
| |
| - there are two modules, Text and Core, which are not intended to be |
| directly used by applications. Their APIs are designed specifically |
| for the needs of the xdc.runtime package and the RTSC IDL code |
| generator where performance and footprint are prioritized over ease |
| of use. |
| |
| - some of the xdc.runtime modules make use of one another |
| |
| Note: to keep this figure understandable, not all "Uses" relations are |
| depicted. For example, the modules represented by *ModX* can directly |
| use Memory, Timestamp, System, Assert, etc. |
| |
| Architecture |
| ------------- |
| |
| .. Requirement |
| | REQ_TAG(SYSBIOS-871), REQ_TAG(SYSBIOS-872), REQ_TAG(SYSBIOS-873) |
| | REQ_TAG(SYSBIOS-874), REQ_TAG(SYSBIOS-875), REQ_TAG(SYSBIOS-876) |
| | REQ_TAG(SYSBIOS-878), REQ_TAG(SYSBIOS-879) |
| |
| |
| All RTSC module instance constructor methods follow a common pattern: |
| |
| - arguments that lack a reasonable default appear first, |
| |
| - if it's possible for the constructor to fail, an Error\_Block pointer |
| is passed as the last argument, |
| |
| - all other arguments are encapsulated in a "Params" structure and |
| passed as a pointer to the constructor, |
| |
| - if the Params pointer is NULL, the module's specified default values |
| for these parameters are used, otherwise, the referenced "Params" |
| structure must be initialized via a *Mod*\ \_Params\_init() function |
| and only parameters of interest need be updated prior to invoking the |
| module's constructor, |
| |
| - memory for heap-based instance objects is allocated by the module's |
| "create" method whereas memory for stack-based and static objects is |
| allocated by the caller and passed as the first parameter to the |
| module's "construct" method. |
| |
| Leveraging this common pattern, the xdc.runtime.Core module defines a |
| small set of functions that encapsulates the common code for all |
| instance object memory management in the system. To ensure the |
| xdc.runtime.Core functions are applicable to *any* module's instances, a |
| uniform description of each instance type, in the form of a const |
| xdc\_runtime\_Core\_ObjDesc structure, is passed to the construction |
| methods. |
| |
| .. code-block:: c |
| :name: Core_ObjDesc |
| |
| struct xdc_runtime_Core_ObjDesc { |
| CPtr fxnTab; /* pointer to module fxns */ |
| Types_Link *modLink; /* link to runtime instances */ |
| SizeT objAlign; /* alignment of instance object */ |
| IHeap_Handle objHeap; /* heap from which obj is allocated */ |
| SizeT objName; /* offset into obj for name pointer */ |
| SizeT objSize; /* sizeof obj (including header) */ |
| CPtr prmsInit; /* pointer to default Mod_Params */ |
| SizeT prmsSize; /* size of these default parameters */ |
| }; |
| |
| The xdc\_runtime\_Core\_ObjDesc structure together with a static |
| constant structure of module-specific parameter defaults provide *all* |
| the information necessary for the Core module's functions to create |
| instances for any RTSC module. This includes the management of optional |
| parameters to a module's instance constructors. |
| |
| It is up to each module to define its own the static and dynamic |
| constructors that are directly invoked by the application. In practice, |
| these functions are nothing more than a few lines of code which "wrap" |
| calls to the xdc.runtime.Core module's functions followed by a call to a |
| module-specific instance state initialization function. |
| |
| The figure below illustrates the general instance construction pattern |
| as well as the relationship between a module, say ModX, its constant |
| descriptor structure, and the xdc.runtime.Core module's functions. |
| |
| |image7| |
| |
| The sections below illustrate, in greater detail, how a hypothetical |
| module, *ModA*, uses the xdc.runtime.Core functions to implement its |
| constructors. To simplify these sections, we do not show every possible |
| variation allowed by xdc.runtime.Core; e.g., although the possibility of |
| errors occurring in constructors is supported by xdc.runtime.Core, the |
| examples below assume *ModA*\ \_construct never fails. |
| |
| Instance construct/destruct |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| This section illustrates the use of xdc.runtime.Core functions in the |
| implementation of the construct/destruct methods of a hypothetical |
| module named *ModA*. To support module instance objects that are not |
| necessarily allocated from the heap, a pointer to a *ModA*\ \_Struct is |
| passed from the application to the constructor; allocation this |
| structure is the responsibility of the caller. |
| |
| For the purpose of this example, we suppose that *ModA* supplies two |
| functions: *ModA*\ \_Instance\_init and *ModA*\ \_Instance\_finalize |
| which are called to perform any module-specific initialization or |
| finalization of *ModA* instances. |
| |
| **ModA\_Params\_init** |
| |
| .. code-block:: c |
| :name: ModA_Params_init |
| |
| void ModA_Params_init(ModA_Params *prms) |
| { |
| if (prms != NULL) { |
| xdc_runtime_Core_assignParams__I( |
| prms, |
| &ModA_Object__PARAMS__C, |
| sizeof(ModA_Params), |
| sizeof(xdc_runtime_IInstance_Params) |
| ); |
| } |
| } |
| |
| **ModA\_construct** |
| |
| .. code-block:: c |
| :name: ModA_construct |
| |
| void ModA_construct(ModA_Struct *obj, |
| const ModA_Params *paramsPtr); |
| { |
| ModA_Params prms; |
| |
| /* common instance initialization */ |
| xdc_runtime_Core_constructObject__I( |
| &ModA_Object__DESC__C, /* instance description */ |
| obj, /* memory for instance object */ |
| &prms, /* tmp memory for all params */ |
| (xdc_CPtr)paramsPtr, /* params supplied by caller */ |
| 0, /* unused (for backward compat) */ |
| NULL /* optional error block */ |
| ); |
| |
| /* module-specific initialization */ |
| ModA_Instance_init((xdc_Ptr)obj, &prms); |
| } |
| |
| **ModA\_destruct** |
| |
| .. code-block:: c |
| :name: ModA_destruct |
| |
| void ModA_destruct(ModA_Struct *obj) |
| { |
| xdc_runtime_Core_deleteObject__I( |
| &ModA_Object__DESC__C, |
| obj, |
| (xdc_Fxn)ModA_Instance_finalize, |
| -1, |
| TRUE |
| ); |
| } |
| |
| |
| The methods defined above support the instance lifecycle pattern shown |
| below. |
| |
| .. code-block:: c |
| :name: ModA_construct_lifecycle |
| |
| ModA_Struct inst; /* alloc space for instance */ |
| ModA_Params params; /* alloc space for params */ |
| |
| ModA_Params_init(¶ms); /* init params to defaults */ |
| params.foo = 3; /* change one or more params ... */ |
| : |
| ModA_construct(&inst, ¶ms); /* fully initialize inst */ |
| |
| ModA_doSomething(&inst, ...); /* invoke ModA methods ... */ |
| : |
| ModA_destruct(&inst); /* finalize inst */ |
| |
| |
| Instance create/delete |
| ~~~~~~~~~~~~~~~~~~~~~~ |
| |
| This section illustrates the use of xdc\_runtime\_Core functions in the |
| implementation of the create/delete methods of a hypothetical module |
| named *ModA*. Recall that create/delete supports module instance |
| lifecycles that use heap memory. |
| |
| However, many similarities exist between this implementation and the |
| construct/destruct implementation illustrated |
| `above <#instance-construct-destruct-support>`__. In fact, the |
| *ModA*\ \_Params\_init() method is identical and is omitted below. The |
| primary difference between the two forms of instance creation is that |
| create/delete must handle to case where memory is not available and |
| simply return a failure to the caller. |
| |
| As above, we suppose that *ModA* supplies two functions: |
| *ModA*\ \_Instance\_init and *ModA*\ \_Instance\_finalize which are |
| called to perform any module-specific initialization or finalization of |
| *ModA* instances. |
| |
| **ModA\_create** |
| |
| .. code-block:: c |
| :name: ModA_create |
| |
| ModA_Handle ModA_create(const ModA_Params *paramsPtr, |
| xdc_runtime_Error_Block *eb) |
| { |
| ModA_Params prms; |
| ModA_Object *obj; |
| |
| /* common instance initialization */ |
| obj = xdc_runtime_Core_createObject( |
| &ModA_Object__DESC__C, /* instance description */ |
| NULL, /* memory for instance object */ |
| &prms, /* tmp memory for all params */ |
| (xdc_CPtr)paramsPtr, /* params supplied by caller */ |
| 0, /* unused (for backward compat) */ |
| eb); /* needed for heap alloc failures */ |
| |
| if (obj == NULL) { |
| return NULL; |
| } |
| |
| /* module-specific initialization */ |
| ModA_Instance_init(obj, &prms); |
| return obj; |
| } |
| |
| **ModA\_delete** |
| |
| .. code-block:: c |
| :name: ModA_delete |
| |
| void ModA_delete(ModA_Handle *instp) |
| { |
| xdc_runtime_Core_deleteObject( |
| &ModA_Object__DESC__C, |
| *((ModA_Object**)instp), |
| NULL, |
| -1, |
| FALSE); |
| *((ModA_Handle*)instp) = NULL; |
| } |
| |
| |
| The methods defined above support the instance lifecycle pattern shown |
| below. |
| |
| .. code-block:: c |
| :name: ModA_create_lifecycle |
| |
| ModA_Handle inst; /* handle returned by create */ |
| ModA_Params params; /* alloc space for params */ |
| |
| ModA_Params_init(¶ms); /* init params to defaults */ |
| params.foo = 3; /* change one or more params ... */ |
| : |
| inst = ModA_create(¶ms, NULL); /* fully initialize inst */ |
| |
| ModA_doSomething(inst, ...); /* invoke ModA methods ... */ |
| : |
| ModA_delete(&inst); /* finalize inst */ |
| |
| |
| .. |image0| image:: ./media/image4.png |
| :width: 6.48958in |
| :height: 3.28125in |
| .. |image1| image:: ./media/image5.png |
| :width: 7.26042in |
| :height: 2.72917in |
| .. |image2| image:: ./media/image6.png |
| :width: 6.66667in |
| :height: 3.15625in |
| .. |image3| image:: ./media/image7.png |
| :width: 6.41667in |
| :height: 5.32292in |
| .. |image4| image:: ./media/image8.png |
| :width: 7.30208in |
| :height: 2.80208in |
| .. |image5| image:: ./media/image9.png |
| :width: 6.20833in |
| :height: 4.72917in |
| .. |image6| image:: ./media/image10.png |
| :width: 4.75000in |
| :height: 4.58333in |
| .. |image7| image:: ./media/image11.png |
| :width: 5.66667in |
| :height: 4.20833in |
| .. |RuntimeTime| image:: ./media/RuntimeTime.png |
| :width: 5.66667in |
| :height: 4.20833in |
| .. |Runtime_use| image:: ./media/Runtime_use.png |
| :width: 5.66667in |
| :height: 4.20833in |