The section "Adaptation to Compilers" on page 2842 deals with the introduction of new compilers and machine platforms.
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.
----------------------------------------------------------------------- Caution! The file sdl_cfg.h always carries the same name, for each SDL system generated and is stored in the currently active directory (use pwd to determine). Inconsistencies arise, if several systems are to be generated in the same directory. To avoid this situation, use differ ent working directories for each SDL system, otherwise, unpredict able results at run-time could be observed, as some required auto matic scalable features may/may not have been compiled. -----------------------------------------------------------------------
xInitEnvInitializing the environment, the hardware (a serial link used for communication.)
xInEnvReceiving signals from the environment. This is the connection between the SDL system and its environment, direction environment into the SDL system.
xOutEnvSending signals to the environment. This is the direction from SDL system into the environment.
xCloseEnvClosing the environment, the counterpart to xInitEnv.
ErrorHandlerCentral error handling routine, is called each time an errors occurs.
MemErrorCentral error handling routine only for malloc in the ml_mem-module.
WatchdogTriggerHandling of a hardware watchdog.
The file is not contained in this version of the Cmicro Package.
---------------------------------------------------------------------- Note: If difficulties arise in adapting the Cmicro Package to your compiler or target, please contact your SDT distributor. ----------------------------------------------------------------------
The flag XMK_USE_IRQ should be set to notify the Cmicro Kernel of the need to lock critical paths.
The SDT Code-Generator generates code, so that this static structure is present in the generated code. This is good for debugging purposes.
The Cmicro Generator generates code, so that this static structure is not present in the generated code, in order to spare memory. To enable debugging of the generated code, C comments are generated. Please consult the subsection "GR References" on page 2795.
(*1) In SDL`92 several SDL systems can exist in parallel.
The values 250 to 255 are reserved for internal purposes, and must not be used for process type numbering. For small systems no hindrance is incurred.
The Cmicro Kernel assumes the above definitions.
In the generated code, the SDL values self, sender, parent and offspring, and variables of this type are represented by the typedef xPID. The intention is to have an SDL systemwide unique numbering of processes and their instances. This becomes necessary because of the Cmicro Code no longer containing the structure of the SDL system (system, block...). The typedef xPID is defined as
Example 329 processtype = EPIDTYPE(xPID_variable) processinstance = EPIDINST(xPID_variable) xPID_variable = GLOBALPID(processtype, processinstance)
When using the standard Cmicro Package, as delivered, then the values 0 and 250 to 255 are reserved for internal purposes. If the upper limit of 249 signals and timers is not enough, then the signal ID type has to be changed from unsigned char to unsigned int, thus allowing more than 60000 signals/timer to be handled. The user will have to redefine some fixed values used for internal purposes in the Cmicro Package when using more than these 249 signals and timers, too.
---------------------------------------------------------------------- Caution! The Cmicro Generator doesn't check for the upper limit of 249 sig nals being reached for a generated SDL system. The user will get no warning if, i.e.250 signals are used. Normally, SDL systems grow through their development and maintenance phases, and the user must secure, that this upper limit isn't reached. If more than 250 sig nals (timers + SDL signals) are required, set the signal ID type from unsigned char to unsigned int as described above. ----------------------------------------------------------------------
Example 330 : Code generated for signals and timers #define znnn_SignalName 1 #define znnn_SignalName 2where znnn_ is the automatically generated prefix, required to cope with the SDL scope rules. Remember, that processes in SDL can have the same name as signals, states etc. Prefixing, however, ensures uniquely named SDL objects in the generated C Code.
Example 331 :When it comes to connecting the environment to the SDL system, the automatic numbering of signal IDs and timer IDs may not be required. If you want to prevent the automatic numbering of signals, then it is possible to #include a file containing all the signal and timer numbers. The file may contain something like:
A system with 2 signals S1 and S2, and a timer TIMER1 #define z049_TIMER1 1 #define z050_S1 2 #define z051_S2 3
#undef SignalOrTimerName #define SignalOrTimerName AnyValueAccordingToKernelRules
For some purposes, it may be necessary to give signals and timers and process types a fixed, user defined identification. This makes it possible, for example to identify such objects in the environment handling C functions xInEnv and xOutEnv. For processes, manual numbering is normally not necessary.
Firstly the user has to ensure, that no prefixes are generated for these objects. This can be done object by object, when using the #NAME directive in SDL as follows:
Example 332 : Using #NAME directive signal ThisismySignal /*#NAME `ThisisaSignal' */The following line appears in the generated code.
#define ThisisaSignal <anydecimalnumber>Another possibility for the non augmentation of prefixes to SDL objects is to modify the option settings in the Analyzer menu.
Secondly, for environment signals, (i.e. signals that are swapped between the SDL system and the environment) which are to be used in the module containing the C functions xInEnv and xOutEnv, the user has to include the generated environment header file in the module which contains the necessary definitions of the SDL entities at the system level. The generated environment header file is automatically named <systemname>.ifc by the analyzer.
The following C code generation is supplied for the header-section of the generated C-file(s).
For each SDL-process:
#define znnn_State1Name 1 #define znnn_State2Name 2 .... #define znnn_State3Name 3 Example 333 For a process with 2 states S1 and S2: #define z020_S1 #define z021_S2These values are used in the state-index-table and in the generated C-functions, whereever a nextstate is referenced.
typedef struct { #ifdef XMK_USE_RECEIVER_PID_IN_SIGNAL xPID rec; /* Receiver process */ #endif xmk_T_SIGNAL signal; /* Signalcode */ #ifdef XMK_USE_SIGNAL_PRIORITIES xmk_T_PRIO prio; /* Priority */ #endif #ifdef XMK_USE_SIGNAL_TIME_STAMP xmk_T_TIME time_stamp;/* Timestamp */ #endif #ifdef XMK_USE_SENDER_PID_IN_SIGNAL xPID send /* Sender process */ #endif #ifdef XMK_USED_SIGNAL_WITH_PARAMS xmk_T_MESS_LENGTH mess_length; union { void *ParPtr; #if (XMK_MSG_BORDER_LEN > 0) unsigned char ParCopy[XMK_MSG_BORDER_LEN]; #endif } ParUnion; #endif } xmk_T_MESSAGE;
------------------------------------------------------------------- Note: This margin of XMK_MSG_BORDER_LEN bytes can of course be mod ified by the user to prevent dynamic memory allocation for any sig nal in the queue, or, to the opposite, to use dynamic memory alloca tion in each case. See the file ml_mcf.h to modify this. -------------------------------------------------------------------
typedef struct _T_E_SIGNAL { xmk_T_MESSAGE Signal; struct _T_E_SIGNAL *next; #ifdef XMK_USED_SAVE xmk_T_STATE SaveState; #endif /* XMK_USED_SAVE */ } T_E_SIGNAL ;
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.
If you define XMK_MSG_BORDER_LEN as 0, then for each signal, which has parameters, the C function malloc is called.
If you define XMK_MSG_BORDER_LEN to 127, then
Signal instances are sent using the C function xmk_Send or xmk_SendSimple. That function takes a signal and puts it into the input port of the receiving process instance.
Figure 573 : Queueing - Sending side ----- (fig) -----There is no process ready queue. Physically, the queues of the different processes of the system are represented by one queue implemented as a C array scalable by XMK_MAX_SIGNALS. This define sets the upper limit of signals to be possible to queue at once. The array is used to build a linked list of signals currently in the system's queue. From an abstract point of view, this has no effect on SDL users, and is conform to the semantic rules of SDL. The scheduling simply depends on the ordering of signals in the queue. In the case of a so scaled preemptive Cmicro Kernel, there is one linked list of signals per priority level all using the array mentioned above. See the subsection "Scheduling" on page 2749 for details.
Figure 574 : Queueing - Receiving side ----- (fig) -----When working on a signal, the Cmicro Kernel decides between four different constellations:
After performing the nextstate operation, the input port is scanned, according to 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.
For each timer, there is a C structure defined in ml_typ.h.
typedef struct _TIMER { struct _TIMER *next ; xmk_T_SIGNAL Signal ; xmk_T_TIME time ; xPID OwnerProcessPID ; } TIMER ; xmk_T_TIME is defined as a long value.The componentFigure 575 : Handling of Timers (Timer Model 1) ----- (fig) -----
------------------------------------------- Note: Timers with parameters are not implemented. -------------------------------------------
The structures and tables for processes are described in detail in the subsection "Tables for Processes" on page 2785.
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 their 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 priority, is user-definable in the file ml_mcf.h. In this way it is possible to define signals with a high er priority as the create signal. The user should keep in mind not to do so! ---------------------------------------------------------------------------
Figure 576 : Non preemptive scheduling ----- (fig) -----
Figure 577 : Scheduling for create ----- (fig) -----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 578 Signal Priorities ----- (fig) -----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.
Figure 579 Preemptive Scheduling ----- (fig) -----SDL assumes the start transitions of all statically created processes 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 by the user, too, 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, some having to react very quickly to external events, others having 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 "Configurations / the File ml_mcf.h" on page 2762).
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 lowest priority value used in the system. Assume the following priority levels:
Figure 580 Priority levels ----- (fig) -----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. use of (x, N) declarations, where N > 1 these variables are only available once and not once per process instance. ------------------------------------------------------------------------
In order to produce portable C code, this version of the Cmicro Kernel uses recursive C function calls. A few C compilers available on the market do not support recursion. If such a C compiler is required, the user cannot use preemptive scheduling with process priorities.
Data of a process instance is represented by the following typedef structs:
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 non-existent 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 allo cation for process instance data. Some C-Defines are to be redefined in this case. ---------------------------------------------------------------------
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 (*1). 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 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" on page 2684 in chapter 44, The Cmicro Generator).
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: *1) There are several possibilities to send signals to the environ ment, by not using xOutEnv. Look to the #EXTSIG, #ALT and #TRANSFER-Directives, which can be used in SDL-Output. The most SDL-fashion like, 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).
The return-value either expresses
The signal which was currently 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.
For SDL decisions and for SDL tasks, C assignments and C function calls are implemented. Function calls are used in the case of having 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 you de fine C macros/defines instead of C functions for an ADT. Please consult the subsection "Abstract Data Types" on page 2622 in chap ter 44, The Cmicro Generator. ----------------------------------------------------------------------
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 subject for an ADT.
Procedures returning values are implemented also. 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.
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 C stack for the called procedure.
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 334 : Procedure Call TASK i := (call p(1)) + (call Q(i,k));is translated to something like:
i = p(1) + Q(i,k);An SDL procedure can be called more than once. No conflicts occur if using a preemptive Cmicro Kernel.------------------------------------------------------------------- Note: The value returning procedure calls are transformed to C functions returning values. -------------------------------------------------------------------
Within global procedures, no objects of the calling process can be used without declaring them via formal parameters. As another restriction, each output in a global procedure must be specified with to pid.
To implement a first main function, is possible by simply writing:
Example 335 main () { xmk_InitSDL (); xmk_RunSDL (0xff); }Of course, this example does nothing in order to start the Cmicro Tester. The only possibility to get a very simple trace output is to define:
#define XMK_ADD_PRINTFe.g., in ml_mcf.h. This inserts the C function printf at some places in the generated C code and the Cmicro Library.
In order to implement a trace output, please view the subsection "Example to set Trace Options" on page 3055 in chapter 46, The Cmicro Tester.
Figure 581 : Critical paths. ----- (fig) -----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).
The macros are expanded to calls to the C functions enable and disable if the flag XMK_USE_IRQ is set. The calls are counted using an internal variable, thus after having called XMK_BEGIN_CRITICAL_PATH n-times XMK_END_CRITICAL_PATH has to be called n-times, too, to enable the interrupts again.
In the Cmicro Library only these macros are used to disable/enable interrupts. The application should take care not to handle interrupts without using these macros or at least evaluating the internal counter.
The C functions enable and disable can be found in the module mk_cpu.c and should be implemented according to the application's needs.
--------------------------------------------------------------------- Caution! When it comes to implementing the interrupt handling routines it is of the greatest importance to know about the Cmicro Library's han dling of critical paths. Unpredictable results may result from a care less implementation! ---------------------------------------------------------------------
Alternative 1: Polling external events
This is done by the C function xInEnv, which is called
by the Cmicro Kernel after each transition.
Alternative 2: Directly sending signals into the SDL system, i.e. in an
Interrupt Service Routine (ISR), by using one of the
xmk_Send*( )-functions. These functions directly operate
on the SDL queue.
Important rule:
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.
Example 336 : 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 them. Then the user supplied C code should look like this:
void xInEnv (void) { static xPID receiver_in_SDL=process_pid; /* the above variable is to be filled up by hand, if */ /* possible, or by an signalling with the receiver of the */ /* hardwaresignal. */ /* a process_pid is only available, if the receiver- */ /* processtype has only 1 instance during runtime */ static state = 0; /* state, to detect changes in the hardwareregister */ if ((state==0) && (hw_register != 0)) { state = 1; data_len = 0; /* type integer */ p_data = (void *) NULL; /* pointer to parameters, NULL here */ XMK_SEND_ENV (REGISTER_TO_HIGH, xDefaultPrioSignal, data_len,
p_data, process_pid); /* It is also possible to give a higher */ /* priority here */ return; } if ((state==1) && (hw_register == 0)) { state = 0; data_len = 0;/* type integer */ p_data = (void *) NULL;/* pointer to parameters, here NULL */ XMK_SEND_ENV (REGISTER_TO_LOW, xDefaultPrioSignal, data_len,
p_data, process_pid); return; } return; } /* END OF SAMPLE */
Alternative 1:Using simple SDL output
The Cmicro Kernel is involved in the output operation.
Alternative 2:Using the #EXTSIG directive in the SDL output symbol
You can define your own output operation, like writing
to a register in a single in-line-assembler command.
Alternative 3:Using the #ALT directive in the SDL output symbol,
a variant of alternative 2
Alternative 1 is the most SDL like alternative, because it uses no non SDL constructs, like directives. This alternative should be selected, whereever possible, because it makes your diagrams more SDL conform and MSCs more readable.
Alternative 2 and 3 possibly are the more performant alternatives.
In the following, a way is described with alternative 1, because Alt.2/3 are already well described in the Cmicro Generator reference manual.
Each time, an SDL output of alternative 1 occurs, the Cmicro Kernel is called (C functions xmk_Send*). After performing some checks, the C function xOutEnv is called with all the parameters necessary to represent the signal, like receiver pid, priority, signal-ID, parameter length and a pointer to the parameter area.
The sender of the signal can be retrieved by the global variable xRunPID of the type xPID. Remember, in a system with only (x,1) process declarations, this pid represents the process type of the sender. In a system, where there is a minimum of one process declaration with (x, N), where N is >1, this pid represents the process type plus the process instance of the sender. Possibly 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 337 :Evaluating the Process Type unsigned char ptype; ptype = EPIDTYPE(xRunPID);Remember also, if it is required to signal to a specific pid in the environment, this requires a dynamic signalling, where a process in the environment establishes communication to a process in the system, or the other way around.
Normally, the destination of the receiver in the environment can be calculated from the id of the signal to be sent to the environment, in any case this is one of the simplest possibilities.
-------------------------------------------------------------------------- Note: If a signal with a given name exists at several channels / signal routes, and must also be sent to the environment, users must be aware to route it to the right receiver. The C function xOutEnv is called in any case, when a signal is to be sent, either internally, or to the environment. So, the user must take care to select the right re ceiver, by comparing the receiver id. Another possibility is to make signal names always unique for the whole SDL system. --------------------------------------------------------------------------If the signal to be sent to the environment contains parameters, it is then necessary to copy these parameters to the data area of the environment, see the example following.
------------------------------------------------------------------- Note: If interprocessorcommunication is to be performed, the user has to define a unique protocol between the communicating processors, or use an existing one, like ASN.1 and the Basic Encoding Rules (BER). In small applications with a restricted range, it might be enough to copy C structures, but mostly, this causes the first prob lems, when it comes to redesigning the hardware. -------------------------------------------------------------------In any case, a header file is to be included containing the signal and process identifications in the module which exports xInEnv and xOutEnv. Please view the subsection "Numbering SDL Objects by Hand" on page 2740.
Assume, for example, a process, which has to send a signal with parameters to the environment. The code, you then have to write into the mk_user- module, looks as follows:
Example 338 : xOutEnv() int xOutEnv (xmk_T_SIGNAL sig,
xmk_T_PRIO prio,
unsigned char data_len,
void *p_data,
xPID Receiver ) { int result = XMK_FALSE; switch (sig) { case SDL_Signal1 : /* Declaring a pointer to parameters */ ySig_SDL_Signal1 *p_signal1_parameters; p_signal1_parameters = (ySig_SDL_Signal1 *) p_data; /* define dest as a variable i.e.of type ySig_SDL_Signal1 */ /* to make it accessible in the environment, and perform */ /* the following default-setting of dest */ memset (dest, 0, sizeof (dest_type)); /* You must copy the signal parameters, i.e. */ /* copying simple values looks like : */ dest.p1 = p_signal_parameters->p1; dest.p2 = p_signal_parameters->p2; /* copying an inner structure or array looks like : */ /* ensure, if to use & or not : */ memcpy ([&] dest.pm, p_signal_parameters->pm,
sizeof(dest.pm)); /* do this for all parameters of the signal .... */ dest.pN = p_signal_parameters->pN; result = XMK_TRUE; break ; case SDL_Signal2 : result = XMK_TRUE; break ; default : result = XMK_FALSE; /* to tell the caller that the */ /* signal is NOT consumed, but is to * /* be handled by */ /* the Cmicro Kernel ... */ break ; } /* end of switch */ return (result); /* Note : Freeing of the signal takes place in
/* in the CmicroKernel */ /* Signalparameters are no longer valid
/* after returning from xOutEnv. */ } /* END OF SAMPLE */
The SDL_Halt () function is mapped to xCloseEnv () in Cmicro.
Some errors or warnings go undetectable 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" on page 2770.
For each error and warning, there should be an appropriate reaction in the function ErrorHandler in the mk_user-module. Errors are numbered easily by an integer value. If your 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 339 : ErrorHandler void ErrorHandler ( int ErrorNo ) { /* I.E.implement the 3 functions fatalerror,warning,and
/*information */ switch (ErrNo) { case ERR_N_UNKNOWN :fatalerror (ErrNo); break; case ..... ..... default :warning(ERR_N_UNKNOWN); break; } } /* END OF SAMPLE */
Figure 582 Structure of the generated C code ----- (fig) -----.All intricate details of the generated code are not described here. The depth of description is sufficient to give the reader a reasonable understanding of the code generation algorithms. Explanations will illustrate what the code looks like, but not why.
The generated code contains several places where prefixes are generated, which consists of a prefix and unique numbering. The following prefix is generated for all objects: "z<nnn>_", where nnn is an incremental number.
Allowance for conditional compilation occurs in several places throughout the generated code. The generated C code is conditionally compiled, for example, for dynamic process creation (create symbol). A differentiation is made between conditional compilations generated by the Cmicro Generator (called automatic scaling, prefix XMK_USED_) and conditional compilations, which are dependent on header files, which are to be modified by the user (called manual scaling, prefix XMK_USE_).
------------------------------------------------------------------- Note: Generically speaking, the ordering of the following subsections cor responds to the ordering, in which the code is generated. -------------------------------------------------------------------Each compilation unit is compiled either in one a.c file or into two files a.c and a.h.
Example 340 /* Program generated by Micro Generator, version x.x */ #define MICRO_C_x_x #include "sdl_cfg.h" #include "ml_typ.h"
#define SynonymName SynonymValue
extern void yAss_TypeName XPP(( TypeName *, TypeName , int ));
extern void yDef_TypeName XPP(( TypeName * ));
#define yDef_TypeName1(yVar) \ *(yVar) = DefaultExpression; #define yDef_TypeName2(yVar) \ yDef_TypeName3(yVar)The first macro is used in most circumstances, and the second is used for a syntype, without default value, of a structured type. In this case the default function for the base type is reused.
extern char * yWri_TypeName XPP(( void * ));
extern int yRead_TypeName XPP(( void * ));
extern SDL_Boolean yEq_TypeName XPP(( TypeName, TypeName ));
extern TypeName yMake_TypeName XPP(( ComponentTypeName ));
extern TypeName yMake_TypeName XPP(( Component1TypeName, Component2TypeName ))
#ifdef XTESTF extern xbool yTest_TypeName XPP(( TypeName )); #endif #ifdef XERANGE extern TypeName yTstA_TypeName XPP(( TypeName )); #else #define yTstA_TypeName(yExpr) yExpr #endif
#ifdef XEINDEX extern TypeName yTstI_TypeName XPP(( TypeName )); #else #define yTstI_TypeName(yExpr) yExpr #endifThe yTstA_TypeName and yTstI_TypeName are used to check the validity of an assignment to a syntype variable (yTstA_) and to check the validity of an index expression when indexing an array.
-------------------------------------------------------------------- Note: Note that the compilation flags XERANGE and XEINDEX determine if there should be test functions or if the macro versions, which only are substituted by the expression, should be used. --------------------------------------------------------------------The code for the yTstA_TypeName and yTstI_TypeName functions are shown in the subsection "Bodies from SDL Data Definitions" on page 2781 and their use is discussed in the subsection "Translation of SDL Expressions" on page 2809.
extern TypeName LiteralName XPP(( void ));
For an exported variable there will be one extra component to represent the currently exported value.
There will also be a component for each type of expression that is used in decisions, except for the types Integer, Real, Boolean, Character, PId. Take, for example, a decision with a Charstring question:
DECISION CharstringVar; ('abc') : ...; ELSE : ...; ENDDECISION;then there will be a component where the question value can be stored. Together with the struct type there will also be a pointer type to the struct type. In the example below we assume that the process has two formal parameters, FPAR_var1 and FPAR_var2, two variables, DCL_var1 and DCL_var2, and a decision where the question type is TypeName5.
typedef struct { PROCESS_VARS TypeName1 FPAR_var1; TypeName2 FPAR_var2; TypeName3 DCL_var1; TypeName4 DCL_var2; TypeName5 yDcn_TypeName5; } yVDef_ProcessName; typedef yVDef_ProcessName *yVDP_ProcessName;In a process type, all variables, formal parameters, and so on, from the all the inherited process types are included in the struct above, starting from the top of the inheritance chain.
------------------------------------------------------------------ Note: Note that fpars in create are not allowed in this Cmicro version. ------------------------------------------------------------------
DECISION CharstringVar; ('abc') : ...; ELSE : ...; ENDDECISION;then there will be a component where the question value can be stored. Together with the struct type there will also be a pointer type to the struct type
typedef struct { PROCEDURE_VARS TypeName1 FPAR_var1; TypeName2 *FPAR_var2; TypeName3 DCL_var1; TypeName4 DCL_var2; TypeName5 yDcn_TypeName5; } yVDef_ProcedureName; typedef yVDef_ProcedureName *yVDP_ProcedureName;where FPAR_var1 is assumed to be an in parameter, while FPAR_var2 is assumed to be an in/out parameter. Note that an in/out parameter is represented as an address. In a procedure, all variables, formal parameters, and decision variables, are included in the struct above.
Example of generated code for a struct called struct1 with two integer components a and b:
/*------------------DEFAULT-----------------*/ #ifndef XNOPROTO extern void yDef_z4_struct1( z4_struct1 *yVar ) #else extern void yDef_z4_struct1( yVar ) z4_struct1 *yVar; #endif { xDef_SDL_Integer(&((*yVar).a)); xDef_SDL_Integer(&((*yVar).b)); } /*------------------EQUAL-------------------*/ #ifndef XNOPROTO extern SDL_Boolean yEq_z4_struct1( z4_struct1 yExpr1, z4_struct1 yExpr2 ) #else extern SDL_Boolean yEq_z4_struct1( yExpr1, yExpr2 ) z4_struct1 yExpr1, yExpr2; #endif { if ( yNEqF_SDL_Integer(yExpr1.a, yExpr2.a) ) return SDL_False; if ( yNEqF_SDL_Integer(yExpr1.b, yExpr2.b) ) return SDL_False; return SDL_True; } /*-------------------MAKE-------------------*/ #ifndef XNOPROTO extern z4_struct1 yMake_z4_struct1( SDL_Integer ya, SDL_Integer yb ) #else extern z4_struct1 yMake_z4_struct1( ya, yb ) SDL_Integer ya; SDL_Integer yb; #endif { z4_struct1 yVar; memset((void *)(&yVar), 0, sizeof(z4_struct1)); yAssF_SDL_Integer(yVar.a, ya, XASSMAKE); yAssF_SDL_Integer(yVar.b, yb, XASSMAKE); return yVar; } /* #SDTREF(TEXT,mall.pr,7) */ COMMENT((This is the #body section))First the SortIdNode for this newtype or syntype is declared. This is followed by the IdNodes for struct components or literals (if valid).
After that the help function bodies are generated.
#ifndef XNOPROTO extern void yAss_TypeName ( TypeName *yVar, TypeName yExpr, int AssType ) #else extern void yAss_TypeName (yVar, yExpr, AssType) TypeName *yVar; TypeName yExpr; int AssType; #endif { code to perform assignment }
#ifndef XNOPROTO extern void yDef_TypeName( TypeName *yVar ) #else extern void yDef_TypeName( yVar ) TypeName *yVar; #endif { code to assign the default value to variable yVar }
#ifndef XNOPROTO extern SDL_Boolean yEq_TypeName( TypeName yExpr1, TypeName yExpr2 ) #else extern SDL_Boolean yEq_TypeName ( yExpr1, yExpr2 ) TypeName yExpr1, yExpr2; #endif { code to check if yExpr1 and yExpr2 are equal }
#ifndef XNOPROTO extern TypeName yMake_TypeName( ComponentTypeName yExpr) #else extern TypeName yMake_TypeName( yExpr ) ComponentTypeName yExpr; #endif { code to return an array with all components equal to yExpr }
#ifndef XNOPROTO extern TypeName yMake_TypeName( Component1TypeName yComponent1, Component2TypeName yComponent2 ) #else extern TypeName yMake_TypeName ( yComponent1,yComponent2 ) Component1TypeName yComponent1; Component2TypeName yComponent2; #endif { code to return a struct with value according to the parameters }
#ifdef XTESTF #ifndef XNOPROTO extern xbool yTest_TypeName(TypeName yExpr) #else extern xbool yTest_TypeName( yExpr ) TypeName yExpr; { code to check if yExpr is in the range conditions for this newtype or syntype } #endif #ifdef XERANGE #ifndef XNOPROTO extern TypeName yTstA_TypeName(TypeName yExpr ) #else extern TypeName yTstA_TypeName( yExpr ) TypeName yExpr; #endif { if (! yTest_TypeName(yExpr) ) { xErrorSubrange(ySrtN_TypeName, xWriteSort(&yExpr, ySrtN_TypeName)); return yExpr; } #endif
#ifdef XEINDEX #ifndef XNOPROTO extern TypeName yTstI_TypeName(TypeName yExpr ) #else extern TypeName yTstI_TypeName( yExpr ) TypeName yExpr; #endif { if (! yTest_TypeName(yExpr) ) { xErrorIndex(ySrtN_TypeName, xWriteSort(&yExpr, ySrtN_TypeName)); return lowest value of type; } return yExpr; } #endif
Example 341 : #ifndef XNOPROTO extern ResultTypeName OperatorName( ParameterType1 yParam1, ParameterType2 yParam2 ) #else extern ResultTypeName OperatorName (yParam1, yParam2) ParameterType1 yParam1; ParameterType2 yParam2; #endif { ResultTypeName Result; xPrintString( "Operator xx in sort xx is called\n"); xPrintOpParameter("Parameter 1: %s\n", &yParam1, ySrtN_ParameterType1); xPrintOpParameter("Parameter 2: %s\n", &yParam2, ySrtN_ParameterType2); if (! xReadOperator((void *)&Result, ySrtN_ResultTypeName)) yDef_ResultTypeName(&Result); return Result; }
Figure 583 : Root process table ----- (fig) -----
Example 342 : Code of Root Process TableC-Type definition (ml_typ.h)
extern xPDTBL yPDTBL []; /* for the Cmicro Kernel */ #define X_END_ROOT_TABLE /* Table-End Marker of yPDTBL */C-Constants (sdl_cfg.h)
#define MAX_SDL_PROCESS_TYPES <N> /* <Process-type-id's> Process Types are numbered */ /* from 0 to N-1(see chapter "Generating PID") */ #define XPTID_Process1Name 0 #define XPTID_Process2Name 1 #define XPTID_ProcessnName N-1C Code Generation for the whole system:
XPDTBL yPDTBL [MAX_SDL_PROCESS_TYPES+1] = { yPDTBL_ Process1Name, yPDTBL_ Process2Name, ...... yPDTBL_ ProcessnName, X_END_ROOT_TABLE }
The table is conditionally compiled, and only included, if the Cmicro Tester is contained in the target- executable.
The symbol trace table looks like:
Example 343 : Code for Symbol Trace Table /************************************************************* ** Symbol trace table *************************************************************/ #ifdef XMK_ADD_TEST_OPTIONS XSYMTRACETBL *xSYMTRACETBL[MAX_SDL_PROCESS_TYPES+1] = { (XSYMTRACETBL_ENTRY *) NULL, /* for first Processtype */ (XSYMTRACETBL_ENTRY *) NULL, /* for second Processtype */ ........ ........ (XSYMTRACETBL_ENTRY *) NULL, /* for last Processtype */ X_END_SYMTRACE_TABLE /* table end marker */ }; #endifMore information can be obtained by reading chapter 46, The Cmicro Tester.
------------------------------------------------------------------- Note: Timer model 2 is not contained in this version of Cmicro Package. Therefore the use of timers in this version is restricted to Timer model 1. -------------------------------------------------------------------
Example 344C Type Definition (ml_typ.h)
#ifdef XMK_USE_TIMER_ROM_TABLE typedef struct _XTIMER_ROM_TABLE_ENTRY { xPID Ownerprocess; xmk_T_SIGNAL timer_id; unsigned long timer_startval; unsigned int offset; } XTIMER_ROM_TABLE_ENTRY ; #define XDEFTIMER_ROM_TABLE_ENTRY(a,b,c,d) \ a, b, c, d, #define X_END_TIMER_ROM (xPID) 0xff #define MAXN 1 #endif /* ... XMK_USE_TIMER_ROM_TABLE */C Code Generation for the whole system:
/*-------------Timer ROM table--------------*/ #ifdef XMK_USE_TIMER_ROM_TABLE XCONST XTIMER_ROM_TABLE_ENTRY xTimerRomTable[MAX_SDL_TIMER_TYPES+MAXN] = { X_END_TIMER_ROM }; #endif /*-------------Timer RAM table--------------*/ #define MAX_SDL_TIMER_INSTS 0 #ifdef XMK_USE_TIMER_RAM_TABLE XTIMER_RAM_TABLE_ENTRY
xTimerRamTable[MAX_SDL_TIMER_INSTS+MAXI]; #endif
Example 345 :Instances of a given type are represented as a C array. The code generation of variables for each SDL process looks like:
Code Generation of type definition for each SDL process typedef struct { PROCESS_VARS TypeName1 FPAR_var1; TypeName2 FPAR_var1; TypeName3 DCL_var1; TypeName4 DCL_var2; TypeName4 yExp_DCL_var2; TypeName5 FPAR_var1; } yVDef_ProcessName;
Example 346 : #define X_MAX_INST_ProcessName upperlimitofprocessinstances1 static yVDef_ ProcessNameA reference to this array is generated in the Process Description Table, which is discussed in the subsection "Process Description Table" on page 2792.
yINSTD_ProcessName[X_MAX_INST_ProcessName];
Example 347 : Code for Process State TableC Typedef for the process state table (located in ml_typ.h)
typedef u_char xSTATE; /* see defines below */ #define XSTARTUP 0xff /* valid only if xSTATE is u_char, else*/C Code Generation for each process:
/* 0xffff */ #define XDORMANT 0xfe /* valid only if xSTATE is u_char, else*/
/* 0xfffe */
static xSTATE yPSTATETBL_znn_ProcessName [X_MAX_INST_znn_ProcessName] = { <creation-tag> /* Instance 0 */ <creation-tag> /* Instance 1 */ <creation-tag> /* Instance M-1 */ };where <creation-tag> is either XSTARTUP or XDORMANT.
Example 348 : for a process type with 4 instances, 2 of which are to be created at SDL system start: static xSTATE yPSTATETBL_znn_ProcessName [4] = { XSTARTUP, /* Create at SDL-system-start */ XSTARTUP, /* Create at SDL-system-start */ XDORMANT, /* Create later */ XDORMANT /* Create later */ };A reference to this table is created in the Process Description Table, which is discussed in the subsection "Process Description Table" on page 2792.
The C-Typedef for the transition table (located in ml_typ.h) is as follows:
Example 349 : Code for Transition Table typedef struct { xINPUT SignalID; /* Input, Asterisk-Input. Input is Timer */C-Codegeneration
/* and/or ordinary Signal */ xSYMBOLNR SymbolNr; /* Symbolnumber to be used */
/* in yPAD-function */ } xTR_TABLE_ENTRY;
static XCONST xTR_TABLE_ENTRY yTRTBL_znn_ProcessName [XMAX_TRANS_znn_ProcessName]= { /* state_0-table */ input_1, SymbolNr, input_2, SymbolNr, XASTERISK, XSAVEID /* asterisk save */ input_N, SymbolNr, /* state_1-table */ ............... ............... /* state_j-table */ input_1, SymbolNr, input_2, SymbolNr, input_N, trans_jN, XASTERISK, XSAVEID /* asterisk save */ };The SymbolNr shown above is used to select the right transition in the switch generated in the yPAD function.
Where the C-define
XASTERISK is an ID defining all possible SDL-Inputs (asterisk Inputs),
XSAVEID is a simple ID defined in ml_typ.h which can be compared by the SDL-Kernel to detect signal-save.
And where:
#define XASTERISK -1 #define XSAVEID xSaveA reference to this table is created in the "Process Description Table" on page 2792.
Example 350 : Code for State Index TableC-Typedef (ml_typ.h):
typedef u_char xSTATE_INDEX;C-Code Generation (Header of generated C-file):
static xCONST xSITBL xSTATE_INDEX_znn_ProcessName [<count_transitions_of_ProcessName] = { 0, /* i.e.a process with 3 states, but no asterisk states, */The first value in the above table indicates the beginning of the first state in the Transition Table. If asterisk state definitions are not found in the process, this value is 0.
/* state_0 has 2 transitions */ 2, /* state_1 has 5 transitions */ 7, /* state_2 has 3 transitions */ 10 /* table-end-index XI_TABLE_END */ };
A reference to this table is created in the Process Description Table.
Example 351 : Code for PID TableC-Type definition (ml_typ.h)
#ifdef XMK_USE_PID_ADDRESSING typedef struct { #ifdef XMK_USE_SDL_PARENT xPID Parent; #endif #ifdef XMK_USE_SDL_OFFSPRING xPID Offspring; #endif } xPIDTable; #endifC-Code generation for each process:
/*-----------Process-PID-Values-------------*/ #ifdef XMK_USE_PID_ADDRESSING static xPIDTable yPID_TBL_z00_P1[X_MAX_INST_z00_P1]; #endifA reference to this table is created in the Process Description Table, which is discussed in the subsection "Process Description Table" on page 2792.
Inspect the following diagram to see which information is contained in the process description table:
Figure 584 : Process Description Table ----- (fig) -----Allocated to each SDL-Process type is one table yPDTBL_ProcessName.
The type definitions of this table are located in the ml_typ.h-module.
Example 352 : Code for Process Description TableC-Typedef for the process description table (ml_typ.h)
typedef struct { #ifdef XMK_USE_PID_ADDRESSING xPIDTable *pPIDTable; /* Table with */C-Code generation for each process:
/* Parent/OffspringValues */ #endif xINSTD *pInstanceData ; /* Pointer to Instancedata */ /* Vector */ xINSTDLEN DataLength ; /* Length of Instancedata */ /* for 1 Instance */ /* (used by SDL-BS) */ unsigned char MaxInstances ; /* Max.Number of Instances */ #ifdef XMK_USE_TIMESLICE /* Time-Slices can be individually specified by the user */ /* The value stored in TimeSlice is measured in ticks */ /* The Cmicro Kernel has to be scaled to handle timeslicing */ xmk_T_TIMESLICE TimeSlice; #endif #ifdef XMK_USE_PREEMPTIVE /* Process-Priority can be specified with #PRIO on the */ /* SDL-Level. It is available only, if the Cmicro Kernel is */ /* scaled to handle preemption. */ xmk_T_PRIOLEVEL PrioLevel; /* Priority of this processtype */ #endif xmk_T_TRANS_ADDRESS yPAD_Function ; /* Address of the */ /* yPADFunction */ xTRTBL * TransitionTable ; /* Pointer to transition table */ xSITBL *StateIndexTable ; /* Pointer to state index table */ xSTATE *ProcessStateTable; /* Pointer to process state table */ } XPDTBL;
#define X_MAX_INST_ProcessName 1 xPDTBL yPDTBL_ProcessName = { yPID_TBL_znn_<process:N>,For each generated process description table, a new entry in the Root Process Table is generated.
(xINSTD*) yINSTD_znn_ProcessName, X_MAX_INST_znn_ProcessName, (xmk_T_TRANS_ADDRESS) yPAD_znn_ProcessName, yTRTBL_znn_ProcessName; xSTATE_INDEX_znn_ProcessName, yPSTATETBL_znn_ProcessName; };
Alternatively, C comments are generated which make it possible to verify and debug the generated code, as illustrated in the following example. The pr <position> indicates, in which line number of the SDL-PR file the symbol can be found.
For processes : /************************************************************* ** PROCESS <process-name> ** <<SYSTEM <system-name>/BLOCK <block-name>> ** #SDTREF(<reference>) *************************************************************/ For signals : /************************************************************* ** SIGNAL S1 ** <<SYSTEM <system-name>/BLOCK <block-name>> ** #SDTREF(<reference>) *************************************************************/ For yPAD-function /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ** Function for process <process-name> ** #SDTREF(<reference>) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ For output : /*----- ** OUTPUT <signal-name> ** #SDTREF(<reference>) ------*/ For nextstate : /*----- ** NEXTSTATE <state-name> ** #SDTREF(<reference>) ------*/
Procedures follow the same codegeneration as processes, with some small exceptions in macro naming conventions for variable declarations.
Each SDL process is represented in C by a C function called yPAD_ProcessName.
Example 353 : yPAD_ProcessName () /* Function for process ProcessName */ #ifndef XNOPROTO extern YPAD_RESULT_TYPE yPAD_ProcessName ( YPAD_ANSI_PARAM ) #else extern YPAD_RESULT_TYPE yPAD_ProcessName ( YPAD_KR_PARAM ) YPAD_KR_DEF #endif { local variable section State-input-selection { start-transition including nextstate transition-1 including nextstate transition-2 including nextstate ....... transition-n including nextstate } pad-end-section } /* Function for procedure ProcedureName */ #ifndef XNOPROTO extern YPRD_RESULT_TYPE yPAD_ProcedureName ( YPRD_ANSI_PARAM ) #else extern YPRD_RESULT_TYPE yPAD_ProcedureName ( YPRD_KR_PARAM ) YPRD_KR_DEF #endif { local variable section section representing procedure body }
Example 354 YPAD_YSVARP /* used for signal variable pointers */ YPAD_YVARP(yVDef_z00_P1) /* used for process variables */ YPAD_TEMP_VARS /* used for temporary variables */ YPRSNAME_VAR("P1") /* can be used for printf */ BEGIN_PAD /* used for some preparations */ /* to handle signals, or Integration */ /* of any Realtime operating system */After expansion by the C-Preprocessor:
yVDef_z00_ProcessName *yVarP =(yVDef_z00_ProcessName *)pRunData; unsigned char *yOutputSignal; unsigned char *ySVarP; (void) printf(("PROCESS:%s\n", "ProcessName")); if ((P_MESSAGE != ((void *) 0)) && (P_MESSAGE->mess_length > 4 )) { ySVarP = (unsigned char *) P_MESSAGE->mess_ud.pt_ud; } else { ySVarP = (unsigned char *) P_MESSAGE->mess_ud.ud; }The following defines are generated in the local variables section for procedures
YPRD_YSVARP /* used for signal variable pointers */ YPAD_YVARP(yVDef_znnn_ProcessName) /* used for process variables */ YPRD_YVARP(yVDef_znnn_ProcedureName) /* used for procedure variables */ YPRD_TEMP_VARS /* used for temporary variables */ YPRDNAME_VAR("P1") /* can be used for printf */After expansion by the C-Preprocessor:
extern void znn_ProcedureName ( unsigned char * _xxptr ) { yVDef_znn_ProcedureName * yVarP =(yVDef_ProcedureName *) pRunData; unsigned char * yOutputSignal; yVDef_znn_ProcedureName * yPrdVarP=(yVDef_znn_ProcedureName *) _xxptr ; SDL_Boolean yDcn_SDL_Boolean ; (void) printf ("PROCEDURE %s\n", "ProcedureName"); ; ; ..... }
The appropriate transition is selected by the following switch:
switch (XSYMBOLNUMBER) { { case 0:. start-transition nextstate; case 1: transition-1 nextstate; }After precompiling it:
switch (_xSymbolNumber_ ) { ..... }
Assignment of initialization values to all local variables in the processes and procedures (if any) is executed. All DCL variables are filled with their default-values.
The start transition is selected by the special case-value zero in the switch-statement of the yPAD function.
--------------------------------------------------------------- Note: FPARS in dynamic process creation are not contained in this ver sion of the Cmicro Package. ---------------------------------------------------------------
END_PAD (yPAD_ProcessName);The main reason for this is to make it possible to integrate other real-time operating systems.
---------------------------------------------------------------------- Note: Some compilers produce a warning, if there is no return at the end of the yPAD function, other compilers produce a warning "unreach able code", if there is a return at the end of the yPAD function. For this reason, a function returning macro END_PAD exists which can be expanded in accordance with the particular compiler used. ----------------------------------------------------------------------
The following actions are not contained in this version of the Cmicro Package:
Call, Export Return.
#ifdef XTRACE xTraceTask("VariableName := ..."); #endifIf the task contains informal text, the string is equal to the first informal text. If the task contains a #ID directive, the string contains the string specified in the directive.
After dealing with trace, the assignments and #CODE directives are handled in the order of occurrence. An SDL assignment is translated to an assignment in C or to a call of an assignment function, depending on the expression type.
One differentiation is made for signals without and signals with parameters. For a signal without parameters, suffix _NPAR is used for the macro generated, and for a signal with parameters, suffix _PAR is used. The relevant output macro can then be expanded to a simpler output C function called xmk_SendSimple, if no signal priority is used.
Another differentiation is made for signals which are sent to the system's environment or which are sent internally in the SDL system. The suffix _ENV is appended to the macros which are shown here, if the signal should go to the system environment.
The different directives, which can be used within SDT to modify outputs, are discussed in chapter 44, The Cmicro Generator, please view the subsection "Modifying Outputs - Directive #EXTSIG, #ALT, #TRANSFER" on page 2687.
The other different output situations, which are handled, will be described in the next subsections.
Output without to and without via
If you specify output SignalName without to and via in SDL, the Cmicro Generator calculates the receiver of the signal. It is also possible to have more than one receiver for the signal. During execution time, any of the living possible receivers will be selected, or, if no receiver can be found, the C function ErrorHandler will be called. The following code is generated:
ALLOC_SIGNAL_ppp (SignalNamewithoutPrefix, SignalNamewithPrefix, SignalParameterTypeStructureName)ordinary assignment of Signal Parameters, if there are some...
SDL_OUTP_ppp (Priority,After expansion, you will find a C function call to the xmk_SendSimple function or the xmk_Send function.
SignalNamewithoutPrefix, SignalNamewithPrefix, TO_PROCESS(ProcessNamewithoutPrefix, ProcessNamewithPrefix), SignalParameterTypeStructureName, "SignalNamewithoutPrefix")----------------------------------------------------------------- Note: The ppp above stands for either PAR or NPAR for a Signal with or without parameters. -----------------------------------------------------------------
Priority is generated as xDefaultPrioSignal, if no priority is specified for the signal with #PRIO.
TO_PROCESS is expanded to a function call, if there is at minimum one (x, N) declaration in the system, where N is > 1. This function returns one of the possible receivers of the signal.
TO_PROCESS selects an active instance of the given process type, it doesn't check for different types as receivers.
TO_PROCESS is expanded, so that the pid is passed directly to one of the C functions xmk_Send*, if there are only (x,1) declarations in the system.
If the environment is the receiver of the signal, then the following code is generated:
ALLOC_SIGNAL_ppp (SignalNamewithoutPrefix, SignalNamewithPrefix, SignalParameterTypeStructureName)ordinary assignment of Signal Parameters, if there are some...
SDL_OUTP_ppp_ENV (Priority, SignalNamewithoutPrefix, SignalNamewithPrefix, ENV, SignalParameterTypeStructureName, "SignalNamewithoutPrefix")After expansion, you will find, that ENV is passed to one of the C-functions xmk_SendSimple or xmk_Send. ENV is a special value used inside the Cmicro Kernel to detect, which signals are to be passed to the C function xOutEnv.----------------------------------------------------------------- Note: The ppp above stands for either PAR or NPAR for a Signal with or without parameters. -----------------------------------------------------------------
Output with to clause
If the user specifies: output SignalName to pid in SDL, the Cmicro Generator generates the following code:
ALLOC_SIGNAL_ppp (SignalNamewithoutPrefix, SignalNamewithPrefix, SignalParameterTypeStructureName)ordinary assignment of Signal Parameters, if there are some...
SDL_OUTP_ppp (Priority, SignalNamewithoutPrefix, SignalNamewithPrefix, pid-variable, SignalParameterTypeStructureName, "SignalNamewithoutPrefix")Expansion reveals a C function call to the xmk_SendSimple function or the xmk_Send function.----------------------------------------------------------------- Note: The ppp above either stands for PAR or NPAR for a Signal with or without parameters. -----------------------------------------------------------------
Priority is generated as xDefaultPrioSignal, if no priority is specified for the signal with #PRIO.
Possible generated values for pid-variable are SDL_SENDER, SDL_PARENT, SDL_OFFSPRING and SDL_SELF or an SDL pid variable. These values are passed to the xmk_Send* functions. The name of a process as specified in SDL may also be given.
Output with VIA-clause
The Cmicro Generator computes the possible receivers in an output with the via clause. If there are several possible receivers, an error message is produced.
If there is exactly one receiver, the same code is generated as for SDL output without to.
List of generated Output Macros
ALLOC_STARTUP_ppp (ProcessNamewithoutPrefix, ProcessNamewithPrefix, "ProcessNamewithoutPrefix, 0);....assignment of start-up values (cannot be used in this version of the
SDL_CREATE (ProcessNamewithoutPrefix, ProcessNamewithPrefix, "ProcessNamewithoutPrefix, 0, VariableofCreatedProcess, PriorityofCreatedProcess, yPAD-functionNameofCreatedProcess);PriorityofCreatedProcess is generated as----------------------------------------------------------------- Note: The ppp above stands for either PAR or NPAR for a Signal with or without parameters. -----------------------------------------------------------------
#ifdef XTRACE xDcn_SDL_Boolean = QuestionExpression; xTraceDecision (&(xDcn_SDL_Boolean), xSrtN_SDL_Boolean); if (xDcn_SDL_Boolean) #else if (QuestionExpression) #endif .... } else { .... }
The translation of set is, in order to produce effective code for a micro controller, restricted in a few areas. For example, the SDL duration expressed by a real value in the context of timers is not implemented. The reason for this is, that controllers do not have floating point operations or floating point operations are not used in order to increase the performance. For timers, such a high resolution is not necessary in most applications. The Cmicro Package uses a long value in its standard implementation, to represent absolute time.
Example 355If the following is specified in SDL-PR:
Timer TimerName; ...... ...... Set (now + durationvalue, TimerName) ;or,
Set (now + 22222, TimerName) ;then the following code is generated:
SDL_SET_DUR(xPlus_SDL_Time(SDL_NOW,SDL_DURATION_LIT (22222.0,22222,0)), SDL_DURATION_LIT(22222.0, 22222, 0), TimerName, TimerNamewithPrefix, yTim_timer2, "TimerNamewithoutPrefix") Example 356If the following is specified in SDL-PR:
Timer TimerName := TimerGroundValue ; ---> see Note below !then the following code is generated:
SDL_SET_TICKS (xPlus_SDL_Time(SDL_NOW,The code after expansion then contains a function call to
TICKS(SDL_INTEGER_LIT(22222))), TICKS( SDL_INTEGER_LIT(22222)), TimerName, TimerNamewithPrefix, yTim_timer2, "TimerNamewithoutPrefix")
xmk_TimerSet (TIMEEXPR,TimerNamewithPrefix).TIMEEXPR is the result of the evaluation of now plus duration value.
#define SDL_SET_DUR(TIME_EXPR, DUR_EXPR, TIMER_NAME, TIMER_IDNODE, TIMER_VAR, TIMER_NAME_STRING) \ xmk_TimerSet(TIME_EXPR, TIMER_IDNODE); #define SDL_SET_TICKS(TIME_EXPR, DUR_EXPR, TIMER_NAME, TIMER_IDNODE, TIMER_VAR, TIMER_NAME_STRING) \ xmk_TimerSet(TIME_EXPR,TIMER_IDNODE);Restrictions in the use of timers
set (now + 5.5, TimerName)is not allowed (the real part is discarded i.e. 5.5 (= 5).
If you specify in SDL-PR:
Reset (TimerName) ;then the following code is generated:
SDL_RESET (TimerNamewithoutPrefix, TimerNamewithPrefix, yTim_TimerName)The code after expansion contains a function call then to xmk_TimerReset (TimerNamewithPrefix).
----------------------------------------- Note: Timers with parameters are not supported. -----------------------------------------
ex_proc (....C parameters ...);All necessary parameters are routed via the C function call stack.
Example 357 : Procedure Call TASK i := (call p(1)) + (call Q(i,k));is translated to something like:
i = p(1) + Q(i,k);------------------------------------------------------------------- Note: The value returning procedure calls are transformed to C functions returning values. -------------------------------------------------------------------
SDL_NEXTSTATE(State1, z000_State1, "State1")after preprocessing:
return (z000_State1);
SDL_DASH_NEXTSTATEwhich is defined as:
return (XDASHSTATE);
goto L_LabelName
SDL_STOPwhich is defined as
return (XDORMANT);which is most code saving. The Cmicro Kernel then enters the new state value into the Process State Table.
------------------------------------------------------------------------- Note: This table contains ordinary SDL state values as well as the values XSTARTUP and XDORMANT. XSTARTUP is generated for each in stance, which is to be statically created (in (x, N) declarations, where x is > 0), XDORMANT is the value which is used to tag a process in stance as sleeping. In the case of creation this instance can be reused. -------------------------------------------------------------------------
#ifdef XFREEVARS FREE_PROCESS_VARS () #endif SDL_RETURNThe macro definitions are:
#define SDL_RETURN \ if (_xxptr != (unsigned char*) NULL) \ { \ MEM_FREE ((unsigned char *)_xxptr); \ } \ return ;where xxptr is the pointer to the procedure instance data, as given via the C function call parameter list. Note, that the memory previously allocated directly before the procedure call is freed at the end of the procedure, not outside of the procedure.
yTstA_TypeName(Expression)where yTstA_TypeName is either a consistency check function or a macro that replaces the macro call by only the expression itself.
yVarP->VariableName1 yPrdVarP->VariableName2 ((yVDP_ProcedureName)VarP->ActivePrd ->StaticFather)->VariableName3 (*(yPrdVarP->VariableName4))The examples are:
(*(SDL_Integer *)SDL_VIEW(SDL_PARENT, (xbool)1, "revVar", (xViewListRec *) &(((xBlockIdNode)XNAMENODE-> Parent)->ViewList[yView_z_predefined_6_revVar]), sizeof(SDL_Integer)))
#ifdef XMK_USED_SELF #define SDL_SELF xRunPID #endif #ifdef XMK_USED_PARENT #define SDL_PARENT pRunPIDTable->Parent #endif #ifdef XMK_USED_OFFSPRING #define SDL_OFFSPRING pRunPIDTable->Offspring #endif #ifdef XMK_USED_SENDER #define SDL_SENDER P_MESSAGE->send #endifAll the variables above are of type xPID. All variables are maintained by the Cmicro Kernel. xRunPID is a global variable which contains the pid of the SDL process which is currently running. P_MESSAGE is a pointer to the signal instance, which is currently worked on.
SDL_ACTIVE(TimerName, TimerName, yTim_TimerName)which is expanded to:
xmk_TimerActive(TimerName)A conditional expression in SDL is translated to a conditional expression in C.
The structure of the SDL system is not generated into the C-Code. What is seen in the generated code, is the behavior of the SDL system. Variables of processes are initialized during the start transition of a process, and no information about the structure of the SDL system is available during run-time in the generated code.
An initialization function is generated only in that case, if synonyms are used within SDL, which require an initialized C variable.
All this results in a more compact executable.
For example, the following use of an SDL synonym results in a generated initialization function:
synonym a := /*#CODE anyUserFunction () */The following C code is then generated within the C function yInit:
yInit is called by the Cmicro Kernel, if the define
XMK_USED_INITFUNCis generated into the file sdl_cfg.h.
A symbol table is necessary for the Cmicro Tester running on the host or the development system.
For more information consult chapter 46, The Cmicro Tester.
--------------------------------------------------------------------- Note: Possible SDL objects in this context are: process types, signals, tim ers, process states. ---------------------------------------------------------------------
Initialization is implemented within the C function yInit, which is conditionally compiled.
This means, that the Cmicro Kernel has its own memory management to handle processes, signals, and timers. This is done in 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 to handle 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.
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 MicroSoft C compiler version 8.0 for any 80x86 microprocessor, for a middle range SDL application with 15 processes.
Observe the example within the section "Example of Generated C Code" on page 2850. The execution time for this example, is, measured on a SPARC-10:
26.2 seconds for 1.000.000 times ping-pong.This means, that the time to handle 1 input and 1 output is about 13 microseconds.Or, in other words, in one second, it is possible to handle 77.000 signals.
When performed on a 80386-25 MHz DOS PC platform, using the DOS-command "time" the following performance results were recorded.
9 seconds for 30.000 times ping-pong.The last performance measurement is more inaccurate, as DOS-interrupts cannot be excluded.
The following result was observed on a SPARC 10 platform with the example modified, so that 50 parameters were ping-ponged, where each parameter was an integer:
81.2 seconds for 1.000.000 times ping-pong.
The switches used can be grouped:
Flag naming conventions:
------------------------------------------------- Note: You always have to generate the whole SDL-System. -------------------------------------------------
Not included in this version of the Cmicro Package.
int xmk_max_q_cnt,this represents queue-dimensioning and
int xmk_act_q_cnt,this represents the maximum traffic load of the queue, at any time during the execution.
Default: Undefined.
If you define XMK_USE_PREEMPTIVE, the Cmicro Kernel is configured, so that the preemptive scheduling policy is enabled. Each SDL process in the system is then interruptible, if for instance, an external signal is received from the environment, i.e.by means of an interrupt service routine. For a detailed description of what happens in this case see the chapters above.
Default: Not Defined.
Normally, the Cmicro Kernel is configured, so that the simple scheduling policy is used, i.e.Transitions of SDL processes are not interruptible (neither XMK_USE_PREEMPTIVE, nor XMK_USE_TIMESLICE is defined).
If you define XMK_USE_TIMESLICE, the Cmicro Kernel is configured, so that the scheduling policy is scaled to preemptive time slicing.
It is also possible to combine preemption through process priorities with preemption through time slicing.
Default: Not Defined.
If neither XMK_USE_SEND nor XMK_USE_SENDSIMPLE is defined, a compilation error occurs in the standard Cmicro Package.
Default: Defined.
Default: Defined.
Default: Defined.
Default: Defined.
Default: Defined.
Defining XMK_USE_SDL_SYSTEM_STOP means, that the C-function main returns correctly with exit (...). To avoid this overhead in the Cmicro Kernel, the user should un-define the above flag.
Default: Defined.
This flag should be used in combination with using the #PRIO directive. It works for all the different scheduling policies.
Default: Undefined.
This timestamp is especially used by the Cmicro Recorder in order to enable the replay of an SDL session in simulated real-time.
In other cases, the user is free to modify the kind of timestamp implementation.
Default: Undefined.
For a more detailed description see the section on translation of timer model 1/ timer model 2.
Default: Timer model 1 is defined.
Default: Defined.
Default: Undefined.
Default: Undefined.
Default: Defined depending on the current configuration.
Default: Undefined.
Default: Undefined.
Default: Defined.
Default: Defined.
Default: Defined, depending on the configuration selected with XMK_USE_CONFIG<nr>
Default: Defined, depending on the configuration selected with XMK_USE_CONFIG<nr>
Default: Undefined.
Default: Undefined.
Default: Undefined.
Default: Undefined.
Default: Undefined.
Default: Undefined.
Default: Undefined.
Default: Undefined.
Default: Undefined.
Default: Undefined.
Default: Undefined.
Default: Undefined.
Default: Undefined.
Default: Undefined.
Default: Different for each compiler definition section.
Default: Defined when PID addressing is used in SDL.
Default: Undefined.
Defining XMK_ADD_STDIO without setting XMK_ADD_PRINTF, allows the user to exclude the default printfs of the Cmicro Library, but implement user defined printfs.
Default: Defined
This flag must be undefined, when compiling into the target, except in the case, where there is a stdio implemented on the target, which is sometimes the case. For correct compilation, the user must also set XMK_ADD_STDIO. If the user wishes to implement user specific printf functionality then this flag need not be set.
Default: Defined.
Default: Defined, if Cmicro Tester enabled.
Default: Defined, if Cmicro Tester enabled.
<trace_event> is one of
CHECK_PARAMETERS, CREATE, DECISION,
DISCARD,DYNAMIC_CREATE etc...
The complete list is contained in the module ml_typ.h. All the flags are automatically set, if the Cmicro Tester is included. (please view chapter 46, The Cmicro Tester)
Default: Defined for enabled trace
Default: Defined in some situations
Default: Defined in some situations
Default: Defined in some situations
Default: Defined in some situations
Default: Defined in some situations
Default: Undefined.
Default: Defined in some cases.
Default: Defined in some cases.
Default: Defined.
Default: Defined.
Default: Defined.
One method is to use the Validator to calculate the maximum amount of entries in the queue. However the result can only be treated as an estimation, as the Validator uses a different scheduling policy than that of the Cmicro Kernel.
By examining the SDL system it can be determined which processes have a long transition time, and which processes send or receive more than one signal. Estimate by trying out worst case situations. A first estimation is also possible by calculating:
maximum amount of processinstances * 3For a more exact estimation the user should use the profiler contained in the Cmicro Tester to obtain the necessary information on how many entries are used during run time.
Another method of helping to determine the maximum amount of signals required by the system is to use the exception handling mechanism offered by the ErrorHandler. i.e. when the queue is full, and another signal is to be inserted then the ErrorHandler function is called.
------------------------------------------------------------------ Note: Using dynamic memory allocation does not prevent the user from estimating the required memory for the queue. Sooner or later prob lems arise (e.g. memory fragmentation), if dynamic memory man agement is used frequently. For this reason the Cmicro Package avoids where possible the use of dynamic memory management. ------------------------------------------------------------------Default: 20 entries.
If the user does not wish to employ automatic scaling facilities, for example, if test and debugging proves too difficult, then simply define the following flags as desired. This is possible if you use the separate header file"noscale.h" and define XMK_USE_NO_AUTO_SCALING.
All the flags discussed in this chapter are used on the whole SDL system i.e. it is not possible, to define flags for processes separately.
The save construct, although a useful construct for manipulation of the SDL FIFO queue mechanism, unfortunately requires much code overhead. The user should avoid the utilization of this construct where possible.
--------------------------------------------------------------------- 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. --------------------------------------------------------------------
If "to" in output actions is not used, none of the above flags is generated as defined.
The define XMK_USE_PID_ADDRESSING depends on the above flags.
MICROLIBRARY
+---- kernel
+---- tester
+---- sdtmt
+---- others
+---- scripts
+---- template
The scripts, makeoptions and makefiles delivered with this version assume the above structure.
------------------------------------------------------------------ Note: This directory structure should be considered as an template only. ------------------------------------------------------------------
The Cmicro Library is also contained as another entry in this file, as is seen below:
Example 358 : Content of the file $sdtdir/sdtsct.knl------------------------------------------------------------- Output in Kernel menu Compilation Flag Explanation ------------------------------------------------------------- Simulation SCTDEBCOM Monitor and communica tion Simulation-ansi SCTADEBCOM Monitor and communica tion RealTimeSimulation SCTDEBCLCOM Monitor, communica tion and real time RealTimeSimulation-ansi SCTADEBCLCOM Monitor, communica tion and real time ApplicationDebug SCTDEBCLENVCOM Monitor and, real time and the user's Env ApplicationDebug-ansi SCTADEBCLENVCOM Monitor and, real time and the user's Env PerformanceSimulation SCTPERFSIM No monitor included PerformanceSimulation-ansi SCTAPERFSIM No monitor included Application SCTAPPLCLENV No monitor but real time and the user's Env ApplicationDebug-ansi SCTADEBCLENVCOM Monitor and, real time and the user's Env Validation SCTVALIDATOR Validator Validation-ansi SCTAVALIDATOR Validator MICROLIBRARY MICROLIBRARY Cmicro Library including Kernel / Tester -------------------------------------------------------------
---------------------------------------------------------------- Caution! Do not generate and test libraries in the $sdtrelease directory structure. Create an appropriate copy. ----------------------------------------------------------------
---------------------------------------------------------------- Note: The environment variables sdtdir and sctdir need not refer to di rectories in $sdtrelease. Any directory containing the relevant files may be used. ----------------------------------------------------------------
For the Cmicro Package, there is one exception, no precompiled run-time library exists.
In principle, the Cmicro Library is newly scaled each time code is generated for the SDL system. After SDL to C code generation, the Cmicro Library is to be compiled again. This ensures, that the Cmicro Library always contains the functions needed by the SDL system generated.
------------------------------------------------------------------- Caution! The compilation of files in the Cmicro Library are always based on the file sdl_cfg.h, which is generated and written into the current ly active working directory. If a new sdl_cfg.h file is generated with new contents, or if the user has modified parts of the Cmicro Library, the Cmicro library should be re-compiled. -------------------------------------------------------------------
The file makeoptions includes all necessary dependencies to build a Cmicro Library.
#include $sdtdir/MICROLIBRARY/makeoptionsFirst, convert all necessary files from Unix format to DOS format:-
unix2dos filename newfilenameSometimes problems occur, if there are too many arguments to pass to the compiler (or any tool, which you use in the makefile-actions). DOS has a limited set of 128 characters in each command. Possibly this can be solved by using C libraries, which we strongly recommend in each case. Please modify the makefile as is required.
It is most important, that the objects built from the Cmicro Library are consistent with the objects compiled from the application.
---------------------------------------------------------------- Note: To be absolutely sure, recompile all C modules contained in the Cmicro Library. ----------------------------------------------------------------The makefile dependencies can be viewed in the file
#include $sdtdir/MICROLIBRARY/makeoptions
The make file is usually generated and executed by the SDT Organizer. Running the Analyzer stand-alone, the make file is however generated and executed by the Cmicro Generator.Below a make file generated for the SDT system Example is shown. This is generated by the Cmicro Generator. The make files generated by the SDT Organizer is similar but not exactly equal.
Example 359 : # makefile for System: Example include $(sctdir)/makeoptions default: Example$(sctEXTENSION) Example$(sctEXTENSION): Example$(sctOEXTENSION) $(sctLD) $(sctLDFLAGS) \ Example$(sctOEXTENSION) \ $(sctLINKKERNEL) \ -o Example$(sctEXTENSION) Example$(sctOEXTENSION): Example.c $(sctCC) $(sctCPPFLAGS) $(sctCCFLAGS) \ Example.c $(sctIFDEF) \ -o Example$(sctOEXTENSION)
The following parts may be changed:
-------------------------------------------------------- Compilation- Meaning switch -------------------------------------------------------- SOLARIS_CYGNU The CY-GNU C-Compiler for Solaris GNU80166 The GNU 80166 C-Compiler for Sun OS IARC51 The IAR 8051 C-Compiler KEIL8051 The Keil 8051 C-Compiler TMS320 The Texas Instruments C-Compiler for TMS 320C2x/C5x MSP58C80 The same as the Texas Instruments C-Com piler for TMS 320 MS_C_5_1 The MicroSoft C-Compiler 5.1 MS_C_8_0 The MicroSoft C-Compiler 8.0 BORLAND_3_1 The Borland C-Compiler 3.1 --------------------------------------------------------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.
Some changes are then necessary in the file mk_stim.c and mk_cpu.c, where the Cmicro Kernel is using direct hardware access.
If a tight integration with another real time operating system (RTOS), is to be carried out please ask your SDT distributor.
The remaining part of the code of the Cmicro Library should be compileable without performing any modifications. If you have problems with adapting a new compiler or hardware, please contact the supporter of this product.
The list of compilers will of course be extended as and when the necessary information on how to handle each particular compiler are obtained.
The following definitions are to be made in the compiler definition section of ml_typ.h:
#define XPP(x) x #define PROTO(x) x=>If not, define XNOPROTO
#define XPP(x) #define PROTO(x)
#ifdef XMK_ADD_STDIO #include <stdio.h> #endifDoes the operating system which is to be used after linking support Environment functions. This is argc and argv in the main function. If yes, then write:
#define XMK_USE_OS_ENVIRONMENT
#define XCONST constIf it is not, then undefine:
#undef XCONSTIn general, the compilers which are able to produce ROM-able code, can handle the keyword "const".
#define XMK_UNIXIf it is not, then undefine:
#undef XMK_UNIX
void xmk_InitSystime(void)Initialize the hardware registers to support the system time
void xmk_DeinitSystime(void)Give up to use the system time. This normally cannot happen, but in some applications, where the SDL system is stopped and restarted again during run-time, it may prove useful.
void xmk_SetTime(xmk_T_TIME)This function sets the system-time to the given value. Might be used for a hardware, which supports a hardware clock. Never called by Cmicro Kernel.
xmk_T_TIME xmk_NOW(void)This is the most important C function to handle SDL system-time. This function returns the absolute time, which is per default defined as a long value.
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 ISR, which clocks a global variable containing the absolute time. See the templates contained in the mk_stim- module.
Disable interrupts
void disable(void)Enable interrupts
void enable(void )These functions are used in the Cmicro Kernel, if it is scaled to preemption. Mostly, one has to implement the body of these functions by inserting assembler in-line code, but some compilers do have a library, which enables direct hardware access.
Some of the differences discussed in the following are of interest for SDL users, whilst others are not.
Cadvanced uses a process ready queue, together with signal queues, in order to schedule processes. Cmicro uses no process ready queue, so that all scheduling is derived from one physical queue. This physical queue represents all SDL process input ports.
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 process design, if the differences between Cadvanced and Cmicro make a difference as seen from black box view.
If no SDL process assumes a particular behavior from its communicating partner process then the behavior - as seen from a black box view - is always the wanted one.
In addition, the way to include the generated interface file (.ifc) is another one compared with the Cadvanced Generator.
The C module which contains the environment functions, should first
#include "<systemname>.ifc"when using Cmicro.
In general (for Cmicro as well as Cadvanced) four C functions are used to represent the SDL environment, namely
For Cmicro, each of the above C functions is compiled only, if it is wanted (selected by XMK_USE_xInitEnv, XMK_USE_xInEnv...)
Differences occur in the declaration of the C function xOutEnv. For Cmicro, xOutEnv carries a few parameters which represent the signal which is to be output to the environment, including the signal parameters. As a recommendation, the definition of the C function xOutEnv should be written twice, one for Cadvanced and one for Cmicro.
As another difference, signals and processes are identified in different ways. Cmicro doesn't use identifications like "xIdNode". Instead, it uses fixed C defines to identify signals and processes. This is good to reduce the amount of memory, but has the consequence, that each access to any signal and any process is to be implemented differently. The subsection "Numbering SDL Objects by Hand" on page 2740 gives more details of how identifiers are generated and can be used.
To compare the different layouts, the following subsections can be viewed:
Example 360 : system perf01; block B1; signal PING , PONG , PONG_SAY_BYE_BYE ; synonym MAXRUN integer = 10000 ; process PING (1, 1); signalset PONG, PONG_SAY_BYE_BYE; start; output PING ; nextstate State1 ; state State1; input PONG ; output PING ; nextstate - ; input PONG_SAY_BYE_BYE ; stop ; endprocess; process PONG (1, 1); signalset PING; DCL counter integer; start; TASK counter := 0 ; nextstate State1; state State1; input PING ; TASK counter := counter + 1; DECISION counter > MAXRUN ; (true) : output PONG_SAY_BYE_BYE ; stop ; (false) : output PONG ; nextstate - ; ENDDECISION ; endprocess; endblock; endsystem;As an example for generation without separation, the generated code now looks like this:
/* Program generated by Micro Generator, version x.x */ #define MICRO_C_x_x #include "sdl_cfg.h" #include "ml_typ.h" #include "ml_err.h" #define XPTID_z00_PING 0 extern XCONST XPDTBL yPDTBL_z00_PING; #define XPTID_z01_PONG 1 extern XCONST XPDTBL yPDTBL_z01_PONG; /************************************************************ ** SYNONYM MAXRUN ** <<SYSTEM perf01/BLOCK B1>> ** #SDTREF(SDL,b1.sbk(1),122(10,10),6) ************************************************************/ #define z05_MAXRUN SDL_INTEGER_LIT(10000) /*********************************************************** ** PROCESS PING ** <<SYSTEM perf01/BLOCK B1>> ** #SDTREF(SDL,ping.spr(1),110(3,10),1) ************************************************************/ extern YPAD_RESULT_TYPE yPAD_z00_PING XPP((YPAD_ANSI_PARAM)); typedef struct { PROCESS_VARS } yVDef_z00_PING; #define z000_State1 1 /*********************************************************** ** PROCESS PONG ** <<SYSTEM perf01/BLOCK B1>> ** #SDTREF(SDL,pong.spr(1),110(3,10),2) ************************************************************/ extern YPAD_RESULT_TYPE yPAD_z01_PONG XPP((YPAD_ANSI_PARAM)); typedef struct { PROCESS_VARS /* #SDTREF(SDL,pong.spr(1),149(5,25),2) */ SDL_Integer z011_counter; } yVDef_z01_PONG; #define z010_State1 1 /************************************************************ ** SIGNAL PING ** <<SYSTEM perf01/BLOCK B1>> ** #SDTREF(SDL,b1.sbk(1),122(10,10),2) *************************************************************/ #define z02_PING 1 /************************************************************ ** SIGNAL PONG ** <<SYSTEM perf01/BLOCK B1>> ** #SDTREF(SDL,b1.sbk(1),122(10,10),3) ************************************************************** / #define z03_PONG 2 /*********************************************************** ** SIGNAL PONG_SAY_BYE_BYE ** <<SYSTEM perf01/BLOCK B1>> ** #SDTREF(SDL,b1.sbk(1),122(10,10),4) ************************************************************/ #define z04_PONG_SAY_BYE_BYE 3 /*********************************************************** ** #CODE directives, #HEADING sections ************************************************************/ /********************************************************** ** #CODE directives, #BODY sections ************************************************************/ /********************************************************** ** Root Process Table ***********************************************************/ XCONST XPDTBL *xPDTBL[MAX_SDL_PROCESS_TYPES+1] = { &yPDTBL_z00_PING, &yPDTBL_z01_PONG, X_END_ROOT_TABLE }; /********************************************************** ** Symbol Trace Table ***********************************************************/ #ifdef XMK_ADD_TEST_OPTIONS XSYMTRACETBL *xSYMTRACETBL[MAX_SDL_PROCESS_TYPES+1] = { (XSYMTRACETBL_ENTRY *) NULL, (XSYMTRACETBL_ENTRY *) NULL, X_END_SYMTRACE_TABLE }; #endif /********************************************************** ** Timer table ***********************************************************/ /*-------------Timer ROM table--------------*/ #ifdef XMK_USE_TIMER_ROM_TABLE XCONST XTIMER_ROM_TABLE_ENTRY xTimerRomTable[MAX_SDL_TIMER_TYPES+MAXN] = { X_END_TIMER_ROM }; #endif /*-------------Timer RAM table--------------*/ #ifdef XMK_USE_TIMER_RAM_TABLE XTIMER_RAM_TABLE_ENTRY xTimerRamTable[MAX_SDL_TIMER_INSTS+MAXI]; #endif /********************************************************** ** PROCESS PING ** <<SYSTEM perf01/BLOCK B1>> ** #SDTREF(SDL,ping.spr(1),110(3,10),1) ***********************************************************/ /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ** Tables for process PING ** #SDTREF(SDL,ping.spr(1),110(3,10),1) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*--------------Instance Data---------------*/ #define X_MAX_INST_z00_PING 1 static yVDef_z00_PING yINSTD_z00_PING[X_MAX_INST_z00_PING]; /*--------------Process State---------------*/ static xSTATE yPSTATETBL_z00_PING[X_MAX_INST_z00_PING] = { XSTARTUP }; /*---------------State Index----------------*/ static XCONST xSITBL xSTATE_INDEX_z00_PING[2] = {0, 2}; /*---------------Transition-----------------*/ #define XMAX_TRANS_z00_PING 2 static XCONST xTR_TABLE_ENTRY yTRTBL_z00_PING[XMAX_TRANS_z00_PING] = { /* State1 */ z03_PONG, 1, z04_PONG_SAY_BYE_BYE, 2 }; /*-----------Process-PID-Values-------------*/ #ifdef XMK_USE_PID_ADDRESSING static xPIDTable yPID_TBL_z00_PING[X_MAX_INST_z00_PING]; #endif /*-----------Process Description------------*/ #define X_PRIO_z00_PING xDefaultPrioProcess XCONST XPDTBL yPDTBL_z00_PING = { #ifdef XMK_USE_PID_ADDRESSING yPID_TBL_z00_PING, #endif (xINSTD *)yINSTD_z00_PING, sizeof(yINSTD_z00_PING[0]), X_MAX_INST_z00_PING, #ifdef XMK_USE_TIMESLICE X_TIMESLICE_z00_PING, #endif #ifdef XMK_USE_PREEMPTIVE X_PRIO_z00_PING, #endif (xmk_T_TRANS_ADDRESS) yPAD_z00_PING, yTRTBL_z00_PING, xSTATE_INDEX_z00_PING, yPSTATETBL_z00_PING }; /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ** Function for process PING ** #SDTREF(SDL,ping.spr(1),110(3,10),1) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #ifndef XNOPROTO extern YPAD_RESULT_TYPE yPAD_z00_PING( YPAD_ANSI_PARAM ) #else extern YPAD_RESULT_TYPE yPAD_z00_PING( YPAD_KR_PARAM ) YPAD_KR_DEF #endif { YPAD_YSVARP YPAD_YVARP(yVDef_z00_PING) YPAD_TEMP_VARS YPRSNAME_VAR("PING") BEGIN_PAD switch (XSYMBOLNUMBER) { /*----- ** START ** #SDTREF(SDL,ping.spr(1),134(5,25),1) ------*/ case 0: BEGIN_START_TRANSITION /*----- ** OUTPUT PING ** #SDTREF(SDL,ping.spr(1),137(5,40),1) ------*/ ALLOC_SIGNAL_NPAR(PING, z02_PING, 0) SDL_OUTP_NPAR(xDefaultPrioSignal, PING, z02_PING, TO_PROCESS(PONG, z01_PONG), 0, "PING") /*----- ** NEXTSTATE State1 ** #SDTREF(SDL,ping.spr(1),140(5,55),1) ------*/ SDL_NEXTSTATE(State1, z000_State1, "State1") /*----- ** INPUT PONG ** #SDTREF(SDL,ping.spr(1),125(30,40),1) ------*/ case 1: XOS_TRACE_INPUT("PONG") /*----- ** OUTPUT PING ** #SDTREF(SDL,ping.spr(1),128(30,55),1) ------*/ ALLOC_SIGNAL_NPAR(PING, z02_PING, 0) SDL_OUTP_NPAR(xDefaultPrioSignal, PING, z02_PING, TO_PROCESS(PONG, z01_PONG), 0, "PING") /*----- ** NEXTSTATE - ** #SDTREF(SDL,ping.spr(1),131(30,70),1) ------*/ SDL_DASH_NEXTSTATE /*----- ** INPUT PONG_SAY_BYE_BYE ** #SDTREF(SDL,ping.spr(1),119(55,40),1) ------*/ case 2: XOS_TRACE_INPUT("PONG_SAY_BYE_BYE") /*----- ** STOP ** #SDTREF(SDL,ping.spr(1),122(55,55),1) ------*/ #ifdef XFREEVARS FREE_PROCESS_VARS #endif SDL_STOP } END_PAD(yPAD_z00_PING) } /*********************************************************** ** PROCESS PONG ** <<SYSTEM perf01/BLOCK B1>> ** #SDTREF(SDL,pong.spr(1),110(3,10),2) ************************************************************/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ** Tables for process PONG ** #SDTREF(SDL,pong.spr(1),110(3,10),2) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*--------------Instance Data---------------*/ #define X_MAX_INST_z01_PONG 1 static yVDef_z01_PONG yINSTD_z01_PONG[X_MAX_INST_z01_PONG]; /*--------------Process State---------------*/ static xSTATE yPSTATETBL_z01_PONG[X_MAX_INST_z01_PONG] = { XSTARTUP }; /*---------------State Index----------------*/ static XCONST xSITBL xSTATE_INDEX_z01_PONG[2] = {0, 1}; /*---------------Transition-----------------*/ #define XMAX_TRANS_z01_PONG 1 static XCONST xTR_TABLE_ENTRY yTRTBL_z01_PONG[XMAX_TRANS_z01_PONG] = { /* State1 */ z02_PING, 1 }; /*-----------Process-PID-Values-------------*/ #ifdef XMK_USE_PID_ADDRESSING static xPIDTable yPID_TBL_z01_PONG[X_MAX_INST_z01_PONG]; #endif /*-----------Process Description------------*/ #define X_PRIO_z01_PONG xDefaultPrioProcess XCONST XPDTBL yPDTBL_z01_PONG = { #ifdef XMK_USE_PID_ADDRESSING yPID_TBL_z01_PONG, #endif (xINSTD *)yINSTD_z01_PONG, sizeof(yINSTD_z01_PONG[0]), X_MAX_INST_z01_PONG, #ifdef XMK_USE_TIMESLICE X_TIMESLICE_z01_PONG, #endif #ifdef XMK_USE_PREEMPTIVE X_PRIO_z01_PONG, #endif (xmk_T_TRANS_ADDRESS) yPAD_z01_PONG, yTRTBL_z01_PONG, xSTATE_INDEX_z01_PONG, yPSTATETBL_z01_PONG }; /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ** Function for process PONG ** #SDTREF(SDL,pong.spr(1),110(3,10),2) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #ifndef XNOPROTO extern YPAD_RESULT_TYPE yPAD_z01_PONG( YPAD_ANSI_PARAM ) #else extern YPAD_RESULT_TYPE yPAD_z01_PONG( YPAD_KR_PARAM ) YPAD_KR_DEF #endif { YPAD_YSVARP YPAD_YVARP(yVDef_z01_PONG) YPAD_TEMP_VARS YPRSNAME_VAR("PONG") BEGIN_PAD switch (XSYMBOLNUMBER) { /*----- ** START ** #SDTREF(SDL,pong.spr(1),140(55,10),1) ------*/ case 0: BEGIN_START_TRANSITION xDef_SDL_Integer(&yVarP->z011_counter); /*----- ** TASK counter := ... ** #SDTREF(SDL,pong.spr(1),143(55,25),1) ------*/ #ifdef XTRACE xTraceTask("counter := ..."); #endif yAssF_SDL_Integer(yVarP->z011_counter, SDL_INTEGER_LIT(0), XASS); /*----- ** NEXTSTATE State1 ** #SDTREF(SDL,pong.spr(1),146(55,40),1) ------*/ SDL_NEXTSTATE(State1, z010_State1, "State1") /*----- ** INPUT PING ** #SDTREF(SDL,pong.spr(1),119(80,25),1) ------*/ case 1: XOS_TRACE_INPUT("PING") /*----- ** TASK counter := ... ** #SDTREF(SDL,pong.spr(1),122(80,40),1) ------*/ #ifdef XTRACE xTraceTask("counter := ..."); #endif yAssF_SDL_Integer(yVarP->z011_counter, xPlus_SDL_Integer(yVarP->z011_counter, SDL_INTEGER_LIT(1)), XASS); /*----- ** DECISION ** #SDTREF(SDL,pong.spr(1),125(80,55),1) ------*/ #ifdef XTRACE yAssF_SDL_Boolean(yDcn_SDL_Boolean, xGT_SDL_Integer(yVarP- >z011_counter, z05_MAXRUN), XASS); xTraceDecision(&(yDcn_SDL_Boolean), xSrtN_SDL_Boolean); if (yDcn_SDL_Boolean) { #else if (xGT_SDL_Integer(yVarP->z011_counter, z05_MAXRUN)) { #endif /*----- ** OUTPUT PONG_SAY_BYE_BYE ** #SDTREF(SDL,pong.spr(1),134(80,70),1) ------*/ ALLOC_SIGNAL_NPAR(PONG_SAY_BYE_BYE, z04_PONG_SAY_BYE_BYE, 0) SDL_OUTP_NPAR(xDefaultPrioSignal, PONG_SAY_BYE_BYE, z04_PONG_SAY_BYE_BYE, TO_PROCESS(PING, z00_PING), 0, "PONG_SAY_BYE_BYE") /*----- ** STOP ** #SDTREF(SDL,pong.spr(1),137(80,85),1) ------*/ #ifdef XFREEVARS FREE_PROCESS_VARS #endif SDL_STOP } else { /*----- ** OUTPUT PONG ** #SDTREF(SDL,pong.spr(1),128(105,70),1) ------*/ ALLOC_SIGNAL_NPAR(PONG, z03_PONG, 0) SDL_OUTP_NPAR(xDefaultPrioSignal, PONG, z03_PONG, TO_PROCESS(PING, z00_PING), 0, "PONG") /*----- ** NEXTSTATE - ** #SDTREF(SDL,pong.spr(1),131(105,85),1) ------*/ SDL_DASH_NEXTSTATE } } END_PAD(yPAD_z01_PONG) }
Parameter: xPID Process-PID
Return : xmk_T_STATE state-Value
(may also be XSTARTUP / XDORMANT)
#ifdef XMK_ANSI xmk_T_STATE xmk_GetProcessState ( xPID pid) #else xmk_T_STATE xmk_GetProcessState ( pid ) xPID pid; #endif
Return : -
#ifdef XMK_ANSI void xGetTimerState ( xmk_T_STATE *tinfo ) #else void xGetTimerState ( tinfo ) xPID pid; #endif
Return : -
#ifdef XMK_ANSI void xmk_GetQueueState ( xmk_Q_STATE *qinfo ) #else void xmk_GetQueueState ( qinfo ) xmk_Q_STATE *qinfo; #endif
Parameter : -
Return : -
int main ( int argc, char* argv[] ) #ifdef XMK_ANSI #ifdef XMK_USE_OS_ENVIRONMENT int main ( int argc, char* argv[] ) #else int main() #endif #endif
Parameter : -
Return : -
#ifdef XMK_ANSI void xInitEnv (void) #else void xInitEnv () #endif
Parameter : -
Return : -
#ifdef XMK_ANSI void xInEnv (void) #else void xInEnv () #endif
Note:
You have several possibilities to send signals to the Environment, see reference manual.
Parameter : sig, prio, dat_len, *p_data, Receiver
Return :
Function must return with TRUE, if Signal was sent to the environment, otherwise with FALSE.
#ifdef XMK_ANSI int xOutEnv ( xmk_T_SIGNAL sig, xmk_T_PRIO prio, unsigned char data_len, void *p_data, xPID Receiver ) #else int xOutEnv (sig, prio, data_len, p_data, Receiver) xmk_T_SIGNAL sig; xmk_T_PRIO prio; unsigned char data_len; void *p_data; xPID Receiver; #endif
Parameter : int ErrorNo - given error number (see header file ml_err.h)
Return : -
#ifdef XMK_ANSI void ErrorHandler ( int ErrorNo ) #else void ErrorHandler ( ErrorNo ) int ErrorNo; #endif
-------------------------------------------------------------------- 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 Ker nel). If the Cmicro Kernel is scaled preemptively, then the Watch dog Trigger should not be used, because the execution time of tran sitions can never be calculated. --------------------------------------------------------------------Parameter : void
Return : -
#ifdef XMK_ANSI void WatchdogTrigger ( void ) #else void WatchdogTrigger ( ) #endif
----------------------------------------------------- Caution! Do not integrate this function into the ErrorHandler! -----------------------------------------------------Parameter : int errnum - error number
Return : -
#ifdef XMK_ANSI void MemError ( int errnum ) #else void MemError ( errnum ) int errnum; #endif
Parameter : -
Return : -
#ifdef XMK_ANSI void xmk_InitSDL( void ) #else void xmk_InitSDL( ) #endif
Parameter :
CountSignals - amount of signals, which are to be processed in this function call, where 0xFF means endless processing.
Return :
NORMALRETURN - SDL-System not to be stopped. There are
processes living or the queue is not empty.
STOP - SDL-System is to be stopped, because there are no more process instances living and no signal to be worked on.
#ifdef XMK_ANSI int xmk_RunSDL (unsigned char CountSignals) #else int xmk_RunSDL (CountSignals) unsigned char CountSignals; #endif
Parameter : -
Return : -
#ifdef XMK_ANSI void xmk_StartProcesses( void ) #else void xmk_StartProcesses( ) #endif
Parameter : -
Return : -
#ifdef XMK_ANSI void xmk_ProcessSignal( void ) #else void xmk_ProcessSignal( ) #endif
Parameter : ProcessID - ID of the process type
Return :
ID of the newly created instance (0.... (NMax - 1)) OR xNULLINST if it was not possible to create a new instance
#ifdef XMK_ANSI xmk_T_INSTANCE xmk_CreateProcess( xmk_T_PROCESS ProcessTypeID ) #else xmk_T_INSTANCE xmk_CreateProcess( ProcessTypeID ) xmk_T_PROCESS ProcessTypeID ; #endif
Parameter : -
Return : TRUE - There is an active instance
FALSE - No active instances throughout the system
#ifdef XMK_ANSI T_BOOL xmk_IsAnyProcessAlive ( void ) #else T_BOOL xmk_IsAnyProcessAlive ( ) #endif
Parameter : -
Return : -
#ifdef XMK_ANSI void xmk_InitPreemptionVars ( void ) #else void xmk_InitPreemptionVars () #endif
Parameter : -
Return : -
#ifdef XMK_ANSI void xmk_DisablePreemption ( void ) #else void xmk_DisablePreemption () #endif
Parameter : -
Return : -
#ifdef XMK_ANSI void xmk_EnablePreemption( void ) #else void xmk_EnablePreemption() #endif
Parameter : -
Return : xmk_T_PRIOLEVEL highest prio-level, where a
signal exists.
#ifdef XMK_ANSI xmk_T_PRIOLEVEL xmk_FetchHighestPrioLevel ( void ) #else xmk_T_PRIOLEVEL xmk_FetchHighestPrioLevel () #endif
Parameter : -
Return : -
#ifdef XMK_ANSI void xmk_CheckIfSchedule( void ) #else void xmk_CheckIfSchedule() #endif
Parameter : xmk_T_PRIOLEVEL NewPrioLevel - next prio-level to deal with
Return : -
#ifdef XMK_ANSI void xmk_SwitchPrioLevel(xmk_T_PRIOLEVEL NewPrioLevel) #else void xmk_SwitchPrioLevel( NewPrioLevel ) xmk_T_PRIOLEVEL NewPrioLevel; #endif
Parameter : xPID Process-PID
Return : xmk_T_STATE state-Value
(may also be XSTARTUP / XDORMANT)
#ifdef XMK_ANSI xmk_T_STATE xmk_GetProcessState ( xPID pid) #else xmk_T_STATE xmk_GetProcessState ( pid ) xPID pid; #endif
Parameter : sig - Signal's code
Receiver - PID of the receiver-process
Return : -
#ifdef XMK_ANSI void xmk_SendSimple(xmk_T_SIGNAL sig, xPID Receiver) #else void xmk_SendSimple ( sig, Receiver ) xmk_T_SIGNAL sig; xPID Receiver; #endif
Parameter : sig- signal's code
prio- signal's priority
data_len- number of bytes of signal's parameter
p_data- pointer to dynamically allocated memory area
containing the signal's parameter (NULL if
parameter contained within signal)
Receiver- PID of the receiver-process
Return : -
#ifdef XMK_ANSI void xmk_Send(xmk_T_SIGNAL sig, xmk_T_PRIO prio, unsigned char data_len, void *p_data, xPID Receiver) #else void xmk_Send ( sig, prio, data_len, p_data, Receiver ) xmk_T_SIGNAL sig; xmk_T_PRIO prio; unsigned char data_len; void *p_data; xPID Receiver; #endif
Parameter : proc_type - process type to be checked for a receiver
Return : global PID of a found receiver, xNULLPID if none is found
#ifdef XMK_ANSI xPID xmk_Determine_Receiver ( unsigned char proc_type ) #else xPID xmk_Determine_Receiver ( proc_type ) unsigned char proc_type; #endif
Parameter : -
Return : -
#ifdef XMK_ANSI void xmk_InitQueue( void ) #else void xmk_InitQueue() #endif
Parameter : -
Return :
pointer to first signal in queue (NULL, if no signals in queue)
#ifdef XMK_ANSI xmk_T_MESSAGE* xmk_FirstSignal( void ) #else xmk_T_MESSAGE* xmk_FirstSignal( ) #endif
Parameter : -
Return :
Pointer to the next signal in the queue (NULL if no more signals in the queue)
#ifdef XMK_ANSI xmk_T_MESSAGE* xmk_NextSignal( void ) #else xmk_T_MESSAGE* xmk_NextSignal( ) #endif
Parameter : *p_Message - pointer to signal which is to be inserted
Return : -
#ifdef XMK_ANSI void xmk_InsertSignal( xmk_T_MESSAGE *p_Message ) #else void xmk_InsertSignal ( p_Message ) xmk_T_MESSAGE *p_Message ; #endif
Parameter : -
Return : -
#ifdef XMK_ANSI void xmk_RemoveCurrentSignal( void ) #else void xmk_RemoveCurrentSignal( ) #endif
Parameter : SignalID - signal code of the signals to be removed
Return : -
#ifdef XMK_ANSI void xmk_RemoveSignalBySignalID( xmk_T_SIGNAL SignalId ) #else void xmk_RemoveSignalBySignalID ( SignalId ) xmk_T_SIGNAL SignalId ; #endif
Parameter : ProcessId - PID of Process
Return : -
#ifdef XMK_ANSI void xmk_RemoveSignalsByProcessID( xPID ProcessID ) #else void xmk_RemoveSignalsByProcessID( ProcessID ) xPID ProcessID; #endif
Parameter : -
Return : Pointer to returned signal (NULL if there is none)
#ifdef XMK_ANSI xmk_T_MESSAGE* xmk_AllocSignal( void ) #else xmk_T_MESSAGE* xmk_AllocSignal( ) #endif
Parameter : *p_Message - Pointer to signal to be initialized
Return : -
#ifdef XMK_ANSI void xmk_FreeSignal( xmk_T_MESSAGE *p_Message ) #else void xmk_FreeSignal( p_Message ) xmk_T_MESSAGE *p_Message; #endif
Parameter : State - SAVE-state
Return :
TRUE - the given SAVE-state equals the signal's SAVE-state
FALSE - the given SAVE-state differs from the signal's
#ifdef XMK_ANSI T_BOOL xmk_TestAndSetSaveState( xmk_T_STATE State ) #else T_BOOL xmk_TestAndSetSaveState( State ) xmk_T_STATE State ; #endif
Parameter :
Return :
TRUE - No more signals in any queue
FALSE - There is a signal in any queue
#ifdef XMK_ANSI T_BOOL xmk_QueueEmpty ( void ) #else T_BOOL xmk_QueueEmpty ( ) #endif
Parameter : -
Return : -
#ifdef XMK_ANSI void xmk_InitTimer( void ) #else void xmk_InitTimer( ) #endif
This function activates an instance of a timer with the given "Signal-ID"-value and the given time.
Working principles:
Return : void
#ifdef XMK_ANSI void xmk_TimerSet( xmk_T_TIME time ,xmk_T_SIGNAL sid ) #else void xmk_TimerSet( time, sid ) xmk_T_TIME time ; xmk_T_SIGNAL sid ; #endif
Parameter : sid -ID of the timer signal which is produced at timer expiration.
Return : -
#ifdef XMK_ANSI void xmk_TimerReset( xmk_T_SIGNAL sid ) #else void xmk_TimerReset( sid ) xmk_T_SIGNAL sid ; #endif
Parameter : sid - ID of the timer signal which is produced at timer expiration.
Return :
TRUE - the timer is active in the current running process.
FALSE - the timer is not active in the current running process.
#ifdef XMK_ANSI T_BOOL xmk_TimerActive( xmk_T_SIGNAL sid ) #else T_BOOL xmk_TimerActive( sid ) xmk_T_SIGNAL sid ; #endif
Parameter : xPID pid - global Process-ID
Return : -
#ifdef XMK_ANSI void xmk_ResetAllTimer( xPID pid ) #else void xmk_ResetAllTimer( pid ) xPID pid; #endif
Parameter : int nr - Error Number
Return : Pointer to error text string
#ifdef XMK_ANSI char *xmk_err_text ( int nr ) #else char *xmk_err_text ( nr ) int nr ; #endif
Parameter : -
Return : -
#ifdef XMK_ANSI void xmk_InitSystime( void ) #else void xmk_InitSystime( ) #endif
Parameter : -
Return : -
#ifdef XMK_ANSI void xmk_DeinitSystime( void ) #else void xmk_DeinitSystime( ) #endif
Parameter : -
Return : -
#ifdef XMK_ANSI void xmk_SetTime( xmk_T_TIME time ) #else void xmk_SetTime( time ) xmk_T_TIME time ; #endif
Parameter : -
Return : current time
#ifdef XMK_ANSI xmk_T_TIME xmk_NOW ( void ) #else xmk_T_TIME xmk_NOW ( ) #endif
Parameter :
_mem_begin:
_mem_end:
Return : void
#ifdef XMK_ANSI void MemInit( char* _mem_begin, char* _mem_end ) #else void MemInit( _mem_begin, _mem_end ) char* _mem_begin; char* _mem_end; #endif
Parameter : rsize :
Return :
#ifdef XMK_ANSI void* malloc( unsigned long rsize ) #else void* malloc( rsize ) unsigned long rsize; #endif
Parameter : mem:
Return :
#ifdef XMK_ANSI void free( void *mem ) #else void free( mem ) void *mem; #endif
Parameter : RequestedSize:
Return :
#ifdef XMK_ANSI void* calloc( unsigned long RequestedSize ) #else void* calloc( RequestedSize ) unsigned long RequestedSize; #endif
Parameter :
pMemBlock:
NewSize :
Return :
#ifdef XMK_ANSI void memshrink( void *pMemBlock, unsigned long NewSize ) #else void memshrink(pMemBlock, NewSize ) void *pMemBlock ; unsigned long NewSize ; #endif
CAUTION:
Take care when the preemption policy is utilized.
#ifdef XMK_ANSI void memset ( char *p, char val, int length) #else void memset ( p, val, length) void *p; char val; int length; #endif
CAUTION:
Take care when the preemption policy is utilized.
#ifdef XMK_ANSI void memcpy ( char *dest, char *source, int length) #else void memcpy ( dest, source, length) char *dest; char *source; int length; #endif
Parameter : -
Return : -
#ifdef XMK_ANSI void _out( int pa , char v ) #else void _out( pa , v ) int pa ; char v ; #endif
Parameter : -
Return : -
#ifdef XMK_ANSI char _in( int pa ) #else char _in( pa ) int pa ; #endif
Parameter : -
Return : -
#ifdef XMK_ANSI void disable( void ) #else void disable( ) #endif
A Template to show how to enable interrupts (default for MS-DOS)
Parameter : -
Return : -
#ifdef XMK_ANSI void enable( void ) #else void enable( ) #endif
Parameter : -
Return : -
#ifdef XMK_ANSI void xxmonPID (char *ostring, xPID pid) #else void xmonPID (ostring, pid) char *ostring; xPID pid; #endif
Parameter : -
Return : -
#ifdef XMK_ANSI void xxmonhexsingle (char *p_text, unsigned char *p_adress, int length) #else void xxmonhexsingle (p_text, p_adress, length) char *p_text; unsigned char *p_adress; int length; #endif
Parameter : -
Return : -
#ifdef XMK_ANSI void xxmonhex (char *p_text, unsigned char *p_adress, int length) #else void xxmonhex (p_text, p_adress, length) char *p_text; unsigned char *p_adress; int length; #endif
Parameter : -
Return : -
#ifdef XMK_ANSI void xxmonconfig () #else void xxmonconfig () #endif
Table of Contents Next Chapter