[Previous] [Next] [Contents] [Index]


    The Cmicro Library

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.

Table of Contents 

Introduction

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:

  1. The section Differences between Cmicro and Cadvanced helps in taking care of compatibility between different C code generators. There are things which must be observed in SDL diagrams.
  2. The section The SDL Scheduler Concepts gives information about how the SDL scheduler works. This is also of interest for creating SDL specifications with the most highest conformity because the different SDL schedulers work differently.
  3. The section Targeting with the Cmicro Package presents all the steps that must be carried out for doing targeting with Cmicro.
  4. The section The BodyBuilder outlines how the BodyBuilder works and how the graphical user interface of that tool is to be used.
  5. The section Compilation Flags presents a complete list of all the flags that the BodyBuilder recognizes. The different flags are explained in detail. The on line help of the BodyBuilder contains links to these descriptions.
  6. The section Adaptation to Compilers must usually be read before the C code generated by the Cmicro Code Generator and Cmicro Library can be compiled to form an executable. This section outlines the steps that must be carried out for introducing a C compiler which is not in the available list. The Cmicro Library contains some C compiler adaptations, which are listed in the BodyBuilder's graphical user interface.
  7. The section Bare Integration gives detailed information on how to adapt the generated SDL system to the environment. Communication with handwritten C code, as well as communication between SDL and the operating system or a naked machine, is described here.
  8. The section File Structure explains the functionality of the different C files delivered with Cmicro.
  9. The section Functions of the Basic Cmicro Kernel contains a list of C functions that are usually included in a target executable plus a short description.
  10. The section Functions of the Expanded Cmicro Kernel contains a list of C functions that are usually not included in a target executable. The functions listed in this section can usually be left out because they have meaning for special forms of integration in target systems only. The functions include a short description.
  11. The section Technical Data presents some information to the user which enables him to roughly estimate the consumption of memory in the target system. A self defined benchmark test is included, too.

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.

Differences between Cmicro and Cadvanced

General

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.

SDL Restrictions

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.

The subsection Cmicro Kernel/Library explains the definitions that can be changed with the BodyBuilder.

Scheduling

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.

Generation of Files

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.

Environment Handling Functions

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:

In general (for Cmicro as well as Cadvanced) four C functions are used to represent the SDL environment, namely

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.

Including C Code in SDL by User

C code may be included in SDL by the user in the following cases:

If any C code or C identifiers are used, then users must use the right identifiers and functions.

Generated C Code

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.

General Recommendations Regarding Compatibility

In order to reach full compatibility between Cadvanced and Cmicro, the following general recommendations should be followed:

The SDL Scheduler Concepts

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.

Signals, Timers and Start-Up Signals

Data Structure for Signals and Timers

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:

Three different cases are to be considered concerning signals with parameters:

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 ml_mcf.h to modify this.

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:

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

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.

Signals and Signal Parameters

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:

  1. Signal instances are allocated from a static memory pool only.

  2. The static memory is allocated during compilation. The pool's size is predefined with the 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.
  3. As another principle, it is possible to first take memory from the static memory pool. If no more memory is available in that pool, further signal instances are created from the dynamic memory pool.
  4. Caution! 

    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

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.

Predefined Sorts

Some of the predefined sorts require dynamic memory allocation. The sorts are

Cmicro Tester

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.

Overview for Output and Input of Signals

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

Extracted pic [1]

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

Extracted pic [2]

When working on a signal, the Cmicro Kernel decides between four different constellations:

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.

Timers and Operations on Timers

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.

xmk_T_TIME is defined as a long value.

Figure 543 : Handling of timers (timer model 1)

Extracted pic [3]

The component

As can be seen above, timers are implemented as a forward linked list.

Note: 

Timers with parameters are not implemented.

Processes

Data Structure for Processes

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.

Scheduling

The Cmicro Kernel supports in principle the following scheduling policies:

General Scheduling Rules

Further explanation of the scheduling is in the next subsection.

Non Preemptive Scheduling

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.

Note: 

The priority of a create signal in the standard delivery is set to one.

This, as well as all the default signal priorities, is user-definable in the file ml_mcf.h (generated by the BodyBuilder). In this way it is possible to define signals with a higher priority then the create signal. The user should remember not to do so!

Figure 544 : Non preemptive scheduling

Extracted pic [4]

Figure 545 : Scheduling for Create

Extracted pic [5]

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

Extracted pic [6]

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.

Preemptive Scheduling with Process Priorities

Note: 

The Cmicro preemptive kernel is only available if the according license is available.

Figure 547 : Preemptive scheduling

Extracted pic [7]

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:

Figure 548 : Priority levels

Extracted pic [8]

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.

Rules

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.

Restrictions

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.

Create and Stop Operations

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.

Output and Input of Signals

The actions to perform an output in the generated code are as follows:

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.

Note: 

There are several possibilities to send signals to the environment by not using xOutEnv. The user should have a look at the #EXTSIG, #ALT and #TRANSFER directives which can be used in SDL Output. The one most similar to SDL, however, is the one which simply uses the C function xOutEnv.

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).

Nextstate Operation

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

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.

Decision and Task Operations

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.

Procedures

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.

Procedure Calls

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.


Example 455 : Procedure Call      

is translated to something like:


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.

Procedure Body

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.

Blocks, Channels and Signal Routes

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.

Targeting with the Cmicro Package

Directory Structure

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.

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.

Hint: 

Within the template directory there is a template makefile which must be used when compiling and linking the Cmicro Package.

On UNIX this template makefile is called makeoptions.

In Windows this template makefile is called make.opt.

Prerequisites

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.

Steps of Targeting -- Overview

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

Extracted pic [9]

All steps of targeting will be discussed in the following sub-sections.

Generate Cmicro C Code

Figure 550 shows the Organizer's Make dialog and its settings to generate Cmicro C code.

Figure 550  : Make dialog when generating Cmicro

Extracted pic [10]

The selections which must be set for Cmicro are the following:

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

sdl_cfg.h
the automatic configuration

<systemname>.c

the SDL system

<systemname>.ifc
the environment header file
<systemname>.m
the makefile
<systemname>.xrf
the X-References (not used)
<systemname>.sym
the symbol file (Cmicro Tester)

Manual Configuration with the BodyBuilder

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.

Copying Template Files

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.

Adapting the Makefiles

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.

The Template Makefile

There are the following variables to be defined in the template makefile.

Variable Description

sctEXTENSION

Extension of the executable (e.g. ".hex")

sctOEXTENSION

Extension of the objects (e.g. ".obj" or ".r03"

sctCC

Name of the Compiler executable

sctCCFLAGS

Compiler flags

sctCPPFLAGS

Compiler flags

sctLD

Name of the Linker executable

sctLD1FLAGS

Linker flags

sctLD2FLAGS

Linker flags

sctIFDEF

not used

CMICRO_DIR

Path to the Cmicro Package (e.g. $sdtdir/cmicro on UNIX, or %SDTDIR%\cmicro in Windows)

For each variable an example is given in the template itself. The user is asked to have a look into it.

Setting the Variables

Example 456 : Setting the Compiler and Linker for an IAR Compiler      

Description: (all the information given here will differ when using another compiler)

Hint:  Windows only

The linking and compilation in Windows is performed in a DOS environment. This means the command line got a maximum length of 128 characters. To prevent a command line overflow, the linker and compiler flags can be stored in separate files. A lot of compilers support the `-f' or `@'options to include such files.

Selecting the Target Executable

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.

As the default destination is defined as sctLINKKERNEL, the sctLINKKERNEL must be set as one of the above.

The Generated Makefile

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.


Example 457  : The makefile configuration file comp.opt      

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: !include make.opt

All the characters following the character `%' are special substitute characters. There are still others allowed than the ones shown in Example 457 above:

Sequence allowed in line Meaning

%n

1, 2, 3, 4

newline in the generated makefile

%t

1, 2, 3, 4

tabulator in the generated makefile

%d

1, 2, 3, 4

project/target directory

%c

2

name of generated c file (incl. extension)

%C

2

name of generated c file (excl. extension)

%o

2

name of the resulting object in compiler command (sctOEXTENSION is added)

%o

3

list of all object files in the linker command. I.e. list of generated files + sctLINKKERNEL)

%O

3

list of all object files in the linker command separated with backslash followed by newline. I.e. list of generated files + sctLINKKERNEL)

%e

3

name of executable file (sctEXTENSION is added)

%m

4

name of the generated makefile.

%k

1, 2, 3, 4

kernel directory (see Organizer's Make dialog "Use kernel in directory")

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.

Connecting the SDL Environment

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.

Note: 

All the modifications of env.c should only be done between the comments /* BEGIN User Code */ and /* END User Code */. All the other modifications will be lost when generating env.c anew. (Please view The Generated Environment)

Note: 

All the modifications of env.c should only be done between the comments /* BEGIN User Code */ and /* END User Code */. All the other modifications will be lost when generating env.c anew. (Please view The Generated Environment)

The compilation and linkage of the environment functions can be prevented by using the flags given in Compilation Flags.

Compiling and Linking

By the Organizer

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.

From the Command Line

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

Download and Execution

The target executable can now be downloaded and executed on the real target hardware.

Different Forms of Target Integration

Different forms of target integration, that is, integrating generated C code, are distinguished:

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

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:

The BodyBuilder will prompt during start-up if a needed file is missing.

Starting the BodyBuilder

On UNIX, the BodyBuilder simply needs to be started from the working (project) directory.

  1. Change the current directory to the project directory (assumed that this directory is ~/cmicro_project).
    cd ~/cmicro_project
  2. Now, type
    bodybuilder

Note: 

If the command bodybuilder is not found, the $path variable needs to be set up correctly. The user should ask his system administrator or the person that is responsible for the SDT environment.

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.


Extracted pic [12]

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

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

Extracted pic [13]

The Configuration 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

Extracted pic [14]

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.

The Configuration Field

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

Extracted pic [15]

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.

Hint: 

When you click an item, the selection will be toggled. When you click the same item with the right mouse button, the item will only be "selected" for getting help or having a look at its macro name. This makes it easy to get help without checking all the dependencies between the different items.

Using the BodyBuilder

Checking of Dependencies

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

Extracted pic [16]

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.

Target Configuration

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.

Communications Link Configuration

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.

C Compiler Selection

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.

Host Configuration

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.

The Menu Bar

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:

File Menu

The File menu contains the following menu choices:

Generate "env.c"

The environment template file env.c is re-generated. Please see The Generated Environment.

Set Directory

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.

Configure Menu

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:

Tools Menu

The Tools menu contains the following menu choices:

Figure 555  : The BodyBuilder's check dialog

Extracted pic [11]

The Log Window

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

Extracted pic [17]

File Menu

The File menu contains the following menu choices:

The menu choices are described in File Menu

The Generated Environment

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 /* BEGIN User Code */ and
/* END User Code */ only.

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.

The BodyBuilder's Definition Files

There are two files the BodyBuilder needs to get all dependencies of Cmicro Package's configuration possibilities.

  1. 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.
  2. 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.

Structure of the Definition File bodyconf.def

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.


Example 458 : Structure of the bodyconf.def Entries      

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

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:

  1. Flags defining the compiler
  2. Flags defining the properties of a compiler
  3. Flags defining the properties of the Cmicro Library
  4. Flags defining the implementation of a property

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:

Use the default settings of these flags in order to reduce potential problems.

Manual Scaling

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:

  1. Cmicro Kernel/Library
  2. Cmicro Tester
  3. Support of SDL Constructs
  4. SDL environment

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

Sometimes a flag just carries a value. In this case the user has to modify the value in ml_mcf.h

Cmicro Kernel/Library

Kernel

Initialization

Initial setting

set

Initial setting

set

Automatic set

XMK_USE_KERNEL_INIT

Kernel Limits

Initial setting

unset

Initial setting

unset

Initial setting

unset

Preemption

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

MAX_PRIO_LEVELS

xDefaultPrioProcess

XMK_USE_RECEIVER_PID_IN_SIGNAL

Reset

XMK_USE_CHECK_TRANS_TIME

Initial value

1

Depend on

XMK_USE_PREEMPTIVE

Caution! 

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 ErrorHandler() is called if the check fails.

Initial value

0

Depend on

XMK_USE_PREEMPTIVE

Others

Default setting

unset

Initial setting

unset

Initial setting

unset

Initial setting

unset

Initial setting

unset

Initial setting

unset

Reset

XMK_ADD_MICRO_RECORDER

Initial setting

unset

Signals

Signal Priorities

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.

Initial setting

unset

Automatic set

xDefaultPrioSignal

XMK_CREATE_PRIO

Reset

XMK_USE_xmk_SendSimple

Initial value

100

Depend on

XMK_USE_SIGNAL_PRIORITIES

Initial value

1

Depend on

XMK_USE_SIGNAL_PRIORITIES

Signal Structure

Initial setting

set

Initial setting

set

Initial value

4

Signal Handling

Initial setting

set

Reset

XMK_USE_SIGNAL_PRIORITIES

Initial setting

unset

Signal Queue

Initial setting

set

Reset

XMK_USE_STATIC_AND_DYNAMIC_QUEUE

Initial setting

unset

Reset

XMK_USE_STATIC_QUEUE_ONLY

Initial value

20

Note: 

Using dynamic memory allocation does not prevent the user from estimating the required memory for the queue. Sooner or later problems arise (e.g. memory fragmentation) if dynamic memory management is used frequently. For this reason the Cmicro Package avoids where possible the use of dynamic memory management.

Timers

If there are timers used within the SDL system, the timers have to be scaled.

Initial setting

unset

Initial value

100

Initial value

100

Timer queue

Initial value

set

Initial value

unset

Initial value

20

Error Checks

Error Handling

Initial setting

set

Reset

XMK_USE_MIN_ERR_CHECK

XMK_USE_NO_ERR_CHECK

Initial setting

unset

Reset

XMK_USE_MAX_ERR_CHECK

XMK_USE_NO_ERR_CHECK

Initial setting

unset

Reset by

XMK_USE_MAX_ERR_CHECK

XMK_USE_MIN_ERR_CHECK

Initial setting

unset

Initial setting

unset

Automatic set

XMK_ADD_STDIO

Reactions on Warnings

Initial setting

set

Reset

XMK_WARN_ACTION_PRINTF

XMK_WARN_ACTION_USER

Initial setting

unset

Reset

XMK_WARN_ACTION_HANG_UP

XMK_WARN_ACTION_USER

Initial setting

unset

Reset

XMK_WARN_ACTION_HANG_UP

XMK_WARN_ACTION_PRINTF

Initial setting

user_function()

Reaction on Errors

Initial setting

set

Reset

XMK_ERR_ACTION_PRINTF

XMK_ERR_ACTION_USER

Initial setting

unset

Reset

XMK_ERR_ACTION_HANG_UP

XMK_ERR_ACTION_USER

Initial setting

unset

Reset

XMK_ERR_ACTION_HANG_UP

XMK_ERR_ACTION_PRINTF

Initial setting

user_function()

Execution Time

Initial setting

unset

Automatic set

XMK_TRANS_TIME

Initial value

20

Depend on

XMK_USE_CHECK_TRANS_TIME

Cmicro Tester

Initialization

Initial setting

unset

Automatic set

XMK_USE_MAX_ERR_CHECK

Reset when unset

XMK_ADD_MICRO_COMMAND,

XMK_USE_DEBUGGING,

XMK_ADD_PROFILE,

XMK_ADD_MICRO_ENVIRONMENT,

XMK_WAIT_ON_HOST,

XMK_ADD_SDLE_TRACE,

XMK_ADD_SIGNAL_FILTER,

XMK_USE_COMMLINK,

XMK_ADD_MICRO_TRACER,

XMK_ADD_TEST_OPTIONS,

XMK_USE_SIGNAL_TIME_STAMP,

XMK_ADD_MICRO_RECORDER

Initial setting

unset

Depend on

XMK_ADD_MICRO_TESTER

Initial setting

unset

Depend on

XMK_ADD_MICRO_TESTER

Initial setting

unset

Depend on

XMK_ADD_MICRO_TESTER

Initial setting

unset

Depend on

XMK_ADD_MICRO_TESTER

Initial setting

unset

Depend on

XMK_ADD_MICRO_TESTER

Trace

Trace Scaling

Initial setting

unset

Depend on

XMK_ADD_MICRO_TESTER

Reset when unset

XMK_USE_SIGNAL_TIME_STAMP

Initial setting

unset

Depend on

XMK_ADD_MICRO_TESTER

Initial setting

unset

Depend on

XMK_ADD_MICRO_TESTER

Initial setting

unset

Depend on

XMK_ADD_MICRO_TESTER

Initial setting

unset

Depend on

XMK_ADD_MICRO_TESTER

Initial setting

unset

Depend on

XMK_ADD_MICRO_TESTER

Reset when unset

XMK_ADD_REALTIME_PLAY

Initial value

40

Buffers

Initial value

20

Initial value

100

Initial value

20

Initial value

100

Recorder and Play

Note: 

The Cmicro Tester's Record and Play functions are only available if a Cmicro Recorder license is available.

Initial setting

unset

Depend on

XMK_ADD_MICRO_TRACER

Reset when unset

XMK_ADD_REALTIME_PLAY

Initial setting

unset

Automatic set

XMK_USE_SIGNAL_TIME_STAMP

Depend on

XMK_ADD_MICRO_RECORDER

Support of SDL Constructs

Predefined Sorts

Character Strings

Initial setting

set

Reset by

XNOUSEOFCHARSTRING

Caution! 

The Cmicro Recorder is not able to handle SDL charstrings within signal parameters.

Initial setting

set

Reset by

XRESTUSEOFCHARSTRING

Initial value

50

Predefined Sorts

Initial setting

set

Initial setting

set

Note: 

Every multiplication of an integer value with an integer value is mapped to a multiplication of a real value with a real value. This is done because an overflow cannot be detected when using integer values.

ASN.1 Sorts

Initial setting

set

Depend on

XNOUSEOFCHARSTRING

Initial setting

set

Depend on

XNOUSEOFASN1

Initial setting

set

Depend on

XNOUSEOFASN1

Error Checks

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

Size of Variables

Initial setting

set

Initial setting

set

Initial setting

unset

Use of Memory

Memory Management

Initial setting

unset

Reset when unset

XMK_USE_memshrink

Initial setting

unset

Initial setting

unset

Depend on

XMK_USE_SDL_MEM

Initial setting

unset

Initial setting

unset

Initial value

8

Depend on

XMK_USE_SDL_MEM

Initial value

64

Depend on

XMK_USE_MIN_BLKSIZE

Initial value

1024

Depend on

XMK_USE_SDL_MEM

String Functions

Initial setting

unset

Initial setting

unset

Initial setting

unset

Initial setting

unset

SDL environment

Initial setting

set

Initial setting

set

Initial setting

set

Initial setting

set

Initial setting

unset

Automatic set

XNOMAIN

Initial setting

unset

Reset when unset

XMK_ADD_PRINTF

Automatic Scaling Included in Cmicro

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.

Automatic Dimensioning in Cmicro

Some resources of the Cmicro Library are automatically dimensioned. These are described in the following subsections.

Adaptation to Compilers

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:

List of Available C Compilers in ml_typ.h

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:

Compilation switch Meaning

_GCC_

The GNU C++ compiler for workstations

GNU80166

The GNU UNIX C compiler for Siemens 80C166 microcontrollers

TCC80166

The BSO/Tasking DOS C compiler for Siemens 80C166 microcontrollers

TCC80C196

The BSO/Tasking DOS C compiler for INTEL 80196 microcontrollers

IARC51

The Archimedes/IAR UNIX C compiler for INTEL 8051 microcontrollers

IARC6301

The Archimedes/IAR DOS C compiler for Hitachi 6301 microcontrollers

KEIL_C51

The Franklin/Keil DOS C compiler for INTEL 8051 microcontrollers

KEIL_C166

The Franklin/Keil DOS C compiler for Siemens 80166 microcontrollers

TMS320

MSP58C80

The Texas Instruments DOS C compiler for TMS 320C2x/C5x microcontrollers

IARC7700

The Archimedes/IAR DOS C compiler for Melps 7700 microcontrollers

HYPERSTONE

Hyperstone 5.07 C compiler with HyRTK real-time kernel

MCC68K

The MicroTech DOS C compiler for Motorola 68k microprocessors

MICROSOFT_C

The Microsoft C++ compiler

BORLAND_C

The Borland C++ compiler

ARM_THUMB

The Thumb compiler for ARM microcontrollers

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.

Introducing a New C Compiler

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.

Handling of User Defined C Compilers

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.

Caution! 

After installation of a new SDT release, the contents of the files that are stored with the BodyBuilder are not guaranteed to remain.

Adding a New C Compiler to the SDT Installation

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:

Caution! 

After installation of a new SDT release, the contents of the files that are stored with the BodyBuilder are not guaranteed to remain.

Do the C Compiler Adaptations

Creating a New user_cc.h File

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:

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 */

Yes

#define XCONST const

No

#undef XCONST

Yes

#define XMK_UNIX

No


Yes

#define XMK_WINDOWS

No


Defining the SDL System Time Functions in mk_stim.c

The following functions exist in the module mk_stim.c:

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.

Bare Integration

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.

Implementation of Main Function

The user may decide to implement his own main() function 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:


Example 459       

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:

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:

Integrating Hardware Drivers, Functions and Interrupts

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.

Critical Paths in the Cmicro Library

As with every real time application the Cmicro Library has to deal with critical paths.

Figure 557 : Critical paths

Extracted pic [18]

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.

Caution! 

When it comes to implementing the interrupt handling routines it is of the greatest importance to know about the Cmicro Library's handling of critical paths. Unpredictable results may result from a careless implementation!

Initializing the Environment / Interface to the Environment

xInitEnv()

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).

Receiving Signals from the Environment

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:

  1. Polling external events.
    This is done by the C function xInEnv(), which is called by the Cmicro Kernel after each transition.
  2. Directly sending signals into the SDL system.
    For example directly in an interrupt service routine. This is possible by using the XMK_SEND_ENV() function. This function directly operates on the SDL queue.

Caution! 

For each signal sent into the system, the user must ensure that the addressed receiver process instance exists. Each pid value is checked for consistency by the Cmicro Kernel. In the case of an inconsistency the ErrorHandler() is called with an error message.

xInEnv()

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.

Note: 

There is a file called <systemname>.ifc, which is generated by the Cmicro Code Generator. It is necessary to include this file together with ml_typ.h before defining xInEnv(). This is necessary to have access to all the objects that are generated by the Cmicro Code Generator. The user should also make sure that this file is generated, because the analyzer's make menu contains an option for this.


Example 460 : 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):


Caution! 

The function xInEnv() contained in the file env.c is generated by the BodyBuilder. To make sure that changes done by the user will not be lost when generating again it is allowed to modify this file only between the comments /* BEGIN User Code */ and
/* END User Code */.

Furthermore it is not allowed to remove these comments or to add similar at other places which could especially happen when copy and paste is used during editing.

XMK_SEND_ENV()

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.

Sending Signals to the Environment

There are several possibilities to send signals to the environment:

  1. Using simple SDL output.
    The Cmicro Kernel is involved in the output operation.
  2. Using the #EXTSIG directive in the SDL output.
    The user can define his own output operation, like writing to a register in a single in-line-assembler command.
  3. Using the #ALT directive in the SDL output.
    A variant of alternative 2.

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.

xOutEnv()

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.

Note: 

There is a file called <systemname>.ifc, which is generated by the Cmicro Code Generator. It is necessary to include this file together with ml_typ.h before defining xOutEnv(). This is necessary to have access to all the objects that are generated by the Cmicro Code Generator. The user should also make sure that this file is generated, because the analyzer's make menu contains an option for this.

Evaluate the Signals's Sender

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.:


Example 461 : Evaluating the Process Type      

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.

Checking the Signal's Receiver

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.

Caution! 

In earlier version of the Cmicro Package the function xOutEnv() was called any time a signal was sent. I.e. the users had to ensure that signals to the environment are consumed in the environment by returning XMK_TRUE in xOutEnv().

Signal Parameters

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.

Return Values of xOutEnv()

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.

An Easy Example

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:


Example 462  : xOutEnv()      

Caution! 

The function xInEnv() contained in the file env.c is generated by the BodyBuilder (see The Generated Environment). To secure that changes done by the user will not be lost when generating again it is allowed only to modify this file between the comments /* BEGIN User Code */ and /* END User Code */.
Furthermore it is not allowed to remove these comments or to add similar ones at other places.

Inter-Processor-Communication

Note: 

If inter-processor-communication is to be performed, the user has to define a unique protocol between the communicating processors. In small applications with a restricted range, it might be enough to copy C structures, but usually this causes problems when it comes to redesigning the hardware.

Closing the Environment / the Interface to the Environment

xCloseEnv()

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.

SDL System Time Implementation

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.

Getting the Receiver of a Signal -- Using xRouteSignal

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.


Example 463 : Function xRouteSignal()      

Dynamic Memory Allocation

General

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.

Dynamic Memory Allocation Functions -- Compiler or Operating System

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:

Dynamic Memory Allocation Functions -- Cmicro

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.

Adaptations That Are to Be Made

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_CleanPool()

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.

xmk_GetOccupied()

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.

xmk_GetFree()

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.

xmk_EvaluateExp2Size()

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:

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:

The ?Memory Command

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:

The command presents the following output to the user:

The command is available only if XMK_USE_SDL_MEM and XMK_ADD_PROFILE are set.

User Defined Actions for System Errors -- the ErrorHandler

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:

In the case of an error message, either:

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.


Example 464 : Default implementation of ErrorHandler()      


Example 465 : ErrorHandler()      

List of Dynamic Errors and Warnings

Cmicro Kernel Errors

Cmicro Tester Errors

Light Integration

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.

Model

The execution model for an SDL system in a light integration can be sketched with the following meta code:

The model for what the SDL task does in a light integration can be sketched with something like:

Adaptations That Are to Be Made

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:

  1. How to start-up the SDL task.

  2. There usually must be a "CREATE_TASK" function call provided from the operating system. This function must be called in the users main() function or in the "INIT" process. To do so, there must also be a declaration like

    extern 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.
  3. How to initialize the environment.

  4. This is usually done in xInitEnv(), but probably outside SDL, this depends on what the user wants.
  5. How to translate and send signals from SDL to any other task.

  6. Usually, users must fill out the function 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.
  7. How to receive signals from any other task and when to translate the signal parameters.

  8. For the user it is an option to decide between the following both alternatives.

    As the first alternative, the user may decide to format the signal parameters first and then send the signal to the SDL task. In the SDL task, it is then not necessary to format the incoming parameters. A message that was read from the message queue can be sent to the SDL system with XMK_SEND_ENV() as usual.

    As the second alternative, the user may decide to first send the signal to the SDL task. In the SDL task, it is then necessary to format the incoming parameters after the message was read from the message queue, before the signal can be sent to the SDL system with XMK_SEND_ENV. Note again, that all necessary resources must have been created before use, e.g. message queue.
  9. How to implement timers in SDL.

  10. It should be possible to implement hardware timers, like it is described in Defining the SDL System Time Functions in mk_stim.c. A usual way is to increment a global variable (of type xmk_T_TIME) by using an operating system task or similar. An time overrun is automatically detected by the Cmicro Kernel as usual.
  11. How to shutdown the system (if necessary).

  12. There is no default way to shutdown, but usually it is enough to implement the xCloseEnv function and call it at an appropriate place. The next thing that is remaining is the Cmicro Tester. All the explanation which have been given for bare integration, are still valid. But an operating system Light Integration introduces the difficulty of reentrance. The most easiest way to use the Cmicro Tester in a light integration is to spend a communications interface exclusively for the Cmicro Tester. Note, that there might be some functions which are still required to be able to handle reentrance, like memset(), calloc(), malloc(), sprintf() ...
  13. How to compile and link.

  14. The basic procedures for compiling and linking are the same as in a bare integration. But the user must implement his own 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:
    This flag must be set in order to exclude the Cmicro Kernel's main() function. The main() function from the light_ex.c module may be used as an example.
    This must be undefined, as the 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.
    This must be undefined, because otherwise the xmk_RunSDL() C function is not declared appropriate.
    This must be defined in order to include the C functions xmk_SaveSignalsOnly() from mk_queu.c and xmk_NextTimerExpiry() from mk_tim1.c accordingly.

System Partitioning

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.

Model

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:

Specifying and Generating the Partitions

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:


Example 466 : File partition1.script      

The partition will then be translated into all the necessary files by invoking the analyzer like this:


Example 467 : Invoking the analyzer      

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:


Example 468 : How to invoke the Compiler for a partition      

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.

Adaptations That Are to Be Made

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.

Unique Identifiers

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:

In order to make an identifier unique in the system, the following definition is introduced:

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.

Restrictions

The following restrictions are introduced when partitioning is used:

File Structure

Description of Files

The Cmicro Library Functions and Definitions

sdl_cfg.h

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.

Caution! 

The file sdl_cfg.h always carries the same name, for each SDL system generated and is stored in the currently active directory (project or working directory). Inconsistencies arise if several systems are to be generated in the same directory. To avoid this situation, it is recommended to use different working directories for each SDL system. Otherwise, unpredictable results at run-time could result, as some required automatic scalable features may/may not have been compiled.

ml_typ.h

This file is the central header file in the Cmicro Package. It contains

sctpredg.h, sctpred.h and sctpred.c

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.

ml_err.h

This header file defines all error numbers used by the Cmicro Kernel, the Cmicro Library and the Cmicro Tester.

ml_mem.c

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_mon.inc

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.

ml_mon.c

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.

ml_*.h

Other header files which contain extern declarations of modules of the Cmicro Library.

The Cmicro Kernel

mk_main.c

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.

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 xmk_InitQueue() and is exported from the mk_queu.c module.

mk_user.c

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:

Central error handling routine is called each time an errors occurs.

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

mk_sche.c

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.

mk_outp.c

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.

mk_queu.c

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.

mk_tim1.c

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.

mk_stim.c

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

mk_cpu.c

This file also contains some hardware specific functions which should be seen as templates.

mk_*.h

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.

Functions of the Basic Cmicro Kernel

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

can be replaced with

which means to refer to a pointer to an object of the type xmk_T_CMD_QUERY_QUEUE_CNF.

Exported from env.c

xInitEnv

This function is called by the Cmicro Kernel during initialization of the
SDL system. The user may include initialization of the environment here.

xInEnv

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.

xOutEnv

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.

xCloseEnv

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.

Exported from mk_user.c

ErrorHandler

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.

WatchdogTrigger

Description:
If selected this function is called by the Cmicro Kernel each time an SDL transition is executed

Caution! 

Be sure, that the time-out used for the Watchdog is longer than the longest SDL Transition (in the case of non preemptive Cmicro Kernel). If the preemptive Cmicro Kernel configuration is used, then the Watchdog Trigger should not be used because the execution time of transitions cannot be calculated.

Exported from mk_main.c

xmk_InitSDL

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.

xmk_RunSDL

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:

Exported from mk_sche.c

xmk_StartProcesses

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).

xmk_ProcessSignal

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.

xmk_CreateProcess

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.

xmk_IsAnyProcessAlive

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.

xmk_InitPreemptionVars

The variables used in preemption are initialized.

xmk_DisablePreemption

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.

xmk_EnablePreemption

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.

xmk_FetchHighestPrioLevel

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.

xmk_CheckIfSchedule

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.

xmk_SwitchPrioLevel

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.

Exported from mk_outp.c

xmk_SendSimple

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.

xmk_Send

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.

XMK_SEND_ENV

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.

xmk_Determine_Receiver

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.

Exported from mk_queu.c

xmk_InitQueue

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.

xmk_FirstSignal

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.

xmk_NextSignal

The signal following the current signal is copied to the current signal. If there are no more signals, NULL is returned.

xmk_InsertSignal

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.

xmk_RemoveCurrentSignal

The signal which was currently processed is removed from the queue and inserted into the list of free signals.

xmk_RemoveSignalBySignalID

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.

xmk_RemoveTimerWithParameter

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.

xmk_IsTimerInQueue

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.

xmk_RemoveSignalsByProcessID

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.

xmk_AllocSignal

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.

xmk_FreeSignal

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.

xmk_TestAndSetSaveState

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.

xmk_QueueEmpty

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.

Exported from mk_tim1.c

xmk_InitTimer

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.

xmk_TimerSet

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:

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.

xmk_TimerReset

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.

xmk_TimerActive

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.

xmk_ChkTimer

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.

xmk_ResetAllTimer

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.

Exported from mk_stim.c

xmk_InitSystime

This function initializes the hardware timer and is to be filled out by the user.

xmk_DeinitSystime

This function de-initializes the hardware Timer and is to be filled out by the user.

xmk_SetTime

This function sets the system time to the given value time and is to be filled out by the user.

xmk_NOW

This function is used by

The current SDL system time is returned.

The function is to be filled out by the user.

Exported from ml_mem.c

xmk_MemInit

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.

xmk_Malloc

This function allocates one block of memory from the dynamic memory pool. It uses a first fit policy.

xmk_Calloc

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.

xmk_Free

This function is the counterpart of xmk_Malloc(). A memory block is de-allocated again.

xmk_Memshrink

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().

memset

This function is a template for the memset() implementation.

Caution! 

Take care when the preemption policy is utilized.

memcpy

This function is a template for the memcpy() implementation.

Caution! 

Take care when the preemption policy is utilized.

Exported from ml_mon.c

xmk_GetErrorClass

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.

xmk_MonError

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.

xmk_MonPID

Used for test purposes, free use.

xmk_MonHexSingle

Used for test purposes, free use.

xmk_MonHex

Used for test purposes, free use.

xmk_MonHexAsc

Function for test purposes, free use.

xmk_MonConfig

Function for test purposes, free use.

Exported from mk_cpu.c

xmk_PutString

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.

xmk_GetChar

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.

xmk_printf

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.

xAlloc

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.

xFree

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.

xAlloc_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.

xFree_SDL_Charstring

A template for the implementation to free allocated SDL Charstrings.

It is compiled only, if XNOUSEOFCHARSTRING is undefined

xAlloc_SDL_Bit_String

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.

xFree_SDL_Bit_String

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

Functions of the Expanded Cmicro Kernel

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.

Exported from mk_sche.c

xmk_GetProcessState

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).

xmk_SetProcessState

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.

xmk_GetProcessInstanceData

The function returns the address of the process instance data of the given process-PID, or XNOTEXISTENT, if the pid is not existent.

Exported from mk_outp.c

xmk_EnvSend

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.

Exported from mk_queu.c

xmk_SaveSignalsOnly

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.

xmk_QueryQueue

The function evaluates the current SDL-Queue-State and returns some information to the caller:

Exported from mk_tim1.c

xmk_NextTimerExpiry

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.

Caution! 

If the remaining time is to passed to an operating system call, the value of 0 may have special meaning.

xmk_QueryTimer

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:

Technical Data

These descriptions allow the user to estimate the required resources for the target executable. The following items are described:

Allocating Dynamic Memory

Introduction

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

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.

Signals with and without Parameters

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.

Timers

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.

Estimating the Required Memory

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.

ROM Occupation by the Generated Application without Cmicro Library Functions

RAM Occupation for the Generated Application without Cmicro Library Functions

For signals with more than 4 byte parameters, an additional memory block is allocated with the size of the parameter area.

ROM Occupation by the Functions and Tables of the Cmicro Library

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.

Static RAM Occupation by the Functions and Tables of the Cmicro Library

For the non preemptive Cmicro Kernel:

For a Cmicro Kernel using preemption an additional static memory occupation of 8 Bytes to 16 Bytes in the scheduler per priority level applies.

Stack and dynamic RAM-occupation by the Cmicro Library

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.

Performance

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:

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.

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:


[Previous] [Next] [Contents] [Index]