Select Page

Graphical object-oriented C programs with Simulink

Simulink scripts generated from header files

Author: Dr. Hartmut Schorrig, Vishia

Contribution – Embedded Software Engineering Congress 2017

This article demonstrates the application of graphical programming in a MATLAB-Simulink environment. It utilizes core modules in so-called S-functions, which are programmed in C. The advantage of this approach is twofold: firstly, low-level layers and operating system interfaces can be directly formulated in C; secondly, the core module calls are reflected in the code generated by Simulink, simplifying code navigation and long-term maintenance. The article aims to introduce developers accustomed to primarily line-oriented programming to the benefits of graphical programming and the ease of integrating existing code.

Object-oriented programming in Simulink

While Simulink traditionally employs a highly modular approach, object-oriented programming is not. Object-oriented programming is associated with C and thus permeates Simulink models, extending even to the generated code of the implementation platform. Object-oriented programming means placing the data at the center of consideration. Operations (methods) interact with this data. At the Simulink level, S-functions serve this purpose. Object-FB and as Operation FB. (FB=Function BlockThe object function block contains the data and delivers it to the associated function blocks via a Handle. The handle is directly the memory address in the 32-bit target system, and an index in Simulink.

The image (see Figure 1, PDFThe image shows a Simulink model. The blocks are internally S-functions in C, but here some are already represented in Simulink as... For-Each-Subsystem For processing multiple parallel values, the data is processed as a vector. Therefore, the higher-level data organization no longer needs to be programmed in C, but is handled by automatic code generation. The data aggregation shown in the image on the right, similar to a Simulink bus, is also an S-function in C. Here, additional mechanisms such as swapping buffers or mutexes can be implemented. The sample time assignments are color-coded in the image. Certain calculations are executed in a fast interrupt in the real-time system, while others run in threads. Simulink generates a separate routine for each sample time during code generation, which can then be integrated accordingly.

Inheritance and abstraction

Object-oriented programming includes the ability to connect derived classes with abstract operations. When connecting blocks in Simulink via initially uniform, typed handles (uint32), type correctness is checked when the model is started. This type check is then no longer included in the generated code for the target system; it is assumed that the model has already been tested at the Simulink level. The type check allows the provision of a handle from a derived object function block to a base class operation function block. The operation function block thus initially works only with the basic data. Multiple inheritance is not supported, similar to Java. Late binding of operations at runtime can be achieved in C using... FunctionPointer This can also be implemented. This allows an operation function block (FB) of a base class to call the operation at runtime as defined in the derived class. In C++, these are the familiar virtual methods. This is useful at the Simulink level, for example, when data needs to be retrieved in one module and then provided independently in another module, perhaps using a derived object function block.

A comparison with UML

UML is a suitable tool for representing software structures and automatically generating the frameworks of C code. Simulink goes further in code generation. It is more focused on functionality than design. With this Simulink concept, a class is represented as an Object FB in its instantiation. Aggregations are reversed in the arrow direction, not directed towards the class being used, but rather as a provision of the aggregation towards the class using it. Operations are represented by separate boxes, drawn in the order of their invocation. Operations are therefore not created here, but called. The creation takes place in C, which may have been generated with a UML tool. Data is encapsulated within the Object FB and thus... private.

Generation of the S-Function wrapper and TLC files for Simulink

Simulink offers built-in tools for embedding C code into models. However, these are geared towards larger units, requiring some effort per S-function. When there are a large number of core C modules, as shown here, this is no longer optimal. Therefore, the author developed a generator that automatically creates the S-function call wrappers required by Simulink, as well as the so-called tlc files for Simulink code generation, from information in the C header files. Existing C source code can easily be adapted for this system.

In header files, structures and function prototype declarations are supplemented with comments containing annotations. Specific naming conventions apply to the arguments in the prototype declarations. The following example illustrates this:

/**Internal data of an OrthogonalOscillator.

 * @simulink no-bus

 */

typedef struct OrthOsc2_FB_t

{

  ObjectJc obj; //:The base structure

  Param_OrthOsc2_FB* par; //:Reference to parameters

  Angle_abwmf_FB* anglep; //:Reference to angle, null is ok

  float . . . //internal data

} OrthOsc2_FB;

/**The constructor. @simulink ctor */

OrthOsc2_FB* ctor_OrthOsc2_FB(ObjectJc* othiz, int32 identObj,

 float k1, float Tstep);

/**Prepares the instance data.

 * @param par aggregation to the parameter.

 * @param angular aggregation to angular source.

 * @simulink init

 */

char const* init_OrthOsc2_FB(OrthOsc2_FB* thiz, float

  Param_OrthOsc2_FB* par, Angle_FB* angle, float k2_param);

/**Step routine.

 * @param xAdiff Difference...

 * @param yaz_y variable to store the a-Output.

 * @param ab_Y variable to store the orthogonal output..

 * @simulink Object-FB, accel-tlc

 */

void step_OrthOsc2_FB(OrthOsc2_FB* thiz, float xAdiff,

 float* yaz_y, float_complex* ab_y);

The struct definition can be generated as a Simulink bus, but not here (no-bus). The constructor is always executed in the start phase of the S-function. Memory allocation is automatically generated using malloc, but can also be adjusted in the generation script. The Tstep argument determines the sampling time. Otherwise, the sampling time of an S-function also depends on the signal sources. All arguments of the constructor are in Simulink. non-tunable-Parameters of the S-function.

The init routine (@simulink init) is scheduled for a specific sampling time and is only called initially at the start of the run phase. It is responsible for aggregating the function block (FB) with other FBs; the non-numeric pointer types are either handles or buses (suffix _bus). This routine can also accept arguments with the suffix _param as non-tunable-Parameters or numerical inputs can be used as constant settings.

The routines, apart from the ctor, can return a text error message that is displayed as an error in Simulink and leads to the termination of the simulation.

The C routine marked with @simulink=Object-FB or …Operation-FB determines the S-function. Numeric scalar arguments or pointers are input or output, also as vectors. Outputs must be pointers and end with _y or _ybus. Arguments ending with _param are used for the S-function. tunable-Parameters. In code generation, such parameters can be grouped in a separate structure and can then be changed externally in the target system.

For one or two unchanged user functions, the minor effort of adding an inline wrapper in the header will be necessary. It is important that data in struct In summary, this is the key to formulating object orientation in C.

Observation tool in simulation run and for the target system: Inspector

Simulink allows the observation of all signals in the models using various methods such as scopes, data logging, or direct online display via "yellow boxes." This does not apply to the C-implemented data itself, unless it is externally accessible. To remedy this, the data can be processed with a Inspector Data can be retrieved via socket communication or symbolically assigned to outputs in the model. This is based on data access in C structures via a reflection mechanism. For reflection access, const data in C is generated from the struct header files, containing the name, type, and position of the data within the structures. A Service Inspc service then executes the access. This system is available for Simulink but can also be used on the target system to access all or relevant data.

Download the article as a PDF


Implementation – our training & coaching

Do you want to bring yourself up to date with the latest technology?

Then find out more here MircoConsult offers training courses/seminars/workshops and individual coaching on the topic of implementation/embedded and real-time software development.

Training & coaching on the other topics in our portfolio can be found here. here.


Implementation – Expertise

Valuable expertise in the field of implementation/embedded and real-time software development is available. here Available for you to download free of charge.

To the specialist information

You can find expertise on other topics in our portfolio here. here.

MicroConsult Newsletter

With the MicroConsult newsletter, you'll stay on the pulse of the embedded world. Look forward to proven practical knowledge, real professional tips, and current events – directly from our experts for your project success.

Subscribe now!

Published by

weissblau media

weissblau media