Software for embedded systems should be run under different conditions:
very fast realtime
small memory available
C or C++ usage
elaborately error checks
safety or fast
The user software itself should not be changed for this challenges, that is the concept of emC: embedded multiplatform C/C++
The possibilities can control the variants for compilation:
a) choice of a proper include path for
b) apply a specific
applstdef.h(which can include one of the standard ones and add some defines)
c) Set defines as compiler call arguments combined with a)
All three possibilities of control are adequate in effect. The b) documents the variant in files in the best case. It should be favored.
The emC basic header regard the variants of compiling conditions. The user software can call operations, which are really macros specified to the variants. The user software should not regard the variants.
One of the basic idea of emC is: Test in a PC-based high level C++ compilation environment - and deploy the well tested software on target with the target conditions. All sophisticated software checks are done on PC testing, the software should be widely error-free after them and can deploy without these checks on target to run fastly - without adapting the sources. It means the software can be run and checked again on PC for enhancements, without change the sources, and without sophisticated #ifdef constructs.
__cplusplus: Selecting *.c-sources for C++ compilation. This can be done by compiler switch only. If C++-Projects are mixed with c-compiled sources, a correct handling of
extern "C"is necessary.
DEF_CPP_COMPILE: This compiler switch have to be set if C-Sources should be compiled with C++. That should be matching with compiler options to force CPP-compilation. It is
/TPfor Visual Studio and
-x c++for GNU compiler.
All Functions which are implemented in C-Sources should be declared in the header with
extern_C Type myOperation_Type(...); //always as C-functions .... extern_CCpp Type myOperation_Type(...); //defined depending DEF_CPP_COMPILE
extern_C is replaced by
extern "C" for C++-compilation.
That prefix forces a C-like Linker label with only the name of the operation,
without argument-sensitivity (signature of the operation). A C-compiled object file
contains this simple label only. The C++ linker regards it.
The second form regards the compiler switch
DEF_CPP_COMPILE. Only if it is not set
then the macro
extern_CCpp is defined as
Elsewhere it assumes that the associated c-source is compiled with C++.
The call of the operation in a C++ environment expects a linker label with argument
sensitivity (signature of the operation). It should be offered by the C-routine
and requests the C++ compilation.
There may be some source which are never compiled with C++ because there are very simple
(then C++ is never necessary) or they define
const-data for a const memory segment
(for example immediately contained and read from a Flash Memory in an embedded device).
For that sources
extern_C should be used anyway.
ObjectJc is recommended as base for all data.
With this unique base the type and size of data can be evaluate in debugging situations
outside an IDE (data view on target), for evaluating extracted data, and for safety
in an application using type and size checks.
In cohesion with Reflection.en.html the data can be evaluated
without knowledge of the data structure especially for unknown software versions,
for example in data evaluating situations on legacy software.
ClassJc const* reflection.
The full capability of
ObjectJc supports an handle for mutex and notify objects
(as in Java) and contains information about the structure inside a block of a block heap.
For that 24 bytes are necessary. It may be seen as 'too much' if that features
are not necessary. Hence some variants of ' ObjectJc' can be used:
The full capability of ObjectJc allows
derived `struct`for ObjectOrientation in C with type test
dynamic linked operation in C with type check
DEF_ObjectJc_SIMPLE: The basic structure
ObjectJc, see ObjectJc.en.html can be defined as small base
structneed only 4, 8 or 12 byte on a 32-bit-platform. The small variants do reduce the possible type check and do not support symbolic access. It may be not necessary in deployed embedded applications.
DEF_ObjectJc_SIMPLE is set, the following compiler switch is regarded additionally:
See also ObjectJc.en.html.
DEF_ObjectJc_REFLREF: If this compiler switch is set together with
structcontains the reference to its reflection
ClassJc. See chapter Reflection handling. Only then evaluating of base structures or base classes in C++ can be checked. It is important for an safety type check. It needs additionally 4 bytes in 32-bit-systems.
DEF_NO_StringJcCapabilities: Some DSP processors (Digital Signal Processor) do not handle String operations in a proper way. Only simple `char const*`can be stored. A String processing is not desired. For that variant this define is set. It reduces String handling in the basic emC functionality.
DEF_ThreadContext_SIMPLE: The thread context is a memory area which is thread specific, or interrupt execution specific too (this is also a thread). The `
DEF_HandlePtr64: In some 64-bit-Applications, for example S-Functions in Simulink, all memory addresses of instances (…of Function Blocks) are held in a global accessable address table. The references are handles - index to the table, as
uint32word. For deployment the code to a 32-bit-System the same
uint32words as connection data between function blocks (aggregations in UML-slang) contains the really memory addresses, for fast access. This is regarded by code generation in Simulink (® Mathworks) - via specific tlc files (tlc = target language control).
struct ClassJc contains the type data for any data, it is referenced in
ClassJc can be presented in full capability,
which is necessary if the target software should contain full symbolic access to all data
DEF_REFLECTION_FULL is present).
Or it is a small
struct only to support type assignment.
See ObjectJc.en.html, chapter Reflection and Types.
DEF_REFLECTION_FULL: The reflection (see Reflection.en.html) contains the possibility of symbolic access to all data. This feature allows dynamic programming in C and C++, for example find out a data element because of its textual identifier name gotten via a communication telegram, or executed an operation by symbolic specification. For example symbolic data access via Inspector.en.html can be used. That features are proper not only for PC programming but for rich powerful embedded applications. For that the symbolic information (reflection) should be generated from the header file information with the tool CHeader2Reflection.en.html.
DEF_REFLECTION_OFFS: To prevent effort on target but allow symbolic data access via the Inspector.en.html tool a inspector target proxy can be used. That proxy contains the textual information and communicates with the target via simple memory accesses. The target should contain generated Reflection information which contains only the offsets# to all data in a struct, because the offsets may be specific on target compilation (cannot be presumed by a compiler- and situation-independent tool). For that this compiler switch can be set.
DEF_REFLECTION_SIMPLE: If this macro is set, only type information is contained in reflection data (Type
ClassJc) to support safety type checks.
DEF_REFLECTION_NO: Whether type nor symbolic access can be done. This is the simplest form - no reflection usage. Instances of
ClassJccannot be defined.
ClassJc data also regard the definition of
If it is set, no textual information are given.
ClassJc const reflection_MyType -instance represents the type able to check
via its memory address. But that type check cannot be done over dynamic linked libraries,
the last one requires the name of the type.
DEF_NO_StringJcCapabilities compiler switch should be set
only in small capability or only numeric embedded systems.
If the reflection are generated via the CHeader2Reflection.en.html tool, there are generated files. The following form are preferred to include it:
#ifdef DEF_REFLECTION_FULL #include "genRefl/MyType.crefl" #elif defined(DEF_REFLECTION_OFFS) #include <emC/Base/genRefl/Time_emC.crefloffs> #else //DEF_REFLECTION_SIMPLE, or DEF_REFLECTION_NO ClassJc const reflection_Clock_MinMaxTime_emC = INIZ_ClassJc(reflection_Clock_MinMaxTime_emC, "Clock_MinMaxTime_emC"); #endif