Guy on Simulink

Simulink & Model-Based Design

My Introduction to Embedded Coder 7

Posted by Guy Rouleau,

This week, I want to share the example which helped me, a long time ago, to get started with Embedded Coder. For readers who never used it, I hope this example will be as useful for you as it has been for me.

The Problem

If you ask me what is the difference between Simulink Coder and Embedded Coder, I would tell you that Simulink Coder allows you to generate code from a Simulink model, and Embedded Coder allows you to configure how the code looks like.

To illustrate that, we will start with a simple hand-written program, and see how to configure a model so that the code generated from it integrates without modification.

In this simple main, at every second, the program reads data from a text file and stores it in a global variable u. We want our auto-generated code to access this variable, and use it to compute value of another global variable y to be used later in the code.

pseudo code of the main application

Configuring the Model

For this example, let's use the following simple model:.

the Model

By default, if we generate code for this model we get something that looks like:

Default code generated form the model

It is obvious that modifications are necessary to map the values of u and y in the hand-written code to the input and output of the generated code.

To configure the look of the code, the first step is to name the input signal u and the output y. Then we need to tell Embedded Coder that u and y are external variables, already defined outside of the generated code, in the hand-written code.

For that, right-click on the signal line and select Properties:

Opening Signal Properties

Go to the Code Generation tab, and set the storage class to ImportedExtern (Note that the storage class and a lot more could also have been specified using a data object).

Signal Properties

Generated Code

Generate code for the model, and you should get something which looks like this:

Generated Code for the Step Function

Where u and y are declared as extern:

Extern Declaration

With this modification, the generated code integrates in the hand-written application, I can build the main program without errors.

Now it's your turn

There are many of ways to customize the code generated by Embedded Coder. This example is probably the simplest one possible, but I hope this gives you a good idea of how to get started. Let us know how you got started with the coders by leaving a comment here.

7 CommentsOldest to Newest

Han Geerligs replied on : 1 of 7

Hello Guy,

I was wondering whether it is possible to use Simulink Coder to obtain the same integration?

regards, Han

Anup replied on : 2 of 7

Hello Guy,
I tried code generation for your sample model and although I do not have Embedded Coder installed, I get the same results with Simulink Coder.

 23   /* Model step function */
   24   void GSModel_step(void)
   25   {
   26     /* Sum: '/Sum' incorporates:
   27      *  Gain: '/Gain'
   28      *  Gain: '/Gain1'
   29      *  Inport: '/u'
   30      *  UnitDelay: '/Unit Delay'
   31      */
   32     y = 0.1 * u + 0.9 * y;
   33   }

with u,y defined as externs in the _private.h file

24   /* Imported (extern) block signals */
   25   extern real_T y;                       /* '/Sum' */
   26   extern real_T u;                       /* '/u' */

Also when I use datastore read and write instead of the input and output ports and by defining appropriate Simulink.Signal objects in the workspace, I automatically get the inputs and outputs as externs in the Model.h file and the Model.cpp file code is very similar (with the exception of the DSTATE for unit delay, why does it not show up in yours?)

   30   /* Model step function */
   31   void SimpleModel_step(void)
   32   {
   33     real_T rtb_Sum;
   34   
   35     /* Sum: '/Sum' incorporates:
   36      *  DataStoreRead: '/Data Store Read'
   37      *  Gain: '/Gain'
   38      *  Gain: '/Gain1'
   39      *  UnitDelay: '/Unit Delay'
   40      */
   41     rtb_Sum = 0.1 * U + 0.9 * SimpleModel_DW.UnitDelay_DSTATE;
   42   
   43     /* DataStoreWrite: '/Data Store Write' */
   44     Y = rtb_Sum;
   45   
   46     /* Update for UnitDelay: '/Unit Delay' */
   47     SimpleModel_DW.UnitDelay_DSTATE = rtb_Sum;
   48   }
   49   

Seems like similar output is possible without the use of Embedded Coder, is that correct?

Regards,
Anup.
ps – your blogs are awesome and very useful

Paul replied on : 3 of 7

Hi,
I’m also interested in the differences between these two products. Is there any feature matrix available that I can use to help understand the differences?
It seems like some of those features (integration of generated code with external code) would be useful to people doing desktop/host application development as well, not just embedded systems running standalone.
I look forward to more posts on this topic.

Guy Rouleau replied on : 4 of 7

Thanks all for the comments. The simple storage classes I used are indeed provided with Simulink Coder. These are useful for basic integration tasks like the one illustrated. More advanced classes involving bitfields or get/set access methods are provided by Embedded Coder. Embedded Coder also lets you specify memory/pragma placement of your data.

Based on the interest for this topic, I will try to follow up with related posts.

Vikram replied on : 5 of 7

Thanks for the differences mentioned above. There is an option called as Matfile logging (In interfaces tab under code generation menu in configuration parameters). Unchecking that option in simulink coder yields the same result as we have got in embedded coder. (Note: But in embedded coder by default the Matfile logging option is unchecked). Please tell if any other advantages in code if we use embedded coder. Whether embedded coder is used for only stand-alone code generation??

Fred replied on : 6 of 7

How do you prevent Embedded Coder from checking ranges and modifying values? I want values to overflow. This is really annoying. The if/else is doing just this.

tmp = (real_T)CurrentRead / 3.7854117 * (real_T)qY * 120.0;
if (tmp < 4.294967296E+9) {
Flow = (uint32_T)tmp;
} else {
Flow = MAX_uint32_T;
}

Tsuki replied on : 7 of 7

hi, i am currently doing some project with TI C6000 series hardware, and i want to let my simulink modell able to change some parameter of specific block according to the message it get through UDP.(like ADC so it can change its sample per frame for different cases)

I think it is a good idea to use variable to do this, maybe u can help me with that?

Add A Comment

Your email address will not be published. Required fields are marked *

*

Preview: hide