The Cmicro Library consists of a configurable SDL kernel together with all the necessary SDL data handling functions. The collection of C functions and C modules make up the so called SDL machine.
The Cmicro Library is used in combination with the C code generated by the Cmicro Code Generator. For information on the generator see The Cmicro Code Generator.
The scaling facilities in Cmicro mean that it is useful for both micro controller and real-time applications. The BodyBuilder is a tool which helps find the correct scalings. Please see The BodyBuilder in this chapter.
The Cmicro Tester offers the ability to target tests and debug Cmicro code. Please see The Cmicro Tester.
The Cmicro Library is required for handling the SDL objects that have been generated from SDL into C with the Cmicro Code Generator. This means that the C code which was generated with the Cmicro Code Generator cannot be used without the Cmicro Library. It also means that the C code generated with Cadvanced cannot be used together with the Cmicro Library and vice versa.
The Cmicro Library is a collection of C functions and C modules which consists of:
Note: The Cmicro preemptive kernel is only available if the according license is available. |
Furthermore the Cmicro Library can be instrumented with Cmicro Tester functionality.
Before the Cmicro Library can be used, some adaptations and configurations must be made. The BodyBuilder is a tool which helps in configuring the target application and the Cmicro Tester. If the user chooses one of the predefined kernels of Cmicro in the Organizer's Make dialog, the use of the BodyBuilder is not always necessary.
In this chapter, the C source code of the Cmicro Library and the generated C code of an application are described. Although a separate chapter is dedicated to the Cmicro Tester (see The Cmicro Tester), a few features are outlined here. The following topics are discussed:
Pay extra attention to the subsection Automatic Scaling Included in Cmicro, which contains important information on the differences to the Cadvanced Library.
If examples of generated code are given, they are always shown in ANSI style. In addition, only the important parts of the code are shown to increase readability in the examples.
This description deals with the differences between the generated C code of the Cadvanced and the Cmicro Code Generator and the run-time libraries. There are differences because the main application area for the code generators differ.
Some of the differences discussed in the following are of interest for SDL users, while others are not.
The Cmicro Code Generator has more SDL restrictions than the Cadvanced Code Generator. The additional restrictions are described in the subsection SDL Restrictions.
Furthermore, there are restrictions within the Cmicro Library that may affect the user's SDL system design. These restrictions are listed in the following. More technical information can be found in the section Generation of Identifiers.
yInit
).The subsection Cmicro Kernel/Library explains the definitions that can be changed with the BodyBuilder.
First, it must be emphasized that both schedulers conform fully with SDL, although the schedulers introduce a different behavior.
Cadvanced uses a process ready queue together with signal queues in order to schedule processes. Cmicro does not use a process ready queue but all scheduling is derived from one physical queue. This physical queue represents all SDL process input ports. Logically, or seen from SDL, each SDL process has its own input port.
Another difference is the preemptive scheduler of Cmicro, if it is used.
Thus, different execution of processes will occur.
It is also a question of SDL design whether the differences between Cadvanced and Cmicro can be externally recognized.
If no SDL process assumes a particular real-time behavior from its communicating partner process then the behavior -- as seen from a black box view -- is always the required one.
The Cmicro Code Generator generates some more files. This is of interest when implementing build scripts, makefiles and so on.
It is important that after each change in the SDL system the Cmicro Library is re-compiled. The reason for this is the automatic scaling facility. Please view Automatic Scaling Included in Cmicro.
The main differences arise when considering the environment handling functions. However, this only has consequences if the SDL environment is the same in both cases (if Cadvanced is used for simulation only and Cmicro for targeting, then the environment functions are to be implemented twice in any case).
Instead of including scttypes.h
as in Cadvanced, for Cmicro the following include statements are to be introduced in the header of the environment module:
#include "ml_typ.h" #include "<systemname>.ifc"
In general (for Cmicro as well as Cadvanced) four C functions are used to represent the SDL environment, namely
xInitEnv,
xInEnv,
xOutEnv,
xCloseEnv.
The functions have the same general meaning for Cadvanced and Cmicro, but there are a few differences so that it is necessary to implement the environment twice.
For Cmicro, each of the above C functions is compiled only if it is required (selected by XMK_USE_xInitEnv, XMK_USE_xInEnv
...)
Differences occur in the declaration of the C functions xInEnv()
and xOutEnv()
.
The xInEnv()
function of Cmicro carries no parameters.
The xOutEnv
() function of Cmicro carries a few parameters which represent the signal which is to be output to the environment, including the signal parameters. It is recommended that the definition of the C function xOutEnv()
should be written twice, once for Cadvanced and once for Cmicro.
The environment functions of Cmicro can also be generated with the help of the BodyBuilder, but the BodyBuilder does not help for Cadvanced.
Another difference is that signals and processes are identified in different ways. Cmicro does not use identifications like xIdNode
. Instead, it uses fixed C defines to identify signals and processes. This is beneficial in reducing the amount of memory but has the consequence that each access to any signal and any process is to be implemented differently. Process type IDs are generated into the file sdl_cfg.h
, signal IDs and type definitions are generated into the <systemname>.ifc
file. The chapter about the Cmicro Code Generator gives more details on how identifiers are generated and can be used.
C code may be included in SDL by the user in the following cases:
xInEnv() / xOutEnv()
If any C code or C identifiers are used, then users must use the right identifiers and functions.
Of course, the generated C code is different when comparing Cmicro with Cadvanced. It would take too much room to list all the details in this subsection. In any case these differences are of interest for certain technical reasons only and not for pure SDL users.
To compare the different code generator outputs, the user should refer to the subsection Output of Code Generation.
In order to reach full compatibility between Cadvanced and Cmicro, the following general recommendations should be followed:
XSCT_CMICRO
will help to distinguish automatically.In this section, the concepts of the Cmicro SDL scheduler are outlined, with particular emphasis on basic SDL, the handling of the queue, scheduling, signals, timers, states etc. To obtain information about data in SDL, especially ADTs, please consult The Cadvanced/Cbasic Code Generator. Here both predefined and user defined ADTs are outlined.
Each signal that is either an ordinary SDL signal, a timer or the start-up signal used for the dynamic process creation, is represented by three structures:
The first and the second is defined in ml_typ.h
, the third is defined in the generated code as yPDef_SignalName
. Some structure components are conditionally compiled, which is used to scale the system. Please view the following C structure:
typedef struct { #ifdef XMK_USE_RECEIVER_PID_IN_SIGNAL xPID rec; /* Receiver process */ #endif xmk_T_SIGNAL signal; /* Signalcode */ #ifdef XMK_USE_SIGNAL_PRIORITIES xmk_T_PRIO prio; /* Priority */ #endif #ifdef XMK_USE_SIGNAL_TIME_STAMP xmk_T_TIME time_stamp;/* Timestamp */ #endif #ifdef XMK_USE_SENDER_PID_IN_SIGNAL xPID send /* Sender process */ #endif #ifdef XMK_USED_SIGNAL_WITH_PARAMS xmk_T_MESS_LENGTH mess_length; union { void *ParPtr; #if (XMK_MSG_BORDER_LEN > 0) unsigned char ParCopy[XMK_MSG_BORDER_LEN]; #endif } ParUnion; #endif } xmk_T_MESSAGE;
signal:
represents a C constant which uniquely identifies the signal or timer across the complete system.rec and send:
represents the pid values of the receiver and sender of the signal. See the subsection Processes and Process IDs (PID) for details. These are conditionally compiled.prio
:#PRIO
in the SDL diagram. It is compiled only, if signals with priority are stipulated by the user.timestamp:
is used to store a timestamp, which is set when the SDL signal is put into the queue (output time). This component is also conditionally compiled.mess_length:
represents the amount of parameter bytes in the signal.Three different cases are to be considered concerning signals with parameters:
mess_length
is set to 0 and ParPtr
is a NULL
pointer.mess_length
is set to the number of bytes and ParPtr
is undefined. mess_length
defines the amount of bytes used for the parameters and ParPtr
points to a dynamically allocated area.
Note: This margin of XMK_MSG_BORDER_LEN bytes can of course be modified by the user to prevent dynamic memory allocation for any signal in the queue, or in contrast, to always use dynamic memory allocation. See the file |
The second structure, which encapsulates the above one, is used to administrate the signals in the queue, as required by the FIFO handling and SDL save construct:
typedef struct _T_E_SIGNAL { xmk_T_MESSAGE Signal; struct _T_E_SIGNAL *next; #ifdef XMK_USED_SAVE xmk_T_STATE SaveState; #endif /* XMK_USED_SAVE */ } T_E_SIGNAL ;
next:
is a pointer which refers to the next entry of the queue. This is used by the Cmicro Kernel to get the next signal after the current one has been worked on.SaveState:
contains either a dummy state value 0 or the state in which the process saved the signal. This is necessary to compare when the signal is to be consumed after state changes in the receiver process. It is used only if save is used anywhere in the SDL system.As already mentioned, the above structure is used for ordinary SDL signals, timers and the start-up signal for the dynamic process creation.
No differentiation is made between signals and timers, except that signals and timers have a different identification (signal in the xmk_T_SIGNAL
structure).
When a process is to be created, a start-up signal is sent. The start-up signal is tagged by a special priority value and a special id.
Dynamic memory allocation is in principle not necessary with Cmicro. There are SDL systems which can live without any dynamic memory allocation and there are SDL systems that require dynamic memory allocation from the user's point of view. The users should in general try to prevent any dynamic memory allocation due to the problems this introduces. Soon or later memory leaks will occur.
Cmicro offers its own dynamic memory allocator. Please view Dynamic Memory Allocation for getting more information on this.
In the following subsections, the exceptions for when Cmicro uses dynamic memory allocation are listed.
In order to cope with efficiency, dynamic memory allocation should not be done, whenever possible. Cmicro offers two principles of memory allocation for signal instances, namely:
XMK_MAX_SIGNALS
macro. To enable this configuration, the macro XMK_USE_STATIC_QUEUE_ONLY
is to be set. This principle has the disadvantage that if there is no free memory in the static memory pool, a fatal error occurs. The user is however given the possibility to react on this error situation because the ErrorHandler
C function is called.
This configuration is not available when the preemptive scheduling mechanism is used. |
To enable the configuration, the macro XMK_USE_STATIC_AND_DYNAMIC_QUEUE
must be set. The static memory pool's size is still predefined with the XMK_MAX_SIGNALS
macro.
When signal instances are allocated from the static memory pool, the allocation procedure is the most efficient.
When the second principle is used, the execution speed will of course dramatically slow down because dynamic memory allocation happens. This change in the behavior of the Cmicro Kernel may cause problems in a real-time environment and the user should keep this in mind.
The static memory pool above is implemented as a predefined array in C. The array is dimensioned with the XMK_MAX_SIGNALS
macro.
Dynamic memory is requested with the xAlloc
C function and released again with the xFree
C function. The body of both these C functions must in any case be filled out appropriately by the user in all cases.
Signal parameters are to be allocated dynamically, if the amount of parameter bytes exceeds a predefined constant. If the amount of signal parameters is below or equal this predefined constant, the parameter bytes are put into the signal's header.
The default value for this predefined constant XMK_MSG_BORDER_LEN is 4 bytes. Dynamic memory allocation only occurs if a signal carries more than XMK_MSG_BORDER_LEN
bytes, where the latter is defined as 4.
If the user defines XMK_MSG_BORDER_LEN
as 0, then for each signal, which has parameters, the C function xAlloc()
is called.
If the user defines XMK_MSG_BORDER_LEN
to 127, then
xmk_T_SIGNAL
structure.Alloc()
).Due to this mechanism, the allocation of signal parameters is also very fast. Releasing the memory is performed automatically by calling the xFree
C function.
Some of the predefined sorts require dynamic memory allocation. The sorts are
If the Cmicro Tester is used, there are some more allocations from the dynamic memory pool. The Cmicro Tester allocates one block of dynamic memory in the start phase. This block is never de-allocated again. The size of the block depends on the amount of process types in the system. Another dynamic memory allocation takes place when a binary frame is to be sent to the host machine. The blocks that are allocated here are de-allocated again after the frame is put into the physical transmitter buffer.
Output and input of signals is performed according to the rules of SDL. To get detailed information about the implementation of output and input, please consult the subsection Output and Input of Signals.
Signal instances are sent using the C function xmk_Send()
or xmk_SendSimple()
. The function takes a signal and puts it into the input port of the receiving process instance.
Figure 541 : Queueing - sending side
|
There is no process ready queue. Physically, the queues of the different processes of the system are represented by just one queue. There are different principals to create signal instances which the user can choose between. The principals are explained within the subsection Signals and Signal Parameters.
From an abstract point of view, it does not matter, if there is one physical queue for all the signal instances in the system, or if there is one physical queue for all the signal instances sent to one process instance. The fact that Cmicro uses one physical queue for all signals in the system only, has no effect on SDL users and conforms to the semantic rules of SDL. The scheduling simply depends on the ordering of signals in the queue. In the case of a preemptive Cmicro Kernel scaled this way, there is one linked list of signals per priority level all using the array mentioned above. See the subsection Scheduling for details.
Figure 542 : Queueing - receiving side
|
When working on a signal, the Cmicro Kernel decides between four different constellations:
ErrorHandler()
, discussed within the subsection User Defined Actions for System Errors -- the ErrorHandler, will be called.In any case, except when being saved, the signal will be removed from the queue and returned to the list of free signals.
After performing the nextstate operation, the input port is scanned in accordance with the rules of SDL to find the next signal which would cause an implicit or explicit transition.
There is no specific input function. This functionality is contained in the Cmicro Kernel.
With the delivered timer model, all timer management entities fully conform to SDL. This means that more memory is required to implement this timer.
For each timer, there is a C structure defined in ml_typ.h
.
typedef struct _TIMER { struct _TIMER *next ; xmk_T_SIGNAL Signal ; xmk_T_TIME time ; xPID OwnerProcessPID ; } TIMER ;
xmk_T_TIME
is defined as a long value.
Figure 543 : Handling of timers (timer model 1)
|
The component
next
is used to refer to the next entry;signal
is the timer identification;time
is used to store the absolute time when the timer should expire;OwnerProcessPID
is used to refer to the process PID for which the timer was set.As can be seen above, timers are implemented as a forward linked list.
Note: Timers with parameters are not implemented. |
Each process is represented by structures and tables containing SDL information, for example, tables containing transition definitions and a structure representing the variables of the process. The typedef for variables is generated in the generated code and named yVDef_ProcessName
. For each process instance, there is one array element defined statically during compile time.
The structures and tables for processes are described in detail in the subsection Tables for Processes.
The Cmicro Kernel supports in principle the following scheduling policies:
Further explanation of the scheduling is in the next subsection.
The Cmicro Kernel takes the first signal from the queue and if the signal is not to be saved the appropriate SDL transition is executed until a nextstate operation is encountered. Outputs in SDL transitions as well as SDL create operations are represented by signals, where create signals are given priority treatment no matter whether signal priorities are used or not. This guarantees that there will not be any problems when a signal is sent to a process just before the process has been dynamically created.
The ordering of signals in the queue can be affected by using signal priorities (#PRIO directive for signals).
Whenever an output takes place, the Cmicro Kernel inserts the signal into the queue according to its priority. High priority signals are inserted at the queue's head, low priority signals at the queue's end. Create signals are still given priority treatment.
Figure 544 : Non preemptive scheduling
|
Figure 545 : Scheduling for Create
|
A signal (this is either an ordinary SDL signal, a timer signal or the internal start-up signal in the event of SDL create) with the highest priority is always put in front of the SDL queue, a signal with the lowest priority is always put at the end of the SDL queue.
Figure 546 : Signal priorities
|
For applications, which do not have time critical requirements, the non preemptive scheduling policy is the correct one to implement. The Cmicro Kernel memory requirements are also reduced when the non-preemptive scheduling policy is implemented. For example, for an interface with a very high transmission rate, the preemptive scheduling policy is better suited in order to increase the reaction time on external signals coming from the environment.
On starting the SDL system, processes are statically created according to their order of priority.
Note: The Cmicro preemptive kernel is only available if the according license is available. |
Figure 547 : Preemptive scheduling
|
SDL assumes the start transitions of all statically created processes are already finished at system start-up (a transition takes no time according to SDL semantics). To simulate this, the Cmicro Kernel starts all statically created processes in the order of their priority before working on any signal. Preemption is disabled during the start-up phase of the system. There are two C functions namely xmk_DisablePreemption
and xmk_EnablePreemption
which can be used to prevent the Cmicro Kernel from performing a context switch. In this way it is possible to affect the scheduling from within the SDL system (using the #CODE directive).
The preemptive scheduling policy is absolutely necessary if an application consists of a mixture of processes, of which some have to react very quickly to external events, while others require enough time for processing. The Cmicro Kernel does all things necessary to schedule such a mixture of processes.
Users only have to specify a high priority for processes which have to react after a short time. This can be done with the #PRIO directive for processes. If no #PRIO
directive is specified, then a process is given the default value, which is specified by the user in the file ml_mcf.h
(please view the subsection Compilation Flags).
The highest priority is represented by the value zero. The numbering has to be consecutive with the priority decreasing with increasing numbers. Processes with the same priority are on the same priority level. The default process priority must be in the range of zero to the lowest priority value used in the system. Assume the following priority levels:
|
In the figure above there are signals queued for processes on four different priority levels. These would be worked on in this order:
According to their priorities the signals on priority level zero are consumed first, afterwards those of level one, two and last three. This is relevant only, if no signals are sent during the transitions executed because of the signals.
Note: If C variables are to be used in the SDL application, i.e. (x, N) declarations are used where N > 1 these variables are only available once and not once per process instance. |
In order to produce portable C code, this version of the Cmicro Kernel uses recursive C function calls. A few C compilers available on the market do not support recursion. If such a C compiler is required, the user cannot use preemptive scheduling with process priorities.
No dynamic memory allocation occurs if an SDL create operation is performed. No freeing of memory occurs if an SDL stop operation is performed.
Data of a process instance is represented by the following typedef structs:
The reason for using such a structure is to make it possible for the Cmicro Kernel to operate on the PID structure and the table with SDL states, so that no code needs to be generated in the application to update such variables.
An array of N elements for each of these typedef structs is generated, where N is the maximum number of process instances. The maximum number is to be specified in the process declaration header in the SDL diagram.
After performing a stop action, old PID values might exist in variables of other processes. The synchronization between processes to prevent situations where signals are sent to dead processes is left to the discretion of the user. If a process sends a signal to a non existent process, where nonexistent means either "never created" or "is dead", the ErrorHandler
is called and the signal is discarded (SDL conform).
When the Cmicro Kernel stops a process, the input queue assigned to the process stopped will be removed. No interpretation error occurs for the signals which existed in the queue before the process was stopped.
Note: It is also possible for the user to implement dynamic memory allocation for process instance data. Some C defines are to be redefined in this case. |
The actions to perform an output in the generated code are as follows:
xmk_Send*
functions is called with a pointer to the location of the struct variable. There are several xmk_Send*
functions in order to use the most effective one in SDL output.Within the xmk_Send*
- functions there are a few checks performed. For example, if the receiver is a NULL-PID, then the ErrorHandler is called.
Next, the environment C function xOutEnv
is called. This function is to be filled out by the user. The function decides if the signal should be sent to the environment. The information necessary can be extracted from the signal ID, the priority or the receiver of the signal. If xOutEnv
has "consumed" the signal, xmk_Send*
returns immediately.
xOutEnv
has to copy the parameters of the signal to the receiver of the signal in the environment because after returning, the parameters will no longer exist.
If the signal is not environment bound, then the signal is sent to an internal SDL system process and xmk_Send*
inserts the signal into the queue. This is done according to the priority of the signal (see subsection Assigning Priorities -- Directive #PRIO.
If the signal carries no parameters, or if the signal parameters are represented by less than or equal to XMK_MSG_BORDER_LEN
bytes, no dynamic memory allocation occurs and possible parameters are transferred directly by copying them into the signal header.
If more than XMK_MSG_BORDER_LEN
bytes parameters are to be transferred dynamic memory allocation occurs. A pointer in the signal header then points to this allocated memory area. Freeing is done after consumption of the signal at the receiver process after executing the nextstate operation or after the signal was consumed by the environment.
In order to implement this strategy, each signal carries a field "data length" in its header, to detect if a pointer is transferred or a copy of the parameters.
At the receiver's side, when the input operation is to be performed, it is checked if the signal is to be saved or discarded. In the case of save, the next signal contained in the queue is checked and worked on. If on the other hand the signal is to be discarded, in the case of an "implicit transition", i.e. no definition is present to handle that signal in the current state, the signal is then deleted from the input port of the process and, using the Cmicro Tester, the user is notified.
Otherwise, the signal leads to the execution of the transition. After performing the nextstate operation, the signal is deleted from the input port of the process and scheduling continues according to the rules of the scheduler again.
In the case of a so scaled preemptive Cmicro Kernel, the signal remains active in the input port until the nextstate operation is executed, although other processes can interrupt the running one (preemption).
The nextstate operation is implemented by a return (return value) statement in the generated code. Several return values are possible to control the action to be taken by the Cmicro Kernel. The PAD function representing the SDL process can return any of the following (PAD means "Process Activity Description").
The return-value either expresses
SDL_DASH_STATE
,SDL_STOP
.After recognizing the action to be taken, the Cmicro Kernel either writes the process state variable or stops the SDL process.
The signal which was just being worked on is deleted from the input port. This includes the freeing of the memory area allocated for the signal, if memory was previously allocated.
No action is to be performed by the Cmicro Kernel for decisions and tasks, except those to trace these actions for the Cmicro Tester.
For SDL decisions and SDL tasks, C assignments and C function calls are implemented. Function calls are used in the case of an ADT or where simple C data operations (i.e. =, >, >=, ==) cannot represent the SDL operation wanted.
Note: Function calls, however, are not necessarily generated, i.e. if the user defines C macros/defines instead of C functions for an ADT. Please consult the subsection Abstract Data Types. |
There are some special topics regarding procedures in SDL. The most important are:
Note that procedures with states and remote procedure calls are not supported within the Cmicro Package.
It is possible to use global procedures (SDL'92) which makes it possible to specify a procedure once, by allowing several processes to call it.
Recursion is allowed, but should be introduced only if an algorithm cannot be designed alternatively. In most cases, algorithms and recursivity are subjects for an ADT.
Procedures returning values are also implemented. The return value in SDL is mapped to a return value in C. Procedures not returning values are mapped to C functions returning void.
The remaining part is the location of procedure data and the access to procedure data. Here another restriction exists, namely that it is not possible to access data of the father procedure of a procedure without declaring this explicitly.
Data, which belongs to a process is always located as a global array in C (for x, N process declarations, where N is >1). Data which belongs to a procedure is always allocated on a C stack for the called procedure.
An SDL procedure call is implemented as a direct function call in C. Each formal parameter is passed as a C parameter to the function. Access to global data of the calling process is possible only if the procedure is not a global procedure. The C code generated for a local procedure uses global C variables of the surrounding process.
Data which is declared locally within a procedure is also allocated on the C stack.
No dynamic memory allocation is performed as procedures with states are not handled.
The following example shows the mapping for procedures returning values.
TASK i := (call p(1)) + (call Q(i,k));
is translated to something like:
i = p(1) + Q(i,k);
Note: The value returning procedure calls are transformed to C functions returning values. |
An SDL procedure can be called more than once. No conflicts occur if using a preemptive Cmicro Kernel.
For each SDL procedure, there is one C function generated. The Procedure body can contain the same SDL actions as the process body. The same code generation is performed with the exception of a few statements declaring temporary variables.
Within global procedures, no objects of the calling process can be used without declaring them via formal parameters. Another restriction is that each output in a global procedure must be specified with to pid.
No C code is generated for blocks, channels and signal routes, except the C comment, which tells the user the location of processes and procedures.
At first it is necessary to know the directory structure the Cmicro Package is stored in.
On UNIX the Cmicro Package is contained in $sdtdir/cmicro
.
In Windows the Cmicro Package is contained in %SDTDIR%\cmicro
.
cmicro
+-- kernel
+-- mcod
+-- template
+-- commlink
+-- tester
The makefiles delivered with this version assume the above structure.
Furthermore all files which are used when targeting Cmicro are definitely stored in this directory tree. Otherwise the files are generated from the Cmicro Code Generator or from the BodyBuilder.
Before starting the targeting with Cmicro it is necessary to have an SDL system designed and already tested with the help of the Simulator.
This means targeting begins when the first testing phase is finished.
Figure 549 describes the different steps of targeting. The use of the Cmicro Tester and the possibly resulting corrections in the SDL system design are not shown here.
Figure 549 : Different steps in the targeting phase
|
All steps of targeting will be discussed in the following sub-sections.
Figure 550 shows the Organizer's Make dialog and its settings to generate Cmicro C code.
Figure 550 : Make dialog when generating Cmicro
|
The selections which must be set for Cmicro are the following:
makeoptions
which is to be implemented by the user. If the template makefile is stored in the same directory as the generated C file a dot (`.') will be enough.In this state of targeting the buttons Makefile and Compile & link should be deselected because the steps following this subsection must be carried out first.
Assumed that separation is not selected the Cmicro Code Generator will generate the files
The Cmicro Package can now be configured by using the BodyBuilder. This work should be done after code generation as the BodyBuilder needs the generated file sdl_cfg.h, <systemname>.sym
and <systemname>.ifc
to get all the necessary information about the SDL system.
For information on how to use the BodyBuilder please view The BodyBuilder.
For information about the compilation flags and their interdependencies please view Compilation Flags.
After all it is necessary to select a target compiler. If the compiler is not already included in the BodyBuilder's compiler list a new compiler can easily be introduced.
For further information on how to introduce a new compiler in the BodyBuilder please view The BodyBuilder's Definition Files.
For further information on how to introduce a compiler in the Cmicro Package please view Adaptation to Compilers.
Several files of the Cmicro Package are delivered as template files. This is done because lots of things can only be done by the user as they must fit to the user's SDL system. The template files give easy to use C functions including help to adapt them to the user's needs.
All the files mk_stim.c, mk_user.c, mk_cpu.c
and the template makefile (makeoptions
on UNIX and make.opt
in Windows) should be copied into the project directory to the generated files listed under Generate Cmicro C Code. All these files are stored in the template
directory.
If the Cmicro Tester should also be used it is necessary to copy the files dl.c
and the files describing the preferred communications link (e.g. the file 8051_v24.[ch] if an 8051 microcontroller and a V.24 interface should be used) into the project directory, too. The file dl.c
is stored in the template
directory and the communications link files are stored in template/commlink
if contained in the Cmicro Package delivery. Please view the sub-section The Communications Link's Target Site to get information about how to create an own communication link.
For an integration with an operating system there is one extra example file called light_ex.c
, which is explained in the subsection Light Integration.
To compile and link the Cmicro Package and the generated C code it is necessary to have a makefile structure which fits in any case.
On the one hand there is the need to have a generated makefile because the name of the generated C file and the kind of generation (using separation or not) can only be known by the Cmicro Code Generator.
On the other hand there has to be a makefile which is not touched by the Cmicro Code Generator to make it easy to add other C modules to the makefile destination.
There are the following variables to be defined in the template makefile.
For each variable an example is given in the template itself. The user is asked to have a look into it.
sctEXTENSION=.hex sctOEXTENSION=.r03 sctCC=icc8051 sctLD=xlink sctLD1FLAGS= -w -x -l $(USD)\link.lst -f lnk8051 #see your compiler manual for the linker file #lnk8051.xcl!! sctLD2FLAGS= sctCCFLAGS= -e -ml -L -q -P -z sctIFDEF= sctCPPFLAGS=
Description: (all the information given here will differ when using another compiler)
sctLD1FLAGS
and sctLD2FLAGS
sctCCFLAGS
and sctCPPFLAGS
The Cmicro Package can be compiled with or without using the Cmicro Tester. To achieve this there are two possible default destinations defined in the template makefile.
sctLINKTARGET_NO_TESTER
sctLINKTARGET_WITH_TESTER
As the default
destination is defined as sctLINKKERNEL,
the sctLINKKERNEL
must be set as one of the above.
The Cmicro Code Generator generates a makefile called <systemname>.m
which is responsible for the compilation of the generated C file(s).
The generation of this makefile can be configured to the used compilers needs. To achieve this a file called comp.opt
is used.
comp.opt
include >template makefile< %t$(sctCC) $(sctCPPFLAGS) $(sctCCFLAGS) $(DIR)#%c %t$(sctLD) $(sctLD1FLAGS) %o $(sctLD2FLAGS) -o %e cd %d; make -f %m >DIR<=%d
On UNIX >template makefile<
must be replaced by makeoptions
, >DIR<
must be replaced with sctdir
and #
must be replaced by /
.
In Windows >template makefile<
must be replaced by make.opt
, >DIR<
must be replaced by SCTDIR
and #
must be replaced \
.
Hint: Windows only When using Borland make there has to be an exclamation mark (!) in the first column of line 1: |
All the characters following the character `%' are special substitute characters. There are still others allowed than the ones shown in Example 457 above:
The numbering of the lines in the file comp.opt
is fixed.
After all, if the Cmicro Code Generator does not find a file comp.opt,
it generates a default solution which fits in most cases.
From the Cmicro Package's point of view the SDL environment is represented in template C functions. A short overview of this C functions is given here. For further information please view Bare Integration.
env.c
. It needs to be filled any time it is necessary to initialize specific hardware components on the target.xCloseEnv()
is given as a template in env.c
, too. It is only necessary to fill this function if the SDL system can perform a system stop.xInEnv()
is basically generated by the BodyBuilder into the file env.c
. This means that all the signals coming from the environment are already inserted into the C code of this function.
Note: All the modifications of |
xOutEnv()
into the file env.c.
All the signals to the environment are included into the C code.
Note: All the modifications of |
ErrorHandler()
in the module mk_user.c
.The compilation and linkage of the environment functions can be prevented by using the flags given in Compilation Flags.
The whole system can be compiled and linked by the Organizer. The compiler's and linker's output will be shown in the Organizer Log.
To achieve a compilation and linkage by the Organizer it is necessary to have the options Makefile and Compile & Link selected in the Organizer's Make dialog. (See Figure 550.)
The Make button is inactive. The reason is, that compilation of the complete Cmicro Library must be performed after any change in SDL. The user must use the Full Make button in any case.
When pressing the Full Make button, the whole SDL system is generated, compiled and linked.
On UNIX the environment variable sctdir
must be set to ".".
In Windows the environment variable SCTDIR
must be set to "."
After changing into the project directory it is possible to execute the generated makefile <systemname>.m
by typing
make -f <systemname>.m
The target executable can now be downloaded and executed on the real target hardware.
Different forms of target integration, that is, integrating generated C code, are distinguished:
main()
function of Cmicro can be used.Bare and Light integration represent the most easiest form of integration.
Bare integration is described in Bare Integration.
Light integration is described in Light Integration.
System partitioning is presented in System Partitioning.
Tight integration cannot be described in general, because there are too many operating systems on the market with too different characteristics. Tight integration can be performed with, but is not available in the Cmicro product.
The BodyBuilder is a stand-alone software tool which eases the scaling of the Cmicro Kernel, Library, Tester and so on.
The result of a BodyBuilder session is an automatically generated file ml_mcf.h
(Manual ConFiguration) for target configuration and an options file sdtmt.opt
for host configuration. Furthermore the BodyBuilder generates a template file called env.c
which represents the environment of the SDL system (See The Generated Environment).
To prevent misunderstandings, it is still possible to do the Cmicro scalings in the old fashioned way by using a handwritten file ml_mcf.h
. And it is still recommended that the user should know the meaning of the different flags. (See Compilation Flags).
The user is asked to read the following subsections to get an idea of the BodyBuilder's benefits.
Several files have to be read from the user's current working directory.
These are:
<systemname>.sym
)<systemname>.ifc
)sdl_cfg.h
)ml_mcf.h
) if already existssdtmt.opt
) env.c
(if already exists) which represents the environment of the SDL system. The BodyBuilder will prompt during start-up if a needed file is missing.
On UNIX, the BodyBuilder simply needs to be started from the working (project) directory.
~/cmicro_project
).cd ~/cmicro_project
bodybuilder
Note: If the command |
In Windows, it is recommended to create a new shortcut to the BodyBuilder in the Window's Start Menu or on the desktop. The shortcut must contain the project directory in its properties (Entry `Start in:') and should start the executable bodbuild.exe
.
Note: The user should ask his system administrator for adding new links to the Start menu or the desktop. |
|
In Windows, start the BodyBuilder by double-clicking the BodyBuilder quick-button. |
The BodyBuilder is started and the definition files bodyconf.bin
and bodyconf.def
are read in from the directory where the BodyBuilder itself is stored in (see The BodyBuilder's Definition Files).
The directory in which the files ml_mcf.h
, sdl_cfg.h
and sdtmt.opt
for the project's settings can be found, is the one from which the BodyBuilder (on UNIX) has been started or accordingly the one the shortcut points to (in Windows).
When all the files found are checked for consistency the BodyBuilder comes up with a check dialog. This dialog is the same which can be invoked from the Tools Menu.
The main window of the BodyBuilder contains a start-up picture which shows the different parts of the Cmicro Package. These parts, which can be configured, are:
Figure 551 : The BodyBuilder's main window
|
Click a box in the main window graphic to open the configuration window. In the configuration window, the selected part can be configured.
Figure 552 shows the configuration window for the target configuration directly after call.
Figure 552 : The Configuration window
|
Double-click items in the left list to expand and collapse the sub items of the target configuration into different groups.
Select an item in the left list to see a description of it in the right part of the window.
Click the wanted group to open the according configuration field in the right part of the window. Figure 553 shows the configuration field for the group "Signal priorities" in the sub item "Cmicro Kernel".
Figure 553 : Configuration field of group Signal priorities
|
In the configuration field, it is possible to select/deselect the items with a small box in front of the text. Items containing values have an input field behind the text instead. These input fields can get numeric or alphanumeric values (but not hexadecimal values) according to the current item. The default values are displayed in the input fields and if a numeric value is expected this value is checked for the correct range.
When an item is selected or an input field is active, the status bar displays a short explanation and the name of the flag used in the C code is shown as the "Macro Name". You can also click the Help button to get more information.
There are a lot of interdependencies between the different flags of the Cmicro Package (see Compilation Flags). This means if a flag is selected by the user probably some of the other flags have also to be set or reset. Sometimes the user cannot select a flag because another flag needs to be previously set or reset.
In any case of an interdependency the user will be informed about the dependence by an info box. Which kind of dependency is recognized and which flag is involved is given in this info box.
Figure 554 : Dependency info box
|
The user now can get help about the selected flag. If no help is needed or the help is already recognized, the setting can be recognized or canceled.
In any case the user can be sure that all dependencies of the Cmicro Package are recognized and that the generated configuration file ml_mcf.h
is consistent.
However, the configuration file ml_mcf.h
can only represent the user's settings. Therefore the user is responsible for selecting all the necessary flags for his SDL system, i.e. the BodyBuilder does not know everything about the SDL system and cannot relieve the user's responsibility.
To get an idea of the user's SDL system, the BodyBuilder reads in the generated file sdl_cfg.h
(from the current work directory). Much of the information about the current SDL system are given here (see Automatic Scaling Included in Cmicro) but there is no information about signal or process priorities for example. So only the user knows about it and has to select it.
All the target configurations must be done here. The user must know that there are dependencies between the different sub items, e.g. "Use signal priorities" in "Cmicro Kernel/Signal priorities" resets "Simple signal output" in "Cmicro Library/Signals".
If for example the user selects the Cmicro Tester there have to be some other settings (like the use of error checks) made which are necessary when using the Cmicro Tester in any configuration.
After removing the Cmicro Tester for target versions that are to be distributed this error checks can be removed but will not be automatically removed.
The communications link configuration is necessary only if the Cmicro Tester is used.
The communications link device and its parameters can be selected here. The configuration made here have an influence on the template file dl.c
which represents the data link layer. As the Cmicro Package is delivered with an V.24 interface this field is for the V.24 configuration only.
It is possible for the user to extend the communications link configuration by modifying the file bodyconf.def
. See The BodyBuilder's Definition Files to get further information.
In this section the user has to select his target C compiler.
Some C code words, e.g. const
, are handled in different ways by different C compilers. Besides some header files to be included have different names. By selecting the correct compiler, the necessary settings will be made automatically.
The Cmicro Package is build to work with any ANSI C compiler available. As the tests can not be performed on any compiler, the compilers listed here have been tested and got there own compiler section within the file ml_typ.h
. (See List of Available C Compilers in ml_typ.h).
The user is free to add any new compiler to this section by modifying the file bodyconf.def
. See The BodyBuilder's Definition Files to get further information. A new compiler section has to be added in ml_typ.h
as well. See Adaptation to Compilers.
The Cmicro Tester's host executable for use on Microsoft Windows or UNIX systems has to be configured via the options file sdtmt.opt
. All settings concerning the target and the communications link have to be made within sdtmt.opt
(see Preparing the Host to Target Communication).
The user also can use the BodyBuilder to generate sdtmt.opt
.
This section describes the menu bar of the Cmicro BodyBuilder Main window and all the available menu choices.
The menu bar contains the following menus:
The File menu contains the following menu choices:
The environment template file env.c
is re-generated. Please see The Generated Environment.
A directory selector box is opened and the user can enter the path to his project directory. The BodyBuilder will read the files ml_mcf.h
, sdl_cfg.h
and sdtmt.opt
from this directory.
Hint: It is recommended to start the BodyBuilder directly from the working (project) directory. In Windows this means to set the correct properties in the shortcut which starts the BodyBuilder. |
The Configure menu delivers the same functionality as clicking on the graphic symbols on the BodyBuilder's start-up picture. The menu contains the following menu choices:
The Tools menu contains the following menu choices:
Figure 555 : The BodyBuilder's check dialog
|
The BodyBuilder has its own log window. This window is used to list all the found problems and all the actions done.
Figure 556 : The BodyBuilder's log window
|
The File menu contains the following menu choices:
The menu choices are described in File Menu
In previous versions of the Cmicro Package there were four functions called xInitEnv(), xInEnv(), xOutEnv() and xCloseEnv() given as template functions. All functions were designed to be filled up completely by the user.
Now the BodyBuilder generates the environment functions xInitEnv(), xInEnv(), xOutEnv() and xCloseEnv() and places all the signals to and from the environment into the correct place.
The user simply has to add the C code which performs the appropriate actions on the environment for all the signals going to the environment. On the other hand he must insert the C code which detects on environment side if a signals has to be sent into the SDL system.
Note: There is no way around, the user is allowed to insert his C code between the comments |
When the BodyBuilder is started and the file env.c
already exists all the C code between /* BEGIN User Code */
and
/* END User Code */
is read in and re-inserted when env.c
is generated anew. This makes it possible to implement new signals on the SDL Editor level and have an updated environment function once the BodyBuilder is used.
There are two files the BodyBuilder needs to get all dependencies of Cmicro Package's configuration possibilities.
bodyconf.bin
This file contains all the flags (and their interdependencies) of the Cmicro Kernel, Tester and Library. It should never be touched to protect all the dependencies.bodyconf.def
This file is written in ASCII format and contains all flags for the communications link implementation and the supported compilers in the delivered version of the Cmicro Package.The file bodyconf.def
can be (and should be) modified by the user, e.g. if the user has added his own communications link or if he has added a new compiler section in ml_typ.h
(see Adaptation to Compilers).
The example below shows the structure of one entry.
bodyconf.def
Entries 1 BEGIN 2 XMK_USE_V24 3 V24 communication 4 COMMLINK 5 V24 interface 6 AUTOSET 7 XMK_V24_BAUD 8 XMK_V24_DEVICE 9 END 10 END
Line 1 and 10 mark the start and the end of one entry.
Line 2 gives the name of the flag as it appears in the generated file ml_mcf.h
. According to this example line 3 is the marker which appears in the BodyBuilder's graphical user interface.
Line 4 specifies the main group this entry belongs to. In bodyconf.def
there are only two possible entries called COMMLINK
and COMPILER
, as this file is for the communications link and compiler selection only.
Line 5 gives the subgroup of the entry. This subgroup can be anything the user likes. In the delivered version there are only the subgroups V24 interface
and Emulator
. However, the user can define his own communications link CAN Bus
for example.
The lines 6 and 9 belong together and between these lines there are listed all flags which have to be set when the flag on line 2 is set. The amount of flags (lines 7 and 8 in the example) is free. In the same way as AUTOSET
in line 6 there can also be the entries RESET
or DEPEND.
RESET
means the following flags will be reset if this flag is defined and DEPEND
means this flag can only be set if the following flags (lines 7 and 8) are already defined.
Not given in the example above is the section VALUE,
(like AUTOSET
finished by an END
) which assign a value to the flag. This section can include 3 lines of information. The first gives the default value. And, if the value is numeric, the second line gives the lowest and the third one the highest value. The user is asked to have a look into bodyconf.def
.
Also not given in the example above is the section VALUE_LIST
(finished by an END
) which assign a value to the flag with a list of allowed values given. The first value given is the default value, the following values (with not upper limit) are giving the list of allowed values. The default value must be given in the list again. The user is asked to have a look into bodyconf.def
.
Compilation flags are used to decide the properties of the Cmicro Library and the generated C code. Both in the Cmicro Library and in the generated code #ifdef's are used to include or exclude parts of the code.
The switches used can be grouped:
The first two groups are discussed in Adaptation to Compilers. The remaining two groups are discussed under Manual Scaling and Automatic Scaling Included in Cmicro.
Flag naming conventions:
XMK_ADD_:
include optional partsXMK_USED_:
automatically include parts of the Cmicro Code Generator. Note: Do not switch off by hand.XMK_USE_
: manual scalingsXMK_MAX
_: manual scalingsUse the default settings of these flags in order to reduce potential problems.
Users are able to scale some features of the Cmicro Library and the Cmicro Kernel in order to optimize the generated code. All the flags discussed in this section are used throughout the complete SDL system, therefore it is not possible to define flags for processes separately.
Note: The whole SDL system must always be generated. |
The manual scalings have to be done in the file ml_mcf.h
. They are divided into the following groups:
In the following subsections, the way to configure the Cmicro Package by hand and all the available flags are described.
The user is asked to use the configuration tool named BodyBuilder to configure the Cmicro Package. For further information see The BodyBuilder.
To configure the Cmicro Package by hand, the user has to modify the file ml_mcf.h
.
To use a Cmicro Package feature just define it in ml_mcf.h
like
#define FLAG_NAME_AS_DESCRIBED_BELOW
Sometimes a flag just carries a value. In this case the user has to modify the value in ml_mcf.h
#define FLAG_CARRYING_VALUE VALUE
memsets
all variables of the SDL processes to 0 before the process is created. This is useful to spare some ROM memory but has the disadvantage of a longer process creation phase. The ROM used by the yDef_SDL_*
functions can be spared in this case where the initialization with 0 is appropriate.
Initial setting |
set |
memset
s all variables of SDL procedures to 0 before the procedure is started. This is useful to spare some ROM memory but has the disadvantage of a longer procedure start phase.
Initial setting |
set |
Automatic set |
xmk_T_SIGNAL
).
Initial setting |
unset |
xmk_T_MESS_LENGTH
in ml_typ.h
for further information.
Initial setting |
unset |
Initial setting |
unset |
Normally, the Cmicro Kernel is configured so that the simple scheduling policy is used, i.e. transitions of SDL processes are non interruptible.
Note: The Cmicro preemptive kernel is only available if an according license is available. |
Initial setting |
unset |
Automatic set |
|
Reset |
Initial value |
1 |
Depend on |
A run-time error occurs if this definition is wrong. If the error checks are enabled, a check is made by the Cmicro Kernel and the C function |
MAX_PRIO_LEVELS
-1).
Initial value |
0 |
Depend on |
XMK_USE_SDL_SYSTEM_STOP
means that the C function main
returns correctly with exit(...). To avoid this overhead in the Cmicro Kernel, the user should not define the above flag.
Default setting |
unset |
sdl_cfg.h
are overwritten in ml_typ.h
.
Initial setting |
unset |
Initial setting |
unset |
WatchdogTrigger
before executing a transition. This function is present as a template in the Cmicro Library source files. Using WatchdogTrigger is only of value when non preemptive scheduling is selected.
Initial setting |
unset |
mk_main.c
is not used. This allows users to implement their own C main() function. A template is also given within the file bare_ex.c
. The user should define this flag whenever he likes to implement additional features to the main function like the use of the arguments argc and argv.
Initial setting |
unset |
Initial setting |
unset |
Reset |
XMK_SWITCH_BANK
.
Initial setting |
unset |
In the standard configuration of the Cmicro Kernel no signal priorities are used. So each signal sent is inserted at the end of the signal queue.
xmk_SendSimple
has to be switched of.
Initial setting |
unset |
Automatic set |
|
Reset |
Initial value |
100 |
Depend on |
XMK_USE_SIGNAL_PRIORITIES
is defined). Like the signal default priority xDefaultPrioSignal, a value between 0 and 250 can be entered here.
Initial value |
1 |
Depend on |
Initial setting |
set |
xRouteSignal()
which is given as a template in mk_user.c
. Each signal type is then mapped to a unique receiver. It is recommended to define this flag in small systems where unique receivers exist for each signal type. It is important to note that in the case of dynamically created processes an internal create signal is used. If there are any (x, N) where N > 1, declarations in the system, the create signal cannot contain the receiver pid. The receiver pid is necessary for correct creation of processes. Never leave it out when using dynamic process creation.
Initial setting |
set |
ml_typ.h
for the typedef xmk_T_SIGNAL
).
Initial value |
4 |
xmk_SendSimple()
defined in the Cmicro Kernel. If the SDL system contains several signals without parameters and priorities, it is useful to set this flag in order to select the more optimal output C function, xmk_SendSimple(),
in the Cmicro Kernel.
Initial setting |
set |
Reset |
Initial setting |
unset |
Initial setting |
set |
Reset |
Initial setting |
unset |
Reset |
ErrorHandler
, i.e. when the queue is full and another signal is to be inserted then the ErrorHandler
function is called.
Initial value |
20 |
If there are timers used within the SDL system, the timers have to be scaled.
Initial setting |
unset |
Initial value |
100 |
Initial value |
100 |
XMK_MAX_TIMER_INST
in the file sdl_cfg.h
. Timer instances are, usually, implemented as a C array with Cmicro. If the XMK_USE_GENERATED_AMOUNT_TIMER
flag is set, then the timer array is dimensioned with the evaluated amount (XMK_MAX_TIMER_INST
).XMK_MAX_TIMER_INST
can be used to predefine one timer instance of a timer declaration. If there are then more timers to be instantiated, dynamic memory allocation must take place. This cannot be evaluated by the code generator.
Initial value |
set |
XMK_USE_GENERATED_AMOUNT_TIMER.
XMK_USE_GENERATED_AMOUNT_TIMER
is not set. The flag XMK_MAX_TIMER_USER
is unset if XMK_USE_GENERATED_AMOUNT_TIMER
is set.
Initial value |
unset |
XMK_MAX_TIMER_USER
is set, the value XMK_MAX_TIMER_USER_VALUE
becomes meaningful. With this value, the user may specify how many timer instances should be predefined during compilation time. The predefined timer instances offer the advantage that no dynamic memory allocation is to be done for them. If the predefined amount of timer instances is exceeded, then dynamic memory allocation will occur. As a result, it is up to the user how he balances static and dynamic memory for timer instances by changing this value.
Initial value |
20 |
Initial setting |
set |
Reset |
XMK_USE_MAX_ERR_CHECK
this flag only includes a basic set of error checks.
Initial setting |
unset |
Reset |
Initial setting |
unset |
Reset by |
ml_mon.c
can be included to have access to functions like xxmonhexasc() etc.
Initial setting |
unset |
printf
C function calls are compiled giving users more information about the internal work of the system. The printf can be switched on separately for Cmicro Kernel, Cmicro Tester and SDL application. At a lower level, it can be switched on separately for each C module. Look at the defines in ml_typ.h
, which are all named as XMK_ADD_PRINTF_*
.stdio
implemented on the target. For correct compilation, the user must also set XMK_ADD_STDIO. If the user wishes to implement user specific printf functionality then this flag need not be set.
Initial setting |
unset |
Automatic set |
Initial setting |
set |
Reset |
XMK_WARN_ACTION_HANGUP
also.
Initial setting |
unset |
Reset |
XMK_WARN_USER_FUNCTION
. Please see XMK_WARN_ACTION_HANGUP
also.
Initial setting |
unset |
Reset |
XMK_WARN_ACTION_USER
is defined, then the user must define the name of a C function with this macro. Please see XMK_WARN_ACTION_HANGUP
also.
Initial setting |
user_function() |
Initial setting |
set |
Reset |
XMK_ERR_ACTION_HANGUP
also.
Initial setting |
unset |
Reset |
XMK_ERR_USER_FUNCTION
. Please see XMK_ERR_ACTION_HANGUP
also.
Initial setting |
unset |
Reset |
XMK_ERR_ACTION_USER
is defined, then the user must define the name of a C function with this macro. Please see XMK_ERR_ACTION_HANGUP
also.
Initial setting |
user_function() |
XMK_TRANS_TIME
flag, the ErrorHandler()
is called. The flag is only available when using a non preemptive Cmicro Kernel. No additional hardware is necessary as the evaluation is based on the SDL time value NOW
which is provided by the same hardware source as for the system clock.
Initial setting |
unset |
Automatic set |
Initial value |
20 |
Depend on |
Initial setting |
unset |
Automatic set |
|
Reset when unset |
xmk_MicroTesterInit()
in the module mk_main.c
), the target can wait for the host's run-time configuration. If this is not needed, the XMK_WAIT_ON_HOST
flag has to be undefined.
Initial setting |
unset |
Depend on |
int xmk_max_q_cnt,representing queue-dimensioning, and
int xmk_act_q_cnt,representing the maximum traffic load of the queue at any time during the execution.
Initial setting |
unset |
Depend on |
Initial setting |
unset |
Depend on |
Initial setting |
unset |
Depend on |
Initial setting |
unset |
Depend on |
Initial setting |
unset |
Depend on |
|
Reset when unset |
Initial setting |
unset |
Depend on |
dl.c
for further information.
Initial setting |
unset |
Depend on |
Initial setting |
unset |
Depend on |
main()
in module bare_ex.c
.
Initial setting |
unset |
Depend on |
NOW
, if an SDL signal is inserted into the queue.
Initial setting |
unset |
Depend on |
|
Reset when unset |
XMK_MAX_PRINT_STRING
.
Initial value |
40 |
Initial value |
20 |
Initial value |
100 |
ml_buf.c
). The recommended amount of entries given here depends of the used communications link. I.e. if using a slow communications link like V.24 this amount should be increased.
Initial value |
20 |
ml_buf.c
). The size of one entry depends on the SDL system. As a rule over the thumb a value of 12 + maximum signal parameter size must be given here.
Initial value |
100 |
Note: The Cmicro Tester's Record and Play functions are only available if a Cmicro Recorder license is available. |
Initial setting |
unset |
Depend on |
|
Reset when unset |
Initial setting |
unset |
Automatic set |
|
Depend on |
Initial setting |
set |
Reset by |
The Cmicro Recorder is not able to handle SDL charstrings within signal parameters. |
Initial setting |
set |
Reset by |
Initial value |
50 |
ml_typ.h
( Adaptation to Compilers)
Initial setting |
set |
Initial setting |
set |
Initial setting |
set |
Depend on |
Initial setting |
set |
Depend on |
Initial setting |
set |
Depend on |
Initial setting |
set |
Initial setting |
set |
Initial setting |
set |
Initial setting |
set |
Note: This flag should be used for testing purposes but uses lots of code size within the target. |
Initial setting |
set |
Initial setting |
set |
Initial setting |
set |
Initial setting |
set |
Initial setting |
unset |
ml_mem
module (xmk_Malloc()
, xmk_Calloc()
and xmk_Free()
). This is necessary if the compiler in use has no malloc
/free
or if the user wishes to modify the standard behavior of these functions, i.e. using a best fit, instead of first fit searching algorithm. The user should refer to Dynamic Memory Allocation Functions -- Cmicro also.
Initial setting |
unset |
Reset when unset |
Initial setting |
unset |
xmk_Memshrink()
function of the mem module can be used. This function delivers the opportunity to free the unused space of a memory block that was requested previously with xmk_Malloc()
or xmk_Calloc()
.
Initial setting |
unset |
Depend on |
Initial setting |
unset |
Initial setting |
unset |
Initial value |
8 |
Depend on |
Initial value |
64 |
Depend on |
xmk_Malloc()
, xmk_Calloc()
and xmk_Free()
) are used, the buffer that is used for dynamic memory allocation is to be initialized with xmk_MemInit()
. The size of the buffer can be given here.
Initial value |
1024 |
Depend on |
Initial setting |
unset |
Initial setting |
unset |
Initial setting |
unset |
Initial setting |
unset |
mk_user
module.
Initial setting |
set |
mk_user
module or which can be generated with the BodyBuilder.
Initial setting |
set |
Initial setting |
set |
Initial setting |
set |
int argc
and char **argv
are declared in the template C function main
in order to give parameters to the implementation. The way these parameters are used depends on the user. (See main
function in bare_ex)
Initial setting |
unset |
Automatic set |
XNOMAIN |
stdio
is available and required on the target system. XMK_ADD_STDIO
without setting XMK_ADD_PRINTF
allows the user to exclude the default printfs of the Cmicro Library and instead implement user defined printfs.
Initial setting |
unset |
Reset when unset |
The flags described in this section are automatically generated into the file sdl_cfg.h
by the Cmicro Code Generator. The purpose is to exclude parts of the C code in order to reduce the generated code. Features or functions which are not required in the SDL description produce no (or only a small) overhead in the generated code.
If the user does not wish to employ automatic scaling facilities, for example if test and debugging proves too difficult, then simply define the flags XMK_USE_NO_AUTO_SCALING.
All the flags discussed in this section are used on the whole SDL system i.e. it is not possible to define flags for processes separately.
The BodyBuilder will use these flags, too, to optimize and ease the manual scaling of Cmicro.
Note: It is possible to implement a user defined timer model by undefining these flags and defining some other macros. |
Note: It is not recommended in each case (because it is not SDL conform), but is possible to send parameters via global parameters by using C code in SDL. |
XMK_USE_PID_ADDRESSING
depends on the above flags.Some resources of the Cmicro Library are automatically dimensioned. These are described in the following subsections.
In this section the steps are explained that must be carried out in order to deal with a new C compiler which is not yet in the list of available compilers.
The following parts may be changed:
ml_typ.h
, there is a section defining the properties of different compilers. If required add a new compiler here by defining a new section:#ifdef <compilername> #endif /* ... <compilername> */
mk_stim.c
, there are template functions as templates which have to be modified to adapt another hardware/compiler to the SDL system time (Now).mk_cpu.c
, there are templates for functions which represent hardware access. Those are required if the preemptive Cmicro Kernel is used.bodyconf.def
needs the introduction of a new compiler Please view The BodyBuilder's Definition Files to get information about this.C compilers are to be selected by the user by choosing from an available list with the help of the BodyBuilder.
If the C compiler from the user is not in the available list, the steps described in the following subsection are to be carried out.
The BodyBuilder will generate a C define into the ml_mcf.h
file. When compiling Cmicro sources, the right C compiler section in ml_typ.h
is selected by using a #ifdef <compilername>
construct. The following <compilername>
defines are currently defined in ml_typ.h
:
These are the compilers that have been used to compile and link generated code and the Cmicro Library. To introduce a new compiler, a new section in ml_typ.h
should be introduced in which the properties of the compiler are defined.
The remaining part of the code of the Cmicro Library should be compilable without performing any modifications. If there are problems with adapting a new compiler or hardware please contact Cmicro technical support.
The list of compilers will of course be extended when the necessary information on how to handle each particular compiler is obtained.
The user may however decide to define his own C compiler. This is explained in the following subsection.
With the help of the BodyBuilder the user may choose from the list of available C compilers. The user may decide to define his own C compiler by following the steps that are documented within this subsection.
There are two possible alternatives to add a user defined C compiler.
The first alternative to add a new user defined C compiler, is to add that compiler to a user's project. This can be achieved with the BodyBuilder.
The advantage of this alternative is that these changes are not stored within the SDT installation, but within the user's working directory (which is the target directory that was chosen when the BodyBuilder was started).
After the C compiler is added, the user should continue with the descriptions that follow in the subsection Do the C Compiler Adaptations.
After installation of a new SDT release, the contents of the files that are stored with the BodyBuilder are not guaranteed to remain. |
It might be a better idea to insert the macro definition for a new user defined C Compiler within the SDT installation. This requires of course that the file's access rights and permissions are set up correctly.
The advantage of this alternative is that the C compiler being added is visible to all project members working with the SDT installation.
The steps are:
After installation of a new SDT release, the contents of the files that are stored with the BodyBuilder are not guaranteed to remain. |
user_cc.h
. If a C compiler is selected, which is not in the list of available C compilers in the Cmicro product, the user_cc.h
is included automatically. -I <pathname>
" option which must point to the path in which user_cc.h
is stored. user_cc.h
file like it is described in the following.The following definitions are to be made by the user when a new user_cc.h
file is to be created.
The file should look like:
#ifdef <compilername> /* user's explanations and comments */ ...user's definitions like described below... #endif /* ... <compilername> */
The things that are to be defined by the user are:
Yes |
#undef XNOPROTO #define XPP(x) x #define PROTO(x) x |
No |
#define XNOPROTO #define XPP(x) #define PROTO(x) |
char |
#define xmk_OPT_INT char |
integer |
#define xmk_OPT_INT integer |
Yes |
#undef X_REGISTER #define X_REGISTER >register< |
No |
/* Nothing to do for X_REGISTER */ |
>register<
is the compiler specific command to store variables in registers.#define xptrint unsigned long
This setting should work for the very most compilers In a few cases it is necessary to define xptrint
as unsigned int
.#define xint32 long
This setting should work for the very most compilers. In a few cases it is necessary to define xint32
as int
. const
in the correct way?
Yes |
#define XCONST const |
No |
#undef XCONST |
const
. Compilers may generate false object code, if using const
.
Yes |
#define XMK_UNIX |
No |
|
Yes |
#define XMK_WINDOWS |
No |
|
#undef XMK_END_CRITICAL_PATH #define XMK_END_CRITICAL_PATH \ if (xmk_InterruptsDisabled) \ {\ xmk_InterruptsDisabled--;\ if (!xmk_InterruptsDisabled) \ { ENABLE; }} #undef XMK_BEGIN_CRITICAL_PATH #define XMK_BEGIN_CRITICAL_PATH \ DISABLE;\ xmk_InterruptsDisabled++;
ENABLE
and DISABLE
are the compiler specific command to allow/prevent interrupts and must be filled.#ifdef XMK_ADD_STDIO #include <stdio.h> #endif
#define "io51.h"is used. For the GNU80166:
#include <string.h> #include <stdlib.h> #include <stdarg.h> #include <c166.h>is used.
#ifdef XMK_USE_SDL_MEM #include "ml_mem.h" #else #include "string.h" #endif /* XMK_USE_SDL_MEM */It must be checked if
malloc(), free(), calloc()
etc. are really prototyped in string.h, on other compilers it might be stdlib.h. Cmicro always calls xAlloc()
and xFree()
which are given as examples in the mk_cpu.c
file below the template directory. For more information on dynamic memory allocation please view the subsection Dynamic Memory Allocation.The following functions exist in the module mk_stim.c
:
void xmk_InitSystime(void)
Initialize the hardware registers to support the system timevoid xmk_DeinitSystime(void)
Give up to use the system time. This normally cannot happen, but in some applications, where the SDL system is stopped and restarted again during run-time, it may prove useful.void xmk_SetTime(xmk_T_TIME)
This function sets the system-time to the given value. Called by Cmicro Kernel in the case when an overrun in the time value is detected.xmk_T_TIME xmk_NOW(void)
This is the most important C function to handle SDL system-time. This function returns the absolute time, which is by default defined as a long
value (xmk_T_TIME
).Usually, the above functions are conditionally compiled. To make the functions available in the target system, at least one timer in SDL must be declared. The functions are not included if there is no timer declared but duration, time or now is used in SDL. This will lead to compilation errors.
To make timers in SDL operable, absolute time must be implemented. This can be reached by using a hardware free running counter or by using a timer interrupt service routine, which clocks a global variable containing the absolute time.
This section deals with functions that must be adapted by the user in order to connect the SDL system to the environment i.e. connection to target hardware, and the environment.
The user may decide to implement his own main() fu
nction body when it comes to target application in a bare integration. No C function main()
is generated by the Cmicro Code Generator. A default main()
function is however included in the Cmicro Kernel.
The implementation of a first main
function looks like this:
main () { xmk_InitQueue(); xmk_InitSDL (); xmk_RunSDL (0xff); }
Of course this example does nothing in order to start the Cmicro Tester. The only possible way to get a very simple trace output is to define:
#define XMK_ADD_PRINTF
in ml_mcf.h
with the help of the BodyBuilder. This will include calls to the C function xmk_printf()
at several places in the generated C code and the Cmicro Library. The xmk_printf()
function is available as an example in the file mk_cpu.c
.
The user can use the main()
functions delivered with the Cmicro Kernel to have full access to all Cmicro features, as follows:
mk_main.c
It is necessary to undefine the flag XNOMAINin ml_mcf.h
(see XNOMAIN) so this main()
is used. It is recommended not to do any modifications within this function!bare_ex.c
It is necessary to define the flag XNOMAIN in ml_mcf.h
. Please remember: bare_ex.c
is a template and should be copied into the current project directory. This template file can be found within the installation, below the directory cmicro/template
.There is no extra handling for hardware drivers, hardware functions and interrupt service routines. It is necessary to implement an interface in the user's application. Hardware drivers, hardware functions and interrupt service routines are seen from the SDL system as the environment. The user has to implement the interface between the SDL system and the environment as it is described in the following subsections.
As with every real time application the Cmicro Library has to deal with critical paths.
|
These are well defined in the source code using two macros namely XMK_BEGIN_CRITICAL_PATH
and XMK_END_CRITICAL_PATH
(see file ml_typ.h
/compilersections).
The macros are expanded to compiler specific calls which disable/enables interrupts. The calls are counted using an internal variable, thus after having called XMK_BEGIN_CRITICAL_PATH
n times XMK_END_CRITICAL_PATH
has also to be called n times, to enable the interrupts again.
In the Cmicro Library these macros are used to disable/enable interrupts only. The application should take care not to handle interrupts without using these macros or at least evaluating the internal counter.
There is one C function called xInitEnv()
available as a template in the generated file env.c
(see The Generated Environment). The user should fill this module out appropriately, thus implementing connection to the environment (drivers, interrupt service routines and so on).
There are two possibilities to send signals into the SDL system. In all cases, the user has to specify an SDL input symbol in the process which has to consume the signal. The possibilities are:
xInEnv()
, which is called by the Cmicro Kernel after each transition. XMK_SEND_ENV()
function. This function directly operates on the SDL queue.
In/Out: -no- Return: -no-
In the case when no interrupt service routine is available to handle an external event, the Cmicro Kernel can poll external events. The user must use the C function xInEnv()
in the file env.c
generated by the BodyBuilder. Please view The Generated Environment.
For example, a hardware register can then be checked in order to establish if its value has changed since the last call.
If an external signal is detected, then one of the xmk_Send*()
functions is to be called thus enabling the signal to be put into the SDL queue.
xInEnv()
Assume, a hardware register where the value 0 is the start-value and where any other value means: data received. Two signals, namely REGISTER_TO_HIGH
, and REGISTER_TO_LOW
are to be defined in the SDL system, with a process receiving these. Then the user supplied C code should look like this (the <p>
below stands for the automatically generated prefix, see the file sdl_cfg.h
):
void xInEnv (void) { XMK_SEND_TMP_VARS static state = 0; /* state, to detect changes in the */ /* hardwareregister */ /* BEGIN User Code */ if ((state==0) && (hw_register != 0)) /* END User Code */ { XMK_SEND_ENV (REGISTER_TO_HIGH, xDefaultPrioSignal, 0, NULL, /* BEGIN User Code */ GLOBALPID(XPTID_<p>_ReceiverName,0)); state = 1; /* END User Code */ return; } /* BEGIN User Code */ if ((state==1) && (hw_register == 0)) /* END User Code */ { XMK_SEND_ENV (REGISTER_TO_LOW, xDefaultPrioSignal, 0, NULL, /* BEGIN User Code */ GLOBALPID(XPTID_<p>_ReceiverName,0)); state = 0; /* END User Code */ return; } return; } /* END OF SAMPLE */
In/Out: xPID Env_ID xmk_T_SIGNAL sig #ifdef XMK_USE_SIGNAL_PRIORITIES xmk_T_PRIO prio #endif #ifdef XMK_USED_SIGNAL_WITH_PARAMS xmk_T_MESS_LENGTH data_len, void xmk_RAM_ptr p_data #endif #ifdef XMK_USE_RECEIVER_PID_IN_SIGNAL xPID Receiver #endif Return: -no-
It is possible to send signals directly into the SDL system by calling the C function XMK_SEND_ENV()
, no matter whether preemption is used or not. No conflict occurs, if an interrupt service routine uses a XMK_SEND_ENV()
function parallel to the C function xInEnv()
.
This function is to be called when a signal is to be sent into the SDL system, e.g. within the users xOutEnv
function. It must be called with one more parameter than the xmk_Send
function, which is the first parameter Env_ID
. This parameter must be set to ENV
by the user.
The macro internally uses some variables which are to be declared before the macro can be used. For example in the xOutEnv function the XMK_SEND_TMP_VARS
macro must be introduced for declaring these variables.
The function is implemented as a macro in C.
Use the template in the previous subsection to see details how to use the XMK_SEND_ENV()
functions.
There are several possibilities to send signals to the environment:
#EXTSIG
directive in the SDL output.#ALT
directive in the SDL output.Alternative 1 is the most SDL like alternative because it does not use non SDL constructs, like directives. This alternative should be selected, where possible because it makes the diagrams more SDL like and MSCs more readable.
Alternative 2 and 3 are probably the alternatives with higher performance.
Alternative 1 is described below. Alternative 2 and 3 are already well described in The Cmicro Code Generator.
In/Out: xmk_T_SIGNAL xmk_TmpSignalID #ifdef XMK_USE_SIGNAL_PRIORITIES xmk_T_PRIO xmk_TmpPrio #endif #ifdef XMK_USED_SIGNAL_WITH_PARAMS xmk_T_MESS_LENGTH xmk_TmpDataLength, void xmk_RAM_ptr xmk_TmpDataPtr #endif #ifdef XMK_USE_RECEIVER_PID_IN_SIGNAL xPID xmk_TmpReceiverPID #endif Return: xmk_OPT_INT
The function xOutEnv()
exists as a template in the generated module env.c
. Please view The Generated Environment.
Each time an SDL output occurs, the generated C code calls the C function xmk_Send
or xmk_SendSimple
. After performing some checks, and if the signal is to be sent to the environment, the C function xOutEnv()
is called with all the parameters necessary to represent the signal. The parameters are explained in the following.
With the parameter xmk_TmpSignalID
, the signal ID is to be specified.
With the xmk_TmpPrio
parameter, the signal's priority is to be specified (if conditionally compiled). If the XMK_USE_SIGNAL_PRIORITIES is not defined, the signal priorities which are specified with #PRIO in the diagrams is just ignored. The use of signal priorities is not recommended because this violates SDL. A few bytes can be spared if signal priority is not used. See also XMK_USE_SIGNAL_PRIORITIES.
With the parameter xmk_TmpDataLength
, the number of bytes of signal parameters is to be specified. The number of bytes is evaluated by using a sizeof (C struct)
construct. If the signal carries no parameters, this value is set to 0.
With the xmk_TmpDataPtr
parameter, a pointer to the memory area containing the parameter bytes of the signal is given. The memory area is not treated as dynamically allocated within this function. Because the function copies the parameter bytes, the caller may use any temporary memory (for example memory allocated from the C stack by declaring a C variable). This parameter should be set to NULL
if no parameter bytes are to be transferred (if conditionally compiled).
The parameters xmk_TmpDataLength
and xmk_TmpDataPtr
are compiled conditionally. The XMK_USED_SIGNAL_WITH_PARAMS is automatically generated into the sdl_cfg.h
file, from the Cmicro Code Generator. For tiny systems, if there are no SDL signals with parameters specified, this is undefined. It will reduce the amount of information which is to be transferred for each signal, with a few bytes. See also XMK_USED_SIGNAL_WITH_PARAMS.
With the last parameter xmk_TmpReceiverPID
, the PID of the receiving process is to be specified (if conditionally compiled). The parameters xmk_TmpDataLength
and xmk_TmpDataPtr
are compiled conditionally, see also XMK_USE_RECEIVER_PID_IN_SIGNAL.
If XMK_USE_RECEIVER_PID_IN_SIGNAL is not defined, the user must implement the C function xRouteSignal
which is responsible to derive the receiver from the signal ID in that case. Using xRouteSignal
is recommended only if the last few bytes must be spared for transferring of signals.
The sender of the signal can be retrieved by the global variable xRunPID
of type xPID
. Users should remember, that in a system with only (x,1) process declarations, this pid represents the process type of the sender. In a system in which multiple process instances of the same process type appear, this pid represents the process type plus the process instance of the sender. Probably it is required to make decisions depending on the sender of the signal. The user can evaluate the process type of the sender by using the C expression EPIDTYPE(xRunPID)
, i.e.:
unsigned char ptype; ptype = EPIDTYPE(xRunPID);
Remember also, if it is required to signal to a specific pid in the environment, this requires dynamic signalling where a process in the environment establishes communication to a process in the system or the other way around.
Under normal circumstances it is not necessary to check the receiver in xOutEnv()
as the Cmicro Kernel calls xOutEnv()
only, if the environment is recognized as the signal's receiver.
If the signal to be sent to the environment contains parameters, it is necessary to copy these parameters to the data area of the environment as the signal and its parameters are deleted after signal consumption.
For each signal carrying parameters, there is a typedef struct generated into the <systemname>.ifc
file. Please view Example 462.
The user must ensure that signals which are to be sent to the environment are consumed by the environment. In xOutEnv()
this is done by returning the values XMK_TRUE
or XMK_FALSE
.
XMK_TRUE
The signal has been consumed by the environment.XMK_FALSE
The signal is NOT consumed by the environment.Assume, for example, a process which has to send a signal with parameters to the environment. The code the user has to write into the xOutEnv()
-function, looks as follows:
xOutEnv()
xmk_OPT_INT xOutEnv (xmk_T_SIGNAL xmk_TmpSignalID, xmk_T_PRIO xmk_TmpPrio, xmk_T_MESS_LENGTH xmk_TmpDataLength, void * xmk_TmpDataPtr, xPID xmk_TmpReceiverPID ) { xmk_OPT_INT xmk_TmpResult = XMK_FALSE; switch (xmk_TmpSignalID) { case SDL_Signal1 : { /* BEGIN User Code */ int temp; temp = (yPDef_z4_SDL_Signal1*)xmk_TmpDataPtr->Param1 UserFunction(temp); /* END User Code */ xmk_TmpResult = XMK_TRUE; /* signal is */ /* consumed */ } break ; case SDL_Signal2 : { /* BEGIN User Code */ char g; int k; g = (yPDef_z5_SDL_Signal2*)xmk_TmpDataPtr->Param1; k = (yPDef_z5_SDL_Signal2*)xmk_TmpDataPtr->Param2; UserFunction2( g, k ); /* END User Code */ xmk_TmpResult = XMK_TRUE; /* signal is */ /* consumed */ } break ; default : xmk_TmpResult = XMK_FALSE;/* signal is NOT */ /* consumed */ /* and to be handled */ /* by the Cmicro Kernel */ break ; } return( xmk_TmpResult ); }
The function |
In/Out: -no- Return: -no-
There is one C function called xCloseEnv
() available as a template in the generated C module env.c
(see The Generated Environment).
The user should fill this function out appropriately thus realizing disconnection from the environment (drivers, interrupt service routines and so on). Disconnection can make sense if a reinitialization or a software reset is to be implemented.
The SDL_Halt
function is mapped to xCloseEnv()
in Cmicro.
Included in the Cmicro Kernel, there are some template functions for the implementation of SDL system time. All these functions are contained in the module mk_stim
. The functions xmk_NOW()
or xmk_SetTime()
must be implemented newly if a new method for accessing the hardware system time is to be implemented. In many cases, the standard C library function time()
is available, which is used in most of the C compiler adaptations that are already been made.
It is necessary though to implement a function which makes the variable SystemTime
topical. This will be an interrupt service routine in most cases.
Please view Defining the SDL System Time Functions in mk_stim.c.
In/Out: xmk_T_SIGNAL sig Return: xPID
The user can remove the receiver's xPID from the signal structure by undefining the flag XMK_USE_RECEIVER_PID_IN_SIGNAL. In this case, the function xRouteSignal()
has to be filled as the Cmicro Kernel needs to know which process likes to receive the current signal.
xRouteSignal()
/* ** the <p> below stands for the automatically generated prefix */ xPID xRouteSignal ( xmk_T_SIGNAL sig ) { /* ** Please insert appropriate code here to map ** Signal ID's to Process - Type - ID's ** (XPTID_ProcessName in generated code). ** Keep in mind that this function might be ** called from within a critical path. ** Include <systemname>.ifc to get signal names ** and process' XPTID */ switch (sig) { /* ** S D L T i m e r s ... */ case SDL_Timer1: return (XPTID_<p>_ProcessName_A) break; case SDL_Timer2: return (XPTID_<p>_ProcessName_B) break; case SDL_Timer3: return (XPTID_<p>_ProcessName_A) break; case SDL_TimerN: return (XPTID_<p>_ProcessName_C) break; /* ** O r d i n a r y S D L S i g n a l s ... */ case SDL_Signal1: return (XPTID_<p>_ProcessName_B) break; case SDL_Signal2: return (XPTID_<p>_ProcessName_A) break; case SDL_Signal3: return (XPTID_<p>_ProcessName_A) break; ...... case SDL_SignalN : return (XPTID_<p>_ProcessName_C) break; default: ErrorHandler (ERR_N_NO_RCV); return (xNULLPID) break; } }
Dynamic memory allocation in real life always introduces problems, which are:
Normally, Cmicro tries to prevent any use of dynamic memory allocation, but there are the following exceptions, in which this is impossible:
There are at least two possibilities to implement dynamic memory allocation namely:
When it comes to targeting, the user decides upon the dynamic memory allocation manager. In the following, the both possibilities are explained.
If the C compiler, that the user is using in the target environment, provides dynamic memory allocation functions, it is possible to use these functions. A few steps must be carried out to include the dynamic memory allocation functions of the C compiler or operating system, which are:
#include
. The user should refer to the manuals of the C compiler or operating system. mk_cpu.c
. mk_cpu.c
below the Cmicro template directory must be copied into the user's project directory. Any modifications should be performed on the private copy of mk_cpu.c
. mk_cpu.c
file contains two C functions called xAlloc()
and xFree()
. Within these functions, the user should call the appropriate dynamic memory allocation functions of the C compiler or operating system. Below the Cmicro kernel directory there is a C module ml_mem.c
that implements a dynamic memory allocator. The C module ml_mem.c
can be used for managing memory dynamically for SDL systems, but it is not forbidden to use this module within handwritten C code also.
The module cannot be used if partitioning is to be used. In that case compilation errors will occur. Please refer to Dynamic Memory Allocation for an explanation which parts in SDL are to be dynamically allocated. The module provides C functions for initialization, allocation, de-allocation, and getting some information about the current memory status.
There is only one memory pool. The memory pool is to be declared by the user and initialized with the C function xmk_MemInit
before the memory pool can be used. Allocations may be performed by calling xmk_Malloc()
or xmk_Calloc()
. An allocated block is de-allocated again by calling xmk_Free()
. So far, the principle behavior is the same as the usual malloc(), calloc()
and free()
functions from compilers. But the memory pool can probably be cleaned with a Cmicro specific function. There are additional functions which can be used to query the amount of free or occupied space.
Before the memory management functions of Cmicro can be used, a few adaptations are to be made which are explained in the following.
Some adaptations are to be made by the user, which are necessary to include the right functions, scale buffers and memory management and take care for general adjusting like alignment of the CPU.
XMK_USE_SDL_MEM
in ml_mcf.h
with the help of the BodyBuilder. This will make the basic memory allocation functions available. The ml_mem.c
module must of course be compiled an linked together with the application. ml_mem.c
called CPU_WORD_SIZE.
The right setting of this macro is basically important for making the dynamic memory allocation functions do work. With this flag, it is possible to define the word size of the target CPU. The value is predefined in ml_mem.c
but it could be the case that the predefined value is inappropriate for the target system. If the CPU_WORD_SIZE
value must be redefined, this could be done in ml_mcf.h
in the user's section. The predefined value for UNIX compilers is 8, the predefined value for ARM_THUMB
C compiler 4, otherwise a default value of 1 (no alignment) is used. 8051
and derivatives a CPU_WORD_SIZE
of 1 is appropriate.XMK_USE_MIN_BLKSIZE
is to be used. With the define XMK_MEM_MIN_BLKSIZE
the user may define the minimum block size per each allocated block. If the XMK_MEM_MIN_BLKSIZE
is not defined from the user, a minimum block size of 64 is predefined. ml_mem.c
module contains profiler that keeps track on how many blocks are allocated, how much memory is free and furthermore. The user must define
XMK_ADD_PROFILE
in order to get the complete functionality. If the Cmicro Tester is used, the flag is automatically predefined.In/Out: -no- Return: -no-
This C function returns the net amount of occupied memory. It is available only if XMK_USE_SDL_MEM
and XMK_ADD_PROFILE
are set.
In/Out: -no- Return: size_t
This C function returns the net amount of occupied memory. It is available only if XMK_USE_SDL_MEM
and XMK_ADD_PROFILE
are set.
In/Out: -no- Return: size_t
Returns the amount of free memory in sum, which means that the overhead from each block is included. It is available only if XMK_USE_SDL_MEM
and XMK_ADD_PROFILE
are set.
In/Out: size_t Return: size_t
This function is either used from Cmicro's dynamic memory allocation functions xmk_Malloc()
and xmk_Calloc()
or it may be used directly from the user.
It is available only if XMK_USE_MIN_BLKSIZE
is set.
The function is declared as:
size_t xmk_EvaluateExp2Size ( size_t GivenLength )
The function evaluates from the given length a length value, which is in any case a 2 exp N value. This is used to reduce the risk of memory leaks that occur in dynamic memory management systems. It may be used for the memory functions of this module but also for the memory functions of an operating system or C compiler. If the minimum block size is in any case greater than the greatest block that is requested in the target system, then there is no risk for memory leaks. The return result is either the minimum specified with XMK_MEM_MIN_BLKSIZE
, but might be also one of the following values:
64,128,256,512,1024,2048,4096,8192,16384,32768,65536
The Cmicro Tester offers a command that allows the user to inspect the status of the dynamic memory. Unfortunately this command can be used only, if the dynamic memory management from Cmicro is used (by setting the XMK_USE_SDL_MEM
flag in the BodyBuilder).
The command allows the user to check the following:
xmk_T_MBLOCK
(see ml_mem.c
)The command presents the following output to the user:
M-STATE:Memory pool size incl.overhead =4096 M-STATE:Current memory fill =136 M-STATE:Current amount of blocks in pool =2 M-STATE:Peak hold: Amount of blocks =29 M-STATE:Peak hold: Largest block =2048 M-STATE:Overhead per block (in bytes) =20 M-STATE:Minimum block size =0 M-STATE:Memory pool address (hex) =28478 M-STATE:(Probably there are memory leaks)
The command is available only if XMK_USE_SDL_MEM
and XMK_ADD_PROFILE
are set.
In/Out: int ErrorNo Return: void
Errors, warnings and information can be generated and detected in many places and situations during the lifetime of an SDL system. By fully utilizing the Analyzer, several dynamic error sources can be eliminated at the design stage of development.
Some errors or warnings go undetected by the Analyzer, for example resource errors or real time errors such as memory, performance, or illogical use of SDL.
These errors and warnings are detectable by the Cmicro Kernel and the Cmicro Tester. For a complete list of errors, warnings and information, please view the following subsection List of Dynamic Errors and Warnings.
As a general rule, for each error and warning there should be an appropriate reaction in the function ErrorHandler()
in the mk_user
module.
The ErrorHandler()
is, as a default implementation, implemented like this:
In the case of a warning message, either:
XMK_WARN_ACTION_HANG_UP
are carried out (see Reactions on Warnings).XMK_WARN_ACTION_PRINTF
are carried out.XMK_WARN_ACTION_USER
and XMK_WARN_USER_FUNCTION
are carried out.In the case of an error message, either:
XMK_ERR_ACTION_HANG_UP
are carried out (see Reaction on Errors)XMK_ERR_ACTION_PRINTF
are carried out.XMK_ERR_ACTION_USER
and XMK_ERR_USER_FUNCTION
are carried out.For more explanations on these flags, please view Reactions on Warnings and Reaction on Errors. If printf is used, the C module ml_mon.c
below the cmicro/kernel
directory must be compiled also.
Errors are numbered easily by an integer value. If the user's target allows the use of printf
, then use the C function xmk_err_text
contained in the ml_err
module. It is easier to specify error handling in this module rather than directly modifying the ErrorHandler
function.
Default implementation of ErrorHandler()
void ErrorHandler ( int ErrorNo ) { ... ... ... ErrorClass = xmk_GetErrorClass (xmk_TmpErrorNumber); #ifdef XMK_WARN_ACTION_HANGUP if (ErrorClass==XMK_WARNING_CLASS) while (1); #endif /* ... XMK_WARN_ACTION_HANGUP */ #ifdef XMK_ERR_ACTION_HANGUP if (ErrorClass==XMK_FATAL_CLASS) while (1); #endif /* ... XMK_ERR_ACTION_HANGUP */ #ifdef XMK_WARN_ACTION_PRINTF if (ErrorClass==XMK_WARNING_CLASS) xmk_MonError (stderr, xmk_TmpErrorNumber); #endif /* ... XMK_WARN_ACTION_HANGUP */ #ifdef XMK_ERR_ACTION_PRINTF if (ErrorClass==XMK_FATAL_CLASS) xmk_MonError (stderr, xmk_TmpErrorNumber); #endif /* ... XMK_ERR_ACTION_HANGUP */ #ifdef XMK_WARN_ACTION_USER if (ErrorClass==XMK_WARNING_CLASS) XMK_WARN_USER_FUNCTION( xmk_TmpErrorNumber ); #endif /* ... XMK_WARN_ACTION_USER */ #ifdef XMK_ERR_ACTION_USER if (ErrorClass==XMK_FATAL_CLASS) XMK_ERR_USER_FUNCTION( xmk_TmpErrorNumber ); #endif /* ... XMK_ERR_ACTION_USER */ ... ... ... } /* END OF SAMPLE */
ErrorHandler()
void ErrorHandler ( int ErrorNo ) { /* The user could implement the 3 functions ** fatalerror, warning, and information */ switch (ErrNo) { case ERR_N_UNKNOWN fatalerror(ErrNo); break; case ..... ..... break; default: warning(ERR_N_UNKNOWN); break; } } /* END OF SAMPLE */
ml_mcf.h
.XMK_USE_STATIC_QUEUE_ONLY
and XMK_USE_STATIC_AND_DYNAMIC_QUEUE
), this must be treated either as a warning or as a fatal error.XMK_USE_STATIC_QUEUE_ONLY
is set.XMK_USE_STATIC_AND_DYNAMIC_QUEUE
is set.ml_mcf.h
or change the size of predefined dynamic memory pool (the memory pool, that is used when the xAlloc C function is called)..
XMK_CREATE_SIGNALID
which is automatically defined in ml_mcf.h
according to the setting of XMK_USE_MORE_THAN_250_SIGNALS.xmk_Send*
.xOutEnv()
does not handle all necessary signals. It should handle all signals which are sent to the environment. Please view Return Values of xOutEnv().alloc()
and malloc()
has to be initialized. This error occurs if a malloc()
takes place before the memory is initialized. See ml_mem.c xRouteSignal()
has to be filled by the user. See Getting the Receiver of a Signal -- Using xRouteSignal. This error code means that there is no receiver defined for the current signal. xmk_InitQueue()
. This function must be called before xmk_InitSDL()
may be called. xmk_Malloc()
C function with a wrong parameter. It is not allowed to request a memory block of the size 0. xmk_Free()
function of the Cmicro Memory Management (see the file Exported from ml_mem.c) occurred and the given block is an invalid block. sdl_cfg.h
) and the amount of statically predefined timer instances (XMK_MAX_TIMER_USER defined with BodyBuilder) is being reached. switch
statement in use with a default branch. It should not occur during system execution.A light integration is to be performed if the SDL system including the Cmicro Library should execute within just one operating system task.
The SDL system usually communicates with the environment by using a mailbox or message queue or something similar, which is provided from the operating system. Within the SDL system, the Cmicro scheduler is used. This means that signals that are sent internally in the SDL system are not sent via the mailbox/message queue from the operating system.
All the explanations which follow now are based on the example C file called light_ex.c
residing below the Cmicro template directory.
The execution model for an SDL system in a light integration can be sketched with the following meta code:
/* In the user's initialization task do : */ Initialize memory Initialize time Initialize mailbox(es) or message queue(s) Initialize other resources Make the SDLTask an operating system task Wait until the SDLTask has finished initialization Continue with creating other operating system tasks
The model for what the SDL task does in a light integration can be sketched with something like:
Initialize Cmicro Tester Initialize Cmicro SDL queue Initialize Cmicro Trace options (if wanted) Initialize SDL and execute start transitions of the process instances which are to be created statically Forever do { if there is a signal to be consumed { process that signal } else, if there are only saved signals { evaluate the remaining duration for the timer that will expire next if there is at least one active timer { listen on the operating system queue for the remaining duration, by using a blocking function call } else { listen forever to the operating system queue by using a blocking function call } If a message was received, format the message and send it as an SDL signal to the SDL system If a timeout occured (remaining duration), then check all the timers. For each timer that has been expired there will be one signal be put into the SDL queue } }
In the Cmicro product, there is an example file called light_ex.c
below the cmicro/template
directory. This file contains a sketch of the adaptations that the user must do for a light integration. This subsection gives the user the details that he must know for the adaptations and at some places a reference into the light_ex.c
is given.
In a light integration, the user must take care upon the following:
main()
function or in the "INIT" process. To do so, there must also be a declaration likeextern void SDLTask (void)in the users C code. The C function
SDLTask()
from the light_ex.c
module will serve as the operating system task for SDL. The user must make sure that resources like memory, mailbox or message queue are available before communication starts. Otherwise there will be errors during system start up. xInitEnv()
, but probably outside SDL, this depends on what the user wants. xOutEnv()
for sending signals to the environment (another operating system task). It is up to the user what kind of communication is to be used in this direction, e.g. it could be mailbox, message queue, semaphore or whatever. Note, that all necessary resources (like the receivers mailbox for example) must have been created before using. XMK_SEND_ENV()
as usual. XMK_SEND_ENV
. Note again, that all necessary resources must have been created before use, e.g. message queue. xmk_T_TIME
) by using an operating system task or similar. An time overrun is automatically detected by the Cmicro Kernel as usual. memset(), calloc(), malloc(), sprintf()
... makeoptions/make.opt
file (and may use the Cmicro example makeoptions/make.opt
file as a template), and the BodyBuilder should be used to set a few options accordingly. These are: main()
function. The main()
function from the light_ex.c
module may be used as an example. xInEnv()
function is useless. Signals coming from the environment are, as explained, read from the OS queue. The xOutEnv()
function is however unaffected from this. xmk_RunSDL()
C function is not declared appropriate. xmk_SaveSignalsOnly()
from mk_queu.c
and xmk_NextTimerExpiry()
from mk_tim1.c
accordingly.System partitioning may be used when:
And either:
System partitioning allows it do specify all blocks, processes, procedures and all necessary declarations within just one SDL system. This increases the overview and the simulation possibilities compared with the solution to specify different SDL systems.
The graphical user interfaces like Organizer, BodyBuilder and Cmicro Tester do not provide the kind of system partitioning feature which is explained here, but the stand alone SDT Analyzer sdtsan
does.
The next subsection describes the model of partitioning.
The use of sdtsan
for system partitioning is explained in the subsection following that subsection.
In the last subsection about partitioning the different adaptations which are to be made for communicating partitions are outlined.
When a system is partitioned, there must be exactly one SDL scheduler per partition. This scheduler is responsible for scheduling all the signals within the partition, which means that the internal signals are not sent via the mailbox or message queue from the operating system.
As a result from this, the usual SDL scheduler which is used for bare and light integrations can be used to handle one partition. But of course it must be possible to let several SDL scheduler coexist in one system.
If several partitions shall execute within one executable, there are a few things that must be handled with care.
The term executable usually stands for a program that consists of one main()
function and the functions which are called from this main()
function.
System partitioning mainly affects the C identifiers for C variables and C functions in the case if several partitions shall coexist in one executable. The Cmicro Library and the generated C code of Cmicro can be used several times within several partitions that coexist in one executable. This has been made possible by renaming global identifiers into identifiers with unique prefixes.
Not all of the C functions have been duplicated per each SDL system, e.g. an exception should be made for C functions that operate on variables allocated on C stack only (an example is ml_pred.c)
.
The main use of partitioning in Cmicro will be:
The stand alone analyzer sdtsan
supports two commands "program" and "component" which allow the user to pick up several pieces out from an SDL system and generate a partition out of it. This can be repeated for each partition and each partition can be compiled and linked.
First, the several commands for invoking the analyzer in stand alone mode are to be specified in a text file, like it is done in the following example in the text file partition1.script:
partition1.script
<Specify the input file> set-Prefix Full set-Compile-Link off program partition1 component system mostctrl/block env_test component system mostctrl/block t_create/process created component system mostctrl/block t_create/process creator set-env-header on Set-Env-function on set-modularity user set-kernel SCTDEBCOM generate-micro-c
The partition will then be translated into all the necessary files by invoking the analyzer like this:
sdtsan < partition1.script
The result of the operation above is as follows:
There is one subdirectory generated below the target directory, that is holding the generated files. The name for the directory is the same as for the program,. In the example above there will be a subdirectory called partition1. There is also the usual makefile <systemname>.m
, which the user might use to compile the partition. The files that belong to one partition are to be compiled with a command line like:
cc -I<pathto>/partition1 -I<otherpathes> -DXSYSID="part1" <pathto>/partition1/*.c cc -I<pathto>/partition1 -I<otherpathes> -DXSYSID="part1" <pathto>/cmicro/kernel/mk*.c
The user must take care, that there might be several object files with the same name, so that as a recommendation, the object files of one partition should be stored below the partition's directory. This can be achieved with the -o
option which conventional C compilers do provide (or otherwise the user may move the object after creating it).
This procedure of generating and compiling a partition is repeated for all the partitions that the user wishes to define. After all, and after communication between the partitions was specified, the procedure of linking all object files together is to be performed.
The user must ensure manually, that the partitions are correctly specified. For instance there is no check, of a process was specified twice in different partitions, which will lead to problems.
As each partition can be seen as a stand alone SDL system, the following things must be done additionally:
The user should be aware that the communication internally in a partition is automatically translated by Cmicro Code Generator, and handled by the Cmicro Kernel.
As a recommendation, not too many partitions should be defined in order to generate most of the communication automatically.
For the case of naming conflicts in global identifiers, there is a mechanism in Cmicro that helps. It may be important for the user to understand the mechanism, because he may wish to use it in his own definitions also. The correct identifiers must however also be known when a C debugger is used.
In the Cmicro Library, there is a macro definition which allows it to redefine the names of global C identifiers. The identifiers that Cmicro Library knows about are already redefined, so that no problems occur.
The macro definition is:
#define XMAKENAME(P1,P2) XCAT(P1,P2)
In order to make an identifier unique in the system, the following definition is introduced:
#define xmk_RunSDL XMAKENAME(XSYSID,RunSDL)
This means, that the global C identifier xmk_RunSDL()
(which is a C function that the user knows from the Cmicro Kernel) is concatenated with the both names of XSYSID
and RunSDL
. If the value of XSYSID
was defined as -DXSYSID="part1"
when the C compiler was invoked, then the redefined name of xmk_RunSDL()
is part1RunSDL()
.
In this wise, all the identifiers of Cmicro are redefined. The C function yInit()
in the generated C code is also redefined with this mechanism, in the example above it would be renamed to part1yInit().
The macro can be used for ANSI C compilers only.
Signal IDs are still generated into the generated C file and into .ifc
file and begin from x to y in each partition. x is still the first signal after the last timer signal.
The above introduces problems for specifying the interface between two partitions, because the signal signal1
may have an ID value of 1 in the first, but an ID value of 2 (or whatever) in the second partition.
The user must in any case define a new ID value manually, that is unique between the partitions, and map the signal IDs appropriately when sending / receiving it.
The following restrictions are introduced when partitioning is used:
env.c
file that the BodyBuilder produces, can be used as a template only. XMAKENAME
macro explained in the previous subsection to prevent naming conflicts.ml_mem.c
, ml_mon.c
This file is automatically generated by the Cmicro Code Generator into the directory which is currently active. It contains compilation flags used for the automatic scaling of the Cmicro Library and the generated C code. The file must not be edited by the user.
This file is the central header file in the Cmicro Package. It contains
These files contain all definitions necessary to handle SDL data, for example predefined sorts. sctpred.h
is included in ml_typ.h
.
sctpredg.h
, including all predefined generators is included from sctpred.h
. These predefined generators need to be excluded for several compilers. Please view the flag XNO_LONG_MACROS.
This header file defines all error numbers used by the Cmicro Kernel, the Cmicro Library and the Cmicro Tester.
This file contains the dynamic memory management functions from Cmicro. It contains among other functions the C functions xmk_Malloc(), xmk_Calloc()
and xmk_Free()
. Possible reasons to use this module are:
ml_mem.c
, like profiling. Please view Dynamic Memory Allocation.This file is included by the ml_mon.c
file. It exists only for internal purposes and in order to maintain all the defined errors in the system in a better way.
This file contains some help functions which are useful in producing screen outputs. It contains C functions for buffer printouts, SDL PId printouts, displaying error messages, and the display of the current scalings used in the executable. The file should usually be included when compiling the kernel.
Other header files which contain extern declarations of modules of the Cmicro Library.
This file represents the main-interface to the SDL user. It contains functions which are to be called by the SDL user to integrate the Cmicro Kernel in his application.
xmk_InitSDL()
xmk_RunSDL()
The C main()
function is placed in mk_main.c
, too. This main()
will only be used if the flag XNOMAIN is not set. If the flag XNOMAIN
is set, the user has to provide his own main function.
For Cmicro Tester, there are some more functions to be called during initialization. Please view The Cmicro Tester.
Note: The SDL queue must in any case be initialized before the SDL system is going to execute. The initialization function is called |
This module is not part of the Cmicro Kernel, but it contains function templates or examples which are to be filled out by the user:
ErrorHandler()
Central error handling routine is called each time an errors occurs.
WatchdogTrigger()
Handling of a hardware watchdog.
In earlier versions of the Cmicro Package the functions xInitEnv(), xInEnv(), xOutEnv()
and xCloseEnv()
were include in mk_user.c
, too. These functions will now be generated by the BodyBuilder and stored in the file env.c
. Please view The Generated Environment
This file is the heart of the Cmicro Kernel. It exports those functions which are used in the mk_main
module and it uses those functions of other modules which represent the SDL model. The module serves with all the different scheduling policies described later in the subsection Scheduling.
This file contains the SDL operation OUTPUT which is represented by a few functions. There is a C function xmk_Send()
representing the SDL output operation. In addition, there is a C function xmk_SendSimple()
which is used when a signal contains no parameters and has no explicitly defined priority. This results in a more compact argument list thus reducing the generated C Code.
This module contains the data type "SDL queue" and defines all operations on the SDL queue. The queue handling covers all the aspects of the SDL semantics as far as signals are concerned. There is one function xmk_InitQueue()
which must be called in the user's main()
function before the SDL system is going to execute.
This file contains the SDL operations on timers such as set, reset, active, and some help functions used by the Cmicro Kernel. The timer model is described within the subsection Timers and Operations on Timers. The Cmicro Kernel has to initialize all timers, test for expired timers and reset all timers of a process, when a process instance stops.
This file contains some functions which are to be filled up by the user. They are used by the Cmicro Kernel to get the system time used in SDL. The contents of this file should be seen as a template. No provision for the connection to hardware timers is provided in the delivered source, as the timer used is application dependent. The user is required to fill out the appropriate functions for the provision of SDL system time. Please view Defining the SDL System Time Functions in mk_stim.c
This file also contains some hardware specific functions which should be seen as templates.
Other header files contain extern declarations of modules of the Cmicro Library. The contents and details of the various header files only need to be known if the user wishes to modify parts of the Cmicro Library.
The list in the following section gives an overview of the functions exported by each module of the Cmicro Library in order to understand the module structure. The functions declared as static are not considered here.
If there is a reference to xmk_RAM_ptr
, this can be replaced with a * (star) usually. This means that for example the declaration
xmk_T_CMD_QUERY_QUEUE_CNF xmk_RAM_ptr qinfo
can be replaced with
xmk_T_CMD_QUERY_QUEUE_CNF *qinfo
which means to refer to a pointer to an object of the type xmk_T_CMD_QUERY_QUEUE_CNF.
In/Out: -no- Return: -no-
This function is called by the Cmicro Kernel during initialization of the
SDL system. The user may include initialization of the environment here.
In/Out: -no- Return: -no-
This function is called by the Cmicro Kernel continuously to retrieve signals polled from the environment. Use the Cmicro Kernel function xmk_Send
* to put signals into the system. The use of this function is not absolutely necessary in the case where the Cmicro Kernel is scaled to preemption and all external Events are put into the SDL system via an Interrupt Service Routines.
In/Out: xmk_T_SIGNAL sig, xmk_T_PRIO prio, unsigned char data_len, void *p_data, xPID Receiver Return: xmk_OPT_INT
This function is called by the Cmicro Kernel if an SDL signal is to be sent to the environment.
Note: The user has several possibilities to send signals to the environment. Please refer to the subsection about the Functions of the Expanded Cmicro Kernel. |
The function must return with XMK_TRUE, if the Signal was sent to the environment, otherwise it must return with XMK_FALSE.
In/Out: -no- Return: -no-
This function is called by the Cmicro Kernel during the exit phase of the
SDL system. The user may include de-initialization of the environment here.
In/Out: int ErrorNo - the given error number Return: -no-
This is a function which is to be filled out by the user. The Cmicro Kernel as well as the SDL application are the main clients of this function.
The user may distinguish between the different errors and define a specific reaction.
The different errors defined in the file ml_err.h
below the Cmicro Kernel directory.
In/Out: -no- Return: -no-
Description:
If selected this function is called by the Cmicro Kernel each time an SDL transition is executed
In/Out: -no- Return: -no-
This C function is called by the user before calling the C function xmk_RunSDL()
and implements the initialization of the whole SDL system, namely Timer, Queue, Processes.
In/Out: unsigned char CountSignals Return: int
This function either processes a fixed number of signals or processes endlessly. Before processing signals, SDL time-outs are checked and the C function xInEnv
is called.
With the given parameter CountSignals
the user may specify the amount of signals which are to be processed within this function call. A value of 0xFF
means endless processing.
The integer value which is returned has the following meaning:
XMK_NORMALRETURN
XMK_STOP
The SDL system is to be stopped because there are no more process instances living and no signals to be processed.In/Out: -no- Return: -no-
This function implements the start-up phase of the SDL system. All static process-instances are created. This means executing the start-transition of all process-instances to be created. For each created process-instance, the first state is set. If configured right, the values SDL_SELF, SDL_PARENT and SDL_OFFSPRING are correctly initialized (only necessary if no semantic check was performed, i.e. if the SDT Analyzer is not used).
In/Out: -no- Return: -no-
This function processes an SDL signal and remains in an internal loop, until a signal has been processed or until no signal remains in any input-port in the SDL system.
In/Out: ProcessID - ID of the process type Return: xmk_T_INSTANCE - created Instance number ID
This function tries to create an instance of the given process-type. This can fail, either if the create signal cannot be allocated (no more memory) or if there is no free process instance of that type. E.g. if there is no instance in the DORMANT
state.
The return value contains the process instance number ID, if one more process instance could be allocated. The return value is set to xNULLINST
if the creation failed for some reason.
The process instance number is not the same as the process ID. The process ID is calculated from the process ID type plus the process ID instance number.
The generated C code does not use the return value, because the SDL offspring and the parent pid value are stored in the pid tables of the process instance.
In/Out: -no- Return: xmk_T_BOOL
This function checks for any active instance of a process type by searching for instances not in the state XDORMANT.
The function returns with XMK_TRUE
, if there is an active instance. It returns with XMK_FALSE
if there is no instance active within the system.
In/Out: -no- Return: -no-
The variables used in preemption are initialized.
In/Out: -no- Return: -no-
The variable which stores the preemption status is incremented. A value greater than zero means it is not allowed to perform a context-switch at the moment.
In/Out: -no- Return: -no-
The variable which stores the preemption status is decremented if preemption was disabled. If the variable's value is zero after it is decremented, the function xmk_CheckIfSchedule()
is called.
In/Out: -no- Return: xmk_T_PRIOLEVEL
This function searches for signals in the priority queue levels. This is done with decreasing priority in order to find the highest priority level at which signals exist. The return value is the highest priority level that contains a signal to process.
In/Out: -no- Return: -no-
It is checked whether a context switch is admissible. If this is the case the current priority-level is compared with the highest priority-level where a signal exists. Supposing the highest level is higher than the current, a context-switch is performed using xmk_SwitchPrioLevel()
. This is repeated until the current priority-level is the highest level.
In/Out: xmk_T_PRIOLEVEL NewPrioLevel Return: -no-
The global variables for the current priority-level are stored. Afterwards, the function xmk_ProcessSignal()
is called in order to deal with the signals on the higher priority level. After returning from this function call the variables for the current priority-level are restored.
With the NewPrioLevel
the next prio-level to deal with is specified.
In/Out: #ifdef XMK_USE_RECEIVER_PID_IN_SIGNAL xmk_T_SIGNAL sig xPID Receiver #else xmk_T_SIGNAL sig #endif Return: -no-
This is a simple SDL output function which needs a maximum of only 2 Parameters. Most SDL systems consist of a lot of "normal" Signals without any parameters and no priority. It makes sense to use this simple function whenever possible to spare program code. The signal is put into the linked list of signals by using a default priority.
With the first parameter sig
, the signal ID of the signal that is to be sent is specified. With the (optional) second parameter, the receiver process ID is specified. If XMK_USE_RECEIVER_PID_IN_SIGNAL is not defined, the user must implement the C function xRouteSignal()
which is responsible to derive the receiver from the signal ID in that case. Using xRouteSignal()
is recommended only if the last few bytes must be spared for transferring of signals.
In/Out: xmk_T_SIGNAL sig #ifdef XMK_USE_SIGNAL_PRIORITIES xmk_T_PRIO prio #endif #ifdef XMK_USED_SIGNAL_WITH_PARAMS xmk_T_MESS_LENGTH data_len void xmk_RAM_ptr p_data #endif #ifdef XMK_USE_RECEIVER_PID_IN_SIGNAL xPID Receiver #endif Return: -no-
This is, compared to the xmk_SendSimple
function, a complete SDL output function which needs all possible signal parameters.
With the parameter sig
, the signal ID is to be specified.
With the prio
parameter, the signal's priority is to be specified (if conditionally compiled).
With the data_len
, the number of bytes as the signal's parameters is to be specified. The number of bytes is evaluated by using a
sizeof (C struct)
construct. If the signal carries no parameters, this value must be set to 0 (if conditionally compiled).
With the p_data
parameter, a pointer to the memory area containing the parameter bytes of the signal is given. The memory area is not treated as dynamically allocated within this function. Because the function copies the parameter bytes, the caller may use any temporary memory (for example memory allocated from the C stack by declaring a C variable). This parameter should be set to NULL
if no parameter bytes are to be transferred (if conditionally compiled).
With the last parameterReceiver, the PID of the receiving process is to be specified (if conditionally compiled).
If the XMK_USE_SIGNAL_PRIORITIES is not defined, the signal priorities which are specified with #PRIO in the diagrams is just ignored. The use of signal priorities is not recommended because the violation of SDL. A few bytes can be spared if signal priority is not used.
The XMK_USED_SIGNAL_WITH_PARAMS is automatically generated into the sdl_cfg.h
file, from the Cmicro Code Generator. For tiny systems, if there are no SDL signals with parameters specified, this is undefined. It will reduce the amount of information which is to be transferred for each signal with a few bytes.
If XMK_USE_RECEIVER_PID_IN_SIGNAL is not defined, the user must implement the C function xRouteSignal()
which is responsible to derive the receiver from the signal ID in that case. Using xRouteSignal()
is recommended only if the last few bytes must be spared for transferring of signals.
In/Out: xPID Env_ID xmk_T_SIGNAL sig #ifdef XMK_USE_SIGNAL_PRIORITIES xmk_T_PRIO prio #endif #ifdef XMK_USED_SIGNAL_WITH_PARAMS xmk_T_MESS_LENGTH data_len, void xmk_RAM_ptr p_data #endif #ifdef XMK_USE_RECEIVER_PID_IN_SIGNAL xPID Receiver #endif Return: -no-
This function is to be called when a signal is to be sent into the SDL system, e.g. within the users xOutEnv()
function. It must be called with one more parameter than the xmk_Send()
function, which is the first parameter Env_ID
. This parameter must be set to ENV
by the user.
The macro internally uses some variables which are to be declared before the macro can be used. For example in the xOutEnv function the XMK_SEND_TMP_VARS
macro must be introduced for declaring these variables.
The function is implemented as a macro in C.
In/Out: xmk_T_PROCESS proc_type - process type ID Return: xPID - process PID
This function is used in the context of SDL output in generated C code. The function determines if any instance with the given process type-ID is available to receive the signal. If no instance can be found, xNULLPID
is returned.
In/Out: -no- Return: -no-
This function initializes the signal queue. It must be called before any other Cmicro Kernel function, e.g. before xmk_InitSDL()
. All relevant pointers are initialized. All signal-elements are put into the free-list. The SAVE-state of all signals is set to false.
In/Out: -no- Return: xmk_T_MESSAGE*
The first signal in the current queue which is the one with the highest priority, is copied to the pointer of the currently treated signal and returned to the caller.
The function returns a pointer to the first signal in the queue or NULL
, if there are no signals in the queue.
In/Out: -no- Return: xmk_T_MESSAGE*
The signal following the current signal is copied to the current signal. If there are no more signals, NULL is returned.
In/Out: xmk_T_MESSAGE xmk_RAM_ptr p_Message Return: -no-
This function puts a signal into the queue. The position depends on only the signal priority, if specified.
With the parameter p_Message
a pointer to the signal which is to be inserted is given.
In/Out: -no- Return: -no-
The signal which was currently processed is removed from the queue and inserted into the list of free signals.
In/Out: xmk_T_SIGNAL SignalId Return: -no-
This function is not used if timers with parameters are in the system (XMK_USED_TIMER_WITH_PARAMS
macro is defined).
Signals of a given signal-code sent to the current process are removed from the queue and inserted in the list of free signals. The signal currently being processed must not be removed, as it is necessary for the current actions. It is only removed after processing is complete.
With the parameter SignalID
, the signal ID of the signals which are to be removed for the currently active process instance is specified.
In/Out: xmk_T_SIGNAL SignalId In : SDL_Integer TimerParValue Return: -no-
This function is only compiled if timers with parameters are in the system (XMK_USED_TIMER_WITH_PARAMS
macro is defined).
This function has the same purpose as the above xmk_RemoveSignalBySignalID
but, in addition, must look to the timer's parameter.
In/Out: xmk_T_SIGNAL TimerID #ifdef XMK_USED_TIMER_WITH_PARAMS In : SDL_Integer TimerParValue #endif Return: -no-
This function checks if the given timer is in the signal queue. If timers with parameters are used, the TimerParValue,
which is conditionally compiled, is checked also.
In/Out: xPID ProcessID Return: -no-
All signals addressed to a specific process are removed by calling this Function.
With the parameter ProcessId
, the PID of the process for which all the signals are to be removed from the queue is specified.
In/Out: -no- Return: xmk_T_MESSAGE xmk_RAM_ptr
According to the principle chosen by the user (the user has to choose between XMK_USE_STATIC_QUEUE_ONLY
and XMK_USE_STATIC_AND_DYNAMIC_QUEUE
), and if possible, an initialized signal instance is returned. The signal instance is then either taken from the static memory pool or from the dynamic memory pool.
Allocation from the dynamic memory pool takes place by calling the xAlloc
C function.
If XMK_USE_STATIC_QUEUE_ONLY
is set, the ErrorHandler
is called with the error "ERR_N_NO_FREE_SIGNAL
". This indicates that no more memory is available to create one more signal instance, and the user may react appropriately in the ErrorHandler
C function.
Otherwise, if XMK_USE_STATIC_AND_DYNAMIC_QUEUE
is set, and if it is impossible to allocate one more instance from the predefined static memory pool, the ErrorHandler
is called with the error "ERR_N_NO_FREE_SIGNAL
". This indicates that dynamic memory allocation is started now, and the user may react appropriately in the ErrorHandler
C function (for example, he might want to print out a warning message). If it is impossible to allocate one more signal from the dynamic memory pool, the ErrorHandler
is called with the error "ERR_N_NO_FREE_SIGNAL_DYN
". The user may then also decide what to do in the ErrorHandler
C function.
A pointer to the signal that was allocated is returned usually, or NULL
, if there is no space left to allocate one more signal.
In/Out: xmk_T_MESSAGE xmk_RAM_ptr p_Message Return: -no-
The given signal is deallocated again.
If the signal was allocated from the static memory pool, it is returned to that pool by initializing it and inserting it into the free list at the first position.
Otherwise, if the signal was allocated from the dynamic memory pool, it will be returned to that pool (by calling the xFree
C function).
The parameter p_Message
must point to the signal that is to be initialized.
In/Out: xmk_T_STATE State Return: xmk_T_BOOL
This function checks whether a signal's SAVE-state is set or not. In testing, the SAVE-state is set to TRUE
or FALSE
.
With the parameter State, the value of the process' current state is to be specified.
The function returns with XMK_TRUE
, if the given state equals the signal's SAVE-state, but returns with XMK_FALSE
if the given state differs from the signal's save state.
In/Out: -no- Return: -no-
This function tests whether there is at least one signal remaining in the queue(s) or not.
The function returns XMK_TRUE
, if there are no signals in the queue, but returns XMK_FALSE
if there is at least one signal in the queue. It does not matter if the signal is a saved signal or not.
When the Cmicro Kernel is configured for preemption, all the queues of the different priority levels are checked.
In/Out: -no- Return: -no-
All initialization of timers is performed within this function, which is called during SDL system start. It initializes some pointers and the free list of timers.
In/Out: xmk_T_TIME time xmk_T_SIGNAL sid #ifdef XMK_USED_TIMER_WITH_PARAMS In : SDL_Integer TimerParValue #endif Return: -no-
This function activates an instance of a timer with the given "signal ID" value and the given time. If timers with parameters are used, the TimerParValue
, which is conditionally compiled, is used also (the value is set to 0 outside this function call if it is not a timer with parameter).
Working principles:
ErrorHandler()
is called.The first parameter time specifies the time at which the timer should expire. The call to SDL now is performed in generated C code.
The second parameter sid
specifies the ID of the timer that is to be started.
If a timer instance of this type is already running, this will be deactivated. If no free timer is available, the ErrorHandler is called. After all these checks a timer instance is created for the currently running process.
In/Out: xmk_T_SIGNAL sid #ifdef XMK_USED_TIMER_WITH_PARAMS In : SDL_Integer TimerParValue #endif Return: -no-
This function resets the timer with the given "signal ID" value, if it is active and set by the currently running process. If an active timer instance is found, then the timer is inserted into the free-list. If timers with parameters are used, the TimerParValue
, which is conditionally compiled, is used also (the value is set to 0 outside this function call if it is not a timer with parameter).
The parameter sid
specifies the ID of the timer which is to be reset.
In/Out: xmk_T_SIGNAL sid #ifdef XMK_USED_TIMER_WITH_PARAMS In : SDL_Integer TimerParValue #endif Return: xmk_T_BOOL
The functions checks if a Timer with the given "Signal-ID" value is active in the current running process. If timers with parameters are used, the TimerParValue, which is conditionally compiled, is used also (the value is set to 0 outside this function call if it is not a timer with parameter).
The parameter sid
specifies the ID of the timer which is to be checked if it is active.
The function returns with XMK_TRUE
if the timer is active in the process that is currently running, it returns XMK_FALSE
otherwise.
In/Out: -no- Return: -no-
The main intention of this function is to check, if any of the timers which are in the list of active timers is expired. There is a list of active timers in which the active timers are stored in the order of their expiry.
This means that the timer that expires first stands in front of the list.
If a timer was recognized as expired, a timer signal is sent to the owning process instance, the timer is removed from the list of active timers and restored into the list of free timers.
If there is no timer that can expire, the function returns immediately.
Another task for this function is to check if the global system time is overrun. If this case occurs, the xmk_ChkTimer()
function will readjust the global system time (by calling xmk_SetTime()
from mk_cpu.c
) and will readjust all the timers in the active list.
In/Out: xPID pid Return: -no-
All active timers of the given process instance are reset. This will occur if a process instance stops.
With the pid
parameter the process instance is addressed.
In/Out: -no- Return: -no-
This function initializes the hardware timer and is to be filled out by the user.
In/Out: -no- Return: -no-
This function de-initializes the hardware Timer and is to be filled out by the user.
In/Out: xmk_T_TIME time Return: -no-
This function sets the system time to the given value time
and is to be filled out by the user.
In/Out: -no- Return: xmk_T_TIME
This function is used by
The current SDL system time is returned.
The function is to be filled out by the user.
In/Out: char* _mem_begin char* _mem_end Return: -no-
This function is to be called by the user, before dynamic memory management can be used. The user has to specify the beginning and the end of the area to be used for dynamic memory management. The function should be called before the first call to xAlloc()
, e.g. as the first statement in the user's main()
function.
In/Out: unsigned long rsize Return: void *
This function allocates one block of memory from the dynamic memory pool. It uses a first fit policy.
In/Out: unsigned long RequestedSize Return: void*
This function allocates one block of memory from the dynamic memory pool. It is the same as xmk_Malloc()
but sets the allocated block to zero.
In/Out: void *mem Return: void
This function is the counterpart of xmk_Malloc()
. A memory block is de-allocated again.
In/Out: void *pMemBlock unsigned long NewSize Return: -no-
This function is an extension of the compared with the standard of dynamic memory management supported by usual C compilers. It allows the user to shrink down a memory area which was previously requested with xmk_Malloc()
.
In/Out: char *p char val int length- Return: -no-
This function is a template for the memset()
implementation.
Take care when the preemption policy is utilized. |
In/Out: char *dest char *source int length Return: -no-
This function is a template for the memcpy()
implementation.
Take care when the preemption policy is utilized. |
In/Out: xmk_T_ERR_NUM EightBitNumber Return: int
This function returns the error class assigned to the given errornumber given by the caller. The error class can be one of XMK_FATAL_CLASS
or XMK_WARNING_CLASS
. This can be used to clasify the predefined error and warning messages and to react properly if such a message occurs.
In/Out: FILE *fp int nr Return: -no-
This function is used to evaluate an ASCII-Errortext from an errornumber given by the caller. The first parameter fp
must contain a pointer to a valid (i.e. file is opened) file descriptor, for example it could be stdin
, stdout
, or a file which was opened with fopen. The second parameter nr
contains one of the possible error numbers defined in ml_err.h
.
In/Out: char *ostring xPID pid Return: -no-
Used for test purposes, free use.
In/Out: char *p_text unsigned char *p_adress int length Return: -no-
Used for test purposes, free use.
In/Out: char *p_text unsigned char *p_adress int length Return: -no-
Used for test purposes, free use.
In/Out: -no- Return: -no-
Function for test purposes, free use.
In/Out: -no- Return: -no-
Function for test purposes, free use.
In/Out: char * Param1 Return: -no-
A template for how to print out a character string. The character string must be terminated with "\0
".
The function must return immediately, i.e. may not be blocking on the output device. If the user does not care about this restriction, the correct function of other program parts cannot be guaranteed.
In/Out: -no- Return: int
This function checks if the user has pressed a key on the keyboard (unblocked). The function must return immediately, i.e. may not be blocking on the input device. If the user does not care about this restriction, the correct function of other program parts cannot be guaranteed.
In/Out: char* format format string other parameters Return: -no-
This function is called from any place in the Cmicro Library, Cmicro Kernel or generated C code, if the printf functionality is compiled with at least one of the XMK_ADD_PRINTF*
defines.
The function must return immediately, i.e. may not be blocking on the output device. If the user does not care about this restriction, the correct function of other program parts cannot be guaranteed.
The function can be used for ANSI C compilers only, because optional argument lists are used like in the printf function of the standard C library.
The return value has no meaning and is introduced just for compatibility with printf.
In/Out: xptrint Size Return: void *
This function is called from any place in the Cmicro Library, Cmicro Kernel, Cmicro Tester or generated C code, if memory is to be allocated dynamically. The user may choose between the dynamic memory allocation functions from the C compiler or operating system or the dynamic memory allocation functions from Cmicro.
The return value points to the allocated buffer or is NULL
if the operation was unsuccessful.
In/Out: void ** Return: -no-
This is the counterpart of xAlloc()
. The function is called when a memory block that was allocated with xAlloc()
before can be de-allocated again.
Note, that the parameter is the address of the pointer to the allocated buffer.
In/Out: xptrint Size Return: SDL_Charstring
A template for the implementation of the allocation of SDL Charstrings. It is compiled only, if
XNOUSEOFCHARSTRING is undefined.
Size
gives the requested size of the SDL_Charstring which should be allocated.
The function returns with a pointer to the allocatedSDL_Charstring or NULL if the function fails.
In/Out: void ** C Return: -no-
A template for the implementation to free allocated SDL Charstrings.
It is compiled only, if
XNOUSEOFCHARSTRING is undefined
In/Out: xptrint Size Return: char *
A template for the implementation of the allocation of SDL Bit Strings. It is compiled only, if
XNOUSEOFCHARSTRING is undefined.
The return value is a pointer to the allocated memory or NULL
if the function fails.
In/Out: void **C Return: -no-
A template for the implementation of the allocation of SDL Charstrings. It is compiled only, ifvoid **C is undefined.
The parameter C
points to the memory area to be freed
The extended Cmicro Kernel offers additional functionality that is usually not necessary for target applications. Extended functionality is for example required by the Cmicro Tester, but may also be required from the user if it comes to target integration.
It is not absolutely necessary to have knowledge of these functions but knowledge of the functions proves useful when it comes to debugging and testing an application.
All the functions within the following subsections are available only, if at least the XMK_USE_EXPANDED_KERNEL
define is set.
In/Out xPID pid Return: xmk_T_STATE
The function evaluates the current SDL state of the SDL process pid
with the given process PID and returns it to the caller. During SDL system start-up, one possible return value might be XSTARTUP
. This means that a process will be started during system start-up. During normal execution and system start-up, the return value XDORMANT
may be returned. This means that an SDL process instance is either stopped or has never been created dynamically (created).
In/Out: xPID pid, xmk_T_STATE state Return: xmk_OPT_INT
The function sets the SDL-state of the process pid
that is addressed with the first parameter to the given value state
within the second parameter. Note, that the value is not checked, because Cmicro does not store any information about this in the generated transition tables.
In/Out: xPID pid Return: void *
The function returns the address of the process instance data of the given process-PID, or XNOTEXISTENT, if the pid is not existent.
In/Out: xmk_T_SIGNAL sig #ifdef XMK_USE_SIGNAL_PRIORITIES xmk_T_PRIO prio #endif #ifdef XMK_USED_SIGNAL_WITH_PARAMS xmk_T_MESS_LENGTH data_len void xmk_RAM_ptr p_data #endif #ifdef XMK_USE_RECEIVER_PID_IN_SIGNAL xPID Receiver #endif Return: -no-
This function is an alternative to the standard function XMK_SEND_ENV
for putting signals into the SDL system in external C code. The function is useful when signals are to be sent in interrupt service routines directly. The function is shorter than XMK_SEND_ENV
, but performs not so many error checks. It is especially not checked, if the receiver process ID exist. Usually there is also no call to functions which produce trace output because this would lead to problems in interrupt service routines. But for some error situations like either
the ErrorHandler()
C function, which is to be implemented by the user, is called.
With the parameter sig
, the signal ID is to be specified.
With the prio
parameter, the signal's priority is to be specified (if conditionally compiled).
With the data_len
, the number of bytes as the signal's parameters is to be specified. The number of bytes is evaluated by using a sizeof (C struct)
construct. If the signal carries no parameters, this value must be set to 0 (if conditionally compiled).
With the p_data
parameter, a pointer to the memory area containing the parameter bytes of the signal is given. The memory area is not treated as dynamically allocated within this function. Because the function copies the parameter bytes, the caller may use any temporary memory (for example memory allocated from the C stack by declaring a C variable). This parameter should be set to NULL
if no parameter bytes are to be transferred (if conditionally compiled).
With the last parameterReceiver, the PID of the receiving process is to be specified (if conditionally compiled).
If XMK_USE_SIGNAL_PRIORITIES is not defined, the signal priorities which are specified with #PRIO in the diagrams is just ignored. The use of signal priorities is not recommended because the violation of SDL. A few bytes can be spared if signal priority is not used.
The XMK_USED_SIGNAL_WITH_PARAMS is automatically generated into the sdl_cfg.h
file, from the Cmicro Code Generator. For tiny systems, if there are no SDL signals with parameters specified, this is undefined. It will reduce the amount of information which is to be transferred for each signal with a few bytes.
If XMK_USE_RECEIVER_PID_IN_SIGNAL is not defined, the user must implement the C function xRouteSignal()
which is responsible to derive the receiver from the signal ID in that case. Using xRouteSignal()
is recommended only if the last few bytes must be spared for transferring of signals.
In/Out: -no- Return: xmk_T_BOOL
This function tests whether there only are SAVE signals contained in the queue. This can be used in integrations with operating systems.
The function returns XMK_TRUE
, if there are SAVE signals only in the queue, otherwise it returns XMK_FALSE
.
In/Out: xmk_T_CMD_QUERY_QUEUE_CNF * qinfo Return: -no-
The function evaluates the current SDL-Queue-State and returns some information to the caller:
In/Out: xmk_T_TIME * RemainingTime Return: xmk_T_BOOL
The function looks for the remaining time of the timer that expires next. This is useful for operating system integration. If there is no active timer the function returns XMK_FALSE
and the returned parameter RemainingTime
is set to 0.
If there is an active timer the function returns with XMK_TRUE
and the returned parameter RemainingTime
contains the time at which the timer expires next. XMK_TRUE
means there is a timer active and the remaining time is returned in the parameter. XMK_FALSE
there is no timer active and returned parameter is set to 0.
If the remaining time is to passed to an operating system call, the value of 0 may have special meaning. |
In/Out: xmk_T_CMD_QUERY_TIMER_CNF *tinfo Return: -no-
The function evaluates the current State of the SDL-Timerhandling and returns it to the caller. The following information is contained in the C structure that is returned:
These descriptions allow the user to estimate the required resources for the target executable. The following items are described:
This section shows when and how dynamic memory allocation is used in the Cmicro Package. It shows,
The Cmicro Package uses a form of dynamic memory management for the following objects:
However, real dynamic memory management is used only in one case, namely for SDL signals, if a signal carries parameters with more than a few bytes.
This means that the Cmicro Kernel has its own memory management to handle processes, signals, and timers. This is done in such a way that each of these 3 objects are managed separately. For each of these 3 objects, a separate fixed memory area is reserved during compilation time, i.e. the area that handles processes cannot be reused to handle timers. This seems to be a restriction but in many micro controller applications users have to fix an upper limit of processes, signals and timers which can be handled in parallel during run time.
Processes are handled without dynamic memory allocation functions. The user has to specify an upper limit of process instances in the SDL diagram separately for each SDL process. For each process instance, there is a variable which is statically allocated.
Cmicro signals are both ordinary SDL signals as well as timer signals. Where timers are implemented without parameters and can therefore be regarded as signals without parameters.
malloc
/free
for timersmalloc
/free
for signals without parametersmalloc
/free
for signals with parameters if less than or equal to XMK_MSG_BORDER_LEN
bytes parameters are to be transferred.XMK_MSG_BORDER_LEN
bytes parameters are to be transferred. XMK_MSG_BORDER_LEN
bytes is a macro defined in the manual configuration file ml_mcf.h
. It can be set to any value, i.e. zero or the maximum number of signal parameters to be handled in the system.For timers, no malloc and free functions are used. The Cmicro Code Generator evaluates the amount of timers in the system and generates a C constant, which is then used in the Cmicro Kernel to define an array for timers.
The RAM memory required for an application can be estimated if the maximum amount of processes, signals in the queue, timers and variables is known. The ROM memory requirements for an application cannot be derived without programming and compiling the application or having experience of a similar application. The ROM occupation from the Cmicro Library can be specified as a minimum and a maximum value for specific hardware.
The estimations made also depend on the target hardware. Microprocessors differ very strongly in the memory requirements for the program code (factor 2 is known) and the layout of variables (an integer sometimes is represented as 2 Bytes but can sometimes be represented as 4 Bytes).
Another influencing factor is that it is not initially known which language characteristics are to be used to implement the application. This is valid regardless of the implementation programming language.
Some threshold values are depicted in the following section.
The following values are measured with the Microvolts C compiler version 8.0 for any 80x86 microprocessor, for a middle range SDL application with 15 processes.
For signals with more than 4 byte parameters, an additional memory block is allocated with the size of the parameter area.
The ROM occupation of the Cmicro Library is very strongly dependent on the automatic and manual scalings. The Cmicro Kernel uses between 1 Kilobyte to 8 Kilobyte on a 80x86.
For the non preemptive Cmicro Kernel:
XMK_MAX_SIGNALS
For a Cmicro Kernel using preemption an additional static memory occupation of 8 Bytes to 16 Bytes in the scheduler per priority level applies.
The Cmicro Kernel requires a stack of about 45 to 128 bytes. If it is scaled for preemption, an additional 14 to 28 bytes is required for the stack.
In this section, performance information on the Cmicro Kernel is given.
Imagine an SDL system consisting of two processes ping and pong. The both processes send the both signals ping and pong alternating. The execution time for this example is measured on a SPARC-10:
26.2 seconds for 1.000.000 times ping-pong.
This means that the time to handle 1 input and 1 output is about 13 microseconds. Or, in other words, in one second it is possible to handle 77.000 signals.
When performed on a 80386-25 MHz DOS PC platform, using the DOS-command "time" the following performance results were recorded.
9 seconds for 30.000 times ping-pong.
The last performance measurement is more inaccurate as DOS-interrupts cannot be excluded.
The following result was observed on a SPARC 10 platform with the example modified so that 50 parameters were ping - ponged, where each parameter was an integer: