1. Why variants are necessary
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
applstdef_emC.h
-
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.
2. C++ and C usage
-
__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 ofextern "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/TP
for 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
The 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 extern "C"
.
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.
3. ObjectJc capability
The base struct
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.
The ObjectJc
references 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
-
ObjectArrayJc
-
DEF_ObjectJc_SIMPLE
: The basic structureObjectJc
, see ObjectJc.en.html can be defined as small basestruct
need 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.
If 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 withDEF_ObjectJc_SIMPLE
than theObjectJc
basestruct
contains the reference to its reflectionClassJc
. 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.
4. String handling
-
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_ONLY_CHAR_StringJc
5. Exception and Thread Context
-
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, asuint32
word. For deployment the code to a 32-bit-System the sameuint32
words 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).
6. ClassJc and Reflection handling
The struct ClassJc
contains the type data for any data, it is referenced in
ObjectJc
. The ClassJc
can be presented in full capability,
which is necessary if the target software should contain full symbolic access to all data
(then 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 (TypeClassJc
) 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 ofClassJc
cannot be defined.
The ClassJc
data also regard the definition of DEF_NO_StringJcCapabilities
.
If it is set, no textual information are given.
But the 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.
The 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