Main Content

Convert Level-1 C MEX S-Functions

Guidelines for Converting Level-1 C MEX S-Functions to Level-2

Level-2 S-functions were introduced with Simulink® version 2.2. Level-1 S-functions refer to S-functions that were written to work with Simulink version 2.1 and previous releases. Level-1 S-functions are compatible with Simulink version 2.2 and subsequent releases; you can use them in new models without making any code changes. However, to take advantage of new features in S-functions, Level-1 S-functions must be updated to Level-2 S-functions. Here are some guidelines:

  • Start by looking at matlabroot/toolbox/simulink/blocks/src/sfunctmpl_doc.c. This template S-function file concisely summarizes Level-2 S-functions.

  • At the top of your S-function file, add this define:

    #define S_FUNCTION_LEVEL 2
    
  • Update the contents of mdlInitializeSizes. In particular, add the following error handling for the number of S-function parameters:

    ssSetNumSFcnParams(S, NPARAMS); /*Number of expected parameters*/
    if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
    	/* Return if number of expected != number of actual parameters */
      	return;
    }
    Set up the inputs using: 
    if (!ssSetNumInputPorts(S, 1)) return; /*Number of input ports */
    ssSetInputPortWidth(S, 0, width);      /* Width of input 
                                              port one (index 0)*/ 
    ssSetInputPortDirectFeedThrough(S, 0, 1); /* Direct feedthrough
                                                 or port one */
    ssSetInputPortRequiredContiguous(S, 0);
    Set up the outputs using:
    if (!ssSetNumOutputPorts(S, 1)) return;
    ssSetOutputPortWidth(S, 0, width);     /* Width of output port
                                              one (index 0) */
    
  • If your S-function has a nonempty mdlInitializeConditions, update it to the following form:

    #define MDL_INITIALIZE_CONDITIONS
    static void mdlInitializeConditions(SimStruct *S)
    {
    }
    

    Otherwise, delete the function.

    • Access the continuous states using ssGetContStates. The ssGetX macro has been removed.

    • Access the discrete states using ssGetRealDiscStates(S). The ssGetX macro has been removed.

    • For mixed continuous and discrete state S-functions, the state vector no longer consists of the continuous states followed by the discrete states. The states are saved in separate vectors and hence might not be contiguous in memory.

  • The mdlOutputs prototype has changed from

    static void mdlOutputs( real_T *y, const real_T *x, 
    	const real_T *u, SimStruct *S, int_T tid)
    

    to

    static void mdlOutputs(SimStruct *S, int_T tid)
    

    Since y, x, and u are not explicitly passed in to Level-2 S-functions, you must use

    • ssGetInputPortSignal to access inputs

    • ssGetOutputPortSignal to access the outputs

    • ssGetContStates or ssGetRealDiscStates to access the states

  • The mdlUpdate function prototype has changed from

    void mdlUpdate(real_T *x, real_T *u, Simstruct *S, int_T tid)
    

    to

    void mdlUpdate(SimStruct *S, int_T tid)
    
  • If your S-function has a nonempty mdlUpdate, update it to this form:

    #define MDL_UPDATE
    static void mdlUpdate(SimStruct *S, int_T tid)
    {
    }
    

    Otherwise, delete the function.

  • If your S-function has a nonempty mdlDerivatives, update it to this form:

    #define MDL_DERIVATIVES
    static void mdlDerivatives(SimStruct *S)
    {
    }
    

    Otherwise, delete the function.

  • Replace all obsolete SimStruct macros. See Obsolete Macros for a complete list of obsolete macros.

  • When converting Level-1 S-functions to Level-2 S-functions, you should build your S-functions with full (i.e., highest) warning levels. For example, if you have gcc on a UNIX®1 system, use these options with the mex utility.

    mex CC=gcc CFLAGS=-Wall sfcn.c
    

    If your system has Lint, use this code.

    lint -DMATLAB_MEX_FILE -I<matlabroot>/simulink/include 
        -Imatlabroot/extern/include sfcn.c 
    

    On a PC, to use the highest warning levels, you must create a project file inside the integrated development environment (IDE) for the compiler you are using. Within the project file, define MATLAB_MEX_FILE and add

    matlabroot/simulink/include 
    matlabroot/extern/include 
    

    to the path (be sure to build with alignment set to 8).

Obsolete Macros

The following macros are obsolete. Replace each obsolete macro with the macro specified in the following table.

Obsolete MacroReplace with
ssGetU(S), ssGetUPtrs(S)ssGetInputPortSignalPtrs(S,port), ssGetInputPortSignal(S,port)
ssGetY(S)ssGetOutputPortRealSignal(S,port)
ssGetX(S)ssGetContStates(S), ssGetRealDiscStates(S)
ssGetStatus(S) Normally not used, but ssGetErrorStatus(S) is available.
ssSetStatus(S,msg) ssSetErrorStatus(S,msg)
ssGetSizes(S) Specific call for the wanted item (i.e., ssGetNumContStates(S))
ssGetMinStepSize(S)No longer supported
ssGetPresentTimeEvent(S,sti)ssGetTaskTime(S,sti)
ssGetSampleTimeEvent(S,sti)ssGetSampleTime(S,sti)
ssSetSampleTimeEvent(S,t)ssSetSampleTime(S,sti,t)
ssGetOffsetTimeEvent(S,sti)ssGetOffsetTime(S,sti)
ssSetOffsetTimeEvent(S,sti,t)ssSetOffsetTime(S,sti,t)
ssIsSampleHitEvent(S,sti,tid) ssIsSampleHit(S,sti,tid)
ssGetNumInputArgs(S) ssGetNumSFcnParams(S)
ssSetNumInputArgs(S, numInputArgs)ssSetNumSFcnParams(S,numInputArgs)
ssGetNumArgs(S)ssGetSFcnParamsCount(S)
ssGetArg(S,argNum)ssGetSFcnParam(S,argNum)
ssGetNumInputsssGetNumInputPorts(S) and ssGetInputPortWidth(S,port)
ssSetNumInputsssSetNumInputPorts(S,nInputPorts) and ssSetInputPortWidth(S,port,val)
ssGetNumOutputsssGetNumOutputPorts(S) and ssGetOutputPortWidth(S,port)
ssSetNumOutputsssSetNumOutputPorts(S,nOutputPorts) and ssSetOutputPortWidth(S,port,val)

See Also

| | |

Related Topics


1 UNIX is a registered trademark of The Open Group in the United States and other countries.