Real-Time Workshop | ![]() ![]() |
Writing an Inlined S-Function Device Driver
To inline a device driver, you must provide:
driver
.c
: C MEX S-function source code, implementing the functions required by the S-function API. These are the same functions required for noninlined drivers, as described in Required Functions. For these functions, only the code for simulation in Simulink simulation is required.
driver
.c
does not attempt to read or write memory locations that are intended to be used in the target hardware environment. The real-time driver implementation, generated via a driver
.tlc
file, should access the target hardware.
mdlRTW
function within driver
.c
. The sole purpose of this function is to evaluate and format parameter data during code generation. The parameter data is output to the model
.rtw
file. If your driver block does not need to pass information to the code generation process, you do not need to write a mdlRTW
function. See mdlRTW and Code Generation .
driver
.dll
(PC) or driver
(UNIX): MEX-file built from your C MEX S-function source code. This component is used:
mdlRTW
function exists in the MEX-file, the code generator executes it to write parameter data to the model
.rtw
file.
driver
.tlc
: TLC functions that generate real-time implementations of the functions required by the S-function API.
Example: An Inlined ADC Driver
As an aid to understanding the process of inlining a device driver, this section describes an example driver block for an ADC device. Source Code for Inlined ADC Driver lists code for:
adc.c
, the C MEX S-function
adc.tlc
, the corresponding TLC file
device.h
, a hardware-specific header file included in both the simulation and real-time generated code
The driver
S-Function block is masked and has an icon. Figure 14-8 shows a model using the driver
S-Function block. Figure 14-9 shows the block's dialog box.
Figure 14-8: ADC S-function Driver Block in a Model
The dialog box lets the user enter:
Figure 14-9: ADC Driver Dialog Box
Simulation Code.. adc.c
consists almost entirely of functions to be executed during simulation. (The sole exception is mdlRTW
, which executes during code generation.) Most of these functions are similar to the examples of non-real-time code given in Writing a Noninlined S-Function Device Driver. The S-function implements the following functions:
mdlInitializeSizes
validates input parameters (via mdlCheckParameters
) and declares all parameters nontunable. This function also initializes ports and sets the number of sample times.
mdlInitializeSampleTimes
sets the sample time using the user-entered value.
mdlStart
prints a message to the MATLAB command window.
mdlOutputs
outputs zero on all channels.
mdlTerminate
is a stub routine.
Since adc.c
contains only simulation code, it uses a single test of MATLAB_MEX_FILE
to ensure that it is compiled as a C MEX-file.
#ifndef MATLAB_MEX_FILE
#error "Fatal Error: adc.c can only be used to create C-MEX S-Function"
#endif
For the same reason, adc.c
unconditionally includes simulink.c
.
mdlRTW and Code Generation. mdlRTW
is a mechanism by which an S-function can generate and write data structures to the model
.rtw
file. The Target Language Compiler, in turn, uses these data structures when generating code. Unlike the other functions in the driver, mdlRTW
executes at code generation time.
In this example, mdlRTW
calls the ssWriteRTWParamSettings
function to generate a structure that contains both user-entered parameter values (base address, hardware gain) and values computed from user-entered values (resolution, offset).
static void mdlRTW(SimStruct *S) { boolean_T polarity = adcIsUnipolar(MIN_SIGNAL_VALUE, MAX_SIGNAL_VALUE); real_T offset = polarity ? 0.0 : MIN_SIGNAL_VALUE/HARDWARE_GAIN; real_T resolution = (((MAX_SIGNAL_VALUE-MIN_SIGNAL_VALUE)/HARDWARE_GAIN)/ ADC_NUM_LEVELS); char_T baseAddrStr[128]; if ( mxGetString(BASE_ADDRESS_PARAM, baseAddrStr, 128) ) { ssSetErrorStatus(S, "Error reading Base Address parameter, " "need to increase string buffer size."); return; } if ( !ssWriteRTWParamSettings(S, 4, SSWRITE_VALUE_QSTR, "BaseAddress", baseAddrStr, SSWRITE_VALUE_NUM, "HardwareGain", HARDWARE_GAIN, SSWRITE_VALUE_NUM, "Resolution", resolution, SSWRITE_VALUE_NUM, "Offset", offset) ) { return; /* An error occured, which will be reported by Simulink. */ } } /* end: mdlRTW */
The structure defined in model
.rtw
is
(The actual values of SFcnParamSettings derive from data entered by the user.)
Values stored in the SFcnParamSettings structure are referenced in driver
.tlc
, as in the following assignment statement.
The Target Language Compiler uses variables such as baseAddr to generate parameters in real-time code files such as model
.c
and model
.h
. This is discussed in the next section.
Note
During code generation, RTW writes all runtime parameters automatically to the model .rtw file, eliminating the need for the device driver S-function to perform this task via a mdlRTW method. See the discussion of runtime parameters in Writing S-Functions for further information.
|
The TLC File
adc.tlc
contains three TLC functions. The BlockTypeSetup
function generates the statement
in the model
.h
file. The other two functions, Start
and Outputs
, generate code within the MdlStart
and MdlOutputs
functions of model
.c
.
Statements in adc.tlc
, and in the generated code, employ macros and symbols defined in device.h, and parameter values in the SFcnParamSettings structure. The following code uses the values from the SFcnParamSettings structure above to generate code containing constant values:
%assign baseAddr = SFcnParamSettings.BaseAddress %assign hwGain = SFcnParamSettings.HardwareGain ... adcSetHardwareGain(%<baseAddr>, adcGetGainMask(%<hwGain>));
The TLC code above generates this statement in the MdlOutputs
function of model
.c
.
adcSetHardwareGain and adcGetGainMask are macros that expand to low-level hardware calls.
S-Function Wrappers
Another technique for integrating driver code into your target system is to use S-function wrappers. In this approach, you write:
See Writing S-Functions for a full description of how to use wrapper S-functions.
![]() | Writing a Noninlined S-Function Device Driver | Building the MEX-File and the Driver Block | ![]() |