How can we generate code for a C-MEX S-Function using custom datatypes with Simulink Coder?
1 vue (au cours des 30 derniers jours)
Afficher commentaires plus anciens
MathWorks Support Team
le 22 Fév 2018
Modifié(e) : MathWorks Support Team
le 18 Avr 2023
I need to include custom data types in an S-Function and generate code using Simulink Coder. I use ssRegisterDataType to register the custom data type but it does not seem to be supported for code-generation. When I use the directive #if defined (MATLAB_MEX_FILE), the build is successful but I see the following warning:
Warning: Simulink Coder -- In block "MyDemo/S-Function", block type "S-Function": User-defined data type MyStruct is required for DWork 0, but the information needed to define this data type is unknown. The generated code that normally specifies the data type of this DWork is being omitted. If additional custom code does not register this user-define data type and set the data type of this DWork, then the generated code will be incomplete.
Are there any recommended steps for this workflow?
Réponse acceptée
MathWorks Support Team
le 18 Avr 2023
Modifié(e) : MathWorks Support Team
le 18 Avr 2023
It is not recommended to generate code for non-inlined S-Functions that register custom data types with Simulink Coder. It is most likely the cause of the generated warning.
While the MATLAB_MEX_FILE approach is a valid workaround for rapid accelerator simulations, it should not apply to stand-alone code generation. There can be multiple approaches to accomplish this:
INLINING THE S-FUNCTION:
Run this command in MATLAB 2016b for documentation:
>> web(fullfile(docroot, 'simulink/sfg/custom-data-types.html'))
Or,
for latest release documentation, please refer to:
To achieve your workflow, you would need to inline the S-Function with TLC, as suggested in the documentation note. It is not recommended to write this by hand, but using tools like the S-Function Builder, or Legacy Code Tool do it for you. For your use-case, you will likely need to use Legacy Code Tool since your workflow requires support for Dwork vectors of non-double type.
For code generation, you could treat the struct as a bus instead of a pure opaque data type. To achieve the following steps would be helpful:
1. Pull out the algorithm code from C S-Function's mdlOutputs and mdlInitializeConditions methods into C functions that Legacy Code Tool (LCT) can call.
(You can find more information about this if you work though the LCT demo linked after Step 3. The algorithm code is in counterbus.c).
2. Import that struct as a bus object:
>>Simulink.importExternalCTypes('MyStruct.h')
3. Use the bus name as the work vector data type in the Legacy Code Tool function prototype specification. Generate the S-Function and TLC with Legacy Code Tool.
We have a good example of using bus data types with legacy code tool here:
Run this command in MATLAB 2016b for documentation:
>> web(fullfile(docroot, 'simulink/examples/using-buses-with-legacy-functions-having-structure-arguments.html'))
Additionally, the following documentation gives a nice list of all the different ways you can declare your function prototypes:
Run this command in MATLAB 2016b for documentation:
>> web(fullfile(docroot, 'simulink/sfg/integrating-existing-c-functions-into-simulink-models-with-the-legacy-code-tool.html'))
Or,
for latest release documentation, please refer to:
NON-INLINED S-FUNCTION
: Declare an instance of MyStruct and set the width of the dWork element to the size of that struct instance with a byte-size datatype.
With this approach, you wouldn't need to register the custom data type with the Simulink engine at all or include the header in the model custom code section (if you really only use this struct type inside the S-Function). You can get rid of all the #ifdef MATLAB_MEX_FILE stuff in mdlinitializesizes and just write this:
static void mdlInitializeSizes(SimStruct *S)
{
/* set up dwork */
ssSetNumDWork(S,1);
ssSetDWorkWidth(S, 0, sizeof(MyStruct));
ssSetDWorkDataType(S, 0, SS_UINT8);
/* rest of mdlInitializeSizes */
...
Then when you get the DWork vector, you can cast it to (MyStruct *) and treat it like the struct. sizeof includes any necessary padding bytes so there should not be any problems treating the byte array as a structure and accessing the fields via dot/arrow notation.
0 commentaires
Plus de réponses (0)
Voir également
Catégories
En savoir plus sur Simulink Coder dans Help Center et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!