Structure of Device Driver System Object
A device driver block is a specialized form of the MATLAB System block that generates custom C/C++ code when deployed to an ARM® Cortex®-A based hardware board. Creating device driver blocks, provides users easy access to features of hardware boards, such as communication protocols or hardware libraries, that are not available in the support package.
A Simulink® device driver block can be generalized to one of two groups based on their port types:
Source blocks have output ports only. In simulation, a source block outputs a predetermined signal. This signal can be created from a random number generator, a stored array, or a constant value. After code generation, the source block outputs data captured from the I/O device that the block represents. For example, the generated code of the digital read block outputs the logical state of the digital I/O pin.
Sink blocks have input ports only. In simulation, a sink block acts as a Terminator block. After code generation, the sink block sets and updates the I/O device according to the input port signals. For example, the generated code of the digital write block sets and updates the logical state of the digital I/O pin equal to the input port signal.
To define the behavior of the device driver block, you use a System object™. Then you use a MATLAB System (Simulink) block to reference the object and
include it in a model. Each System object uses the setupImpl
, stepImpl
, and
releaseImpl
methods to define the code initialization, pin output
behavior, and code termination for the device driver block. Through conditional statements in
the stepImpl
, the device driver block operates in simulation mode. This mode
enables the entire model to run on the host computer either when testing or when you do not
have access to a hardware board. System objects also provide services for adding build
artifacts. Such artifacts include source files, include paths, shared libraries, and
preprocessor defines, to the Simulink generated code. These artifacts automatically define the port properties of a
block and generate a block mask.
Class Definition
At the top of the System object code, you define the name of your System object and the classes it inherits from.
classdef classname < matlab.System & coder.ExternalDependency & matlab.system.mixin.Propagates ... end
All System objects must inherit from matlab.System
. In addition, device
driver System object inherit from coder.ExternalDependency
, which provides APIs to
add build artifacts to generated code. The matlab.system.mixin.Propagates
class provides APIs to define the output size, data type, and complexity of a System object. You can inherit from additional classes, for example
matlab.system.mixin.CustomIcon
. Use this class to specify the name and
icon shown on the MATLAB System (Simulink) block.
Constructor Method
The template System object class, used in the Create a Digital Write Block and Create a Digital Read Block guides, uses a standard constructor method:
methods % Constructor function obj = classname(varargin) coder.allowpcode('plain'); setProperties(obj,nargin,varargin); end ... end
Initialization, Output and Termination Methods
These methods define what happens at initialization, output, and termination. Use
setupImpl
to initialize the hardware peripheral. Use
stepImpl
to read from or write to the hardware peripheral. Use
releaseImpl
to release hardware resources used. These three methods are
the backbone of defining the behavior of a device driver block.
methods (Access=protected) function setupImpl(obj) % Implement tasks that need to be performed only once end function stepImpl(obj,u) % Device driver output end function releaseImpl(obj) % Termination code end end
Input and Output Signal Properties
This code section defines the number of inputs or outputs of a block and the data types
and sizes. For example, the getNumInputsImpl
method in a sink block, sets
the number of input ports. Similarly, the getNumOutputsImpl
method in a
source block sets the number of outputs ports.
methods (Access=protected) % Simulink functions function isInputSizeMutableImpl(~,~) flag = false; end ... function num = getNumInputsImpl(~) num = 1; end function num = getNumOutputsImpl(~) num = 0; end end
Build Artifacts
The build artifacts define the source file locations, include paths, shared libraries,
library search paths, and preprocessor definitions required to compile the device driver
code. Use the getDescriptiveName
method to define an identification string
to the System object. The code generation engine uses this string to report errors. Use the
isSupportedContext
method to specify the code generation context. In
device driver blocks, only the real-time workshop (rtw) code generation context applies, so
this function always specifies 'rtw'
. Use the
updateBuildInfo
method to specify source and header files, include
paths, libraries, and defines required to build the System object.
methods (Static)
function name = getDescriptiveName()
name = 'decriptive name
';
end
function tf = isSupportedContext(context)
tf = context.isCodeGenTarget('rtw');
end
function updateBuildInfo(buildInfo, context)
if context.isCodeGenTarget('rtw')
% Update buildinfo
srcDir = fullfile(fileparts(mfilename('fullpath')),'src'); %#ok<NASU>
includeDir = fullfile(fileparts(mfilename('fullpath')),'include');
addIncludePaths(buildInfo,includeDir);
% Use the following API's to add include files, sources and
% linker flags
%addIncludeFiles(buildInfo,'source.h',includeDir);
%addSourceFiles(buildInfo,'source.c',srcDir);
%addLinkFlags(buildInfo,{'-lSource'});
%addLinkObjects(buildInfo,'sourcelib.a',srcDir);
%addCompileFlags(buildInfo,{'-D_DEBUG=1'});
%addDefines(buildInfo,'MY_DEFINE_1')
end
end