In R2014b, Simulink Functions got introduced. In this post, we highlighted how Simulink Functions can be used to create an Export-Function model. In this case, the Simulink Functions are placed inside a model. In simulation, you can reference the model and call the functions using the Function Caller block.
You can then generate code for the function library model and call those functions in any way you want from hand-written code.
One thing we did not mention at that time, is that it is possible to use Simulink Functions and the Function Caller block in completely opposite way, where the referenced model has a Function Caller block, calling Simulink Functions present in the top model.
Why would someone want to do that? In short, the answer is to simulate custom code that is not directly available for simulation. Let's see how this works.
Using the Function Caller block to call external code
If we generate code for the child codeGenModel.slx in the above picture model, the code will look like:
By default, this code would not build, since the compiler would not know where to find the function timesTwo. However, if you configure your model properly, the function timesTwo can come from anywhere you want. For example, it could be in a dynamic library against which you will link to on your embedded target. For this example, imagine that there is a timesTwo service available in this timesTwo.c file:
In the model configuration, I specify that this file should be included in the build process:
This allows me to generate an executable that calls my custom timesTwo.c implementation.
To summarize, the idea is to create a Simulink Function that emulates the behavior of external software. You can build a simulation harness model that references your code generation model and it will see the Simulink Function. When time comes to generate code for the child model, it will have no idea the Simulink Function exists, but instead will link against any external code you specify.
It is important to note that this technique is just one way to include custom code in the code generated from Simulink.
If the custom code was available on the host, I would recommend going with an S-Function to wrap and reuse the same custom code both in simulation and code generation.
However if the code is unavailable, for example because it is available as an OS service on the target embedded processor, this approach can be interesting.
Now that we have introduced the concepts of Export Function models, the State Reader and Writer blocks, and this way of using Simulink Functions, I believe we have all the pieces to make a realistic example illustrating how we see the Initialize Function, Reset Function and Terminate Function blocks being used... next week.